1import * as Cloudflare from "@/Cloudflare";
2import { CloudflareEnvironment } from "@/Cloudflare/CloudflareEnvironment";
3import * as Provider from "@/Provider";
4import * as Test from "@/Test/Alchemy";
5import { expect } from "alchemy-test";
6import * as Effect from "effect/Effect";
7import { MinimumLogLevel } from "effect/References";
8import * as Schedule from "effect/Schedule";
9
10const { test } = Test.make({ providers: Cloudflare.providers() });
11
12const logLevel = Effect.provideService(
13 MinimumLogLevel,
14 process.env.DEBUG ? "Debug" : "Info",
15);
16
17// The scoped API token the harness mints propagates eventually-consistently
18// across Cloudflare's edge — ride out mid-deploy 403 blips.
19const retryAuthBlip = <A, E, R>(eff: Effect.Effect<A, E, R>) =>
20 eff.pipe(
21 Effect.retry({
22 while: (e) => String(e).includes("Unable to authenticate request"),
23 schedule: Schedule.exponential("1 second"),
24 times: 5,
25 }),
26 );
27
28test.provider(
29 "list enumerates the deployed pipeline stream",
30 (stack) =>
31 Effect.gen(function* () {
32 const { accountId } = yield* yield* CloudflareEnvironment;
33
34 yield* stack.destroy();
35
36 const deployed = yield* retryAuthBlip(
37 stack.deploy(Cloudflare.Pipelines.Stream("ListStream", {})),
38 );
39 expect(deployed.streamId).toBeTruthy();
40
41 const provider = yield* Provider.findProvider(
42 Cloudflare.Pipelines.Stream,
43 );
44 const all = yield* provider.list();
45
46 // Exhaustively-paginated result contains the deployed stream, hydrated
47 // into the exact `read` Attributes shape.
48 const found = all.find((s) => s.streamId === deployed.streamId);
49 expect(found).toBeTruthy();
50 expect(found?.accountId).toEqual(accountId);
51 expect(found?.name).toEqual(deployed.name);
52 expect(found?.httpEnabled).toEqual(deployed.httpEnabled);
53
54 yield* stack.destroy();
55 }).pipe(logLevel),
56 {
57 tags: ["provider:cloudflare", "provider:cloudflare:pipelines", "live"],
58 timeout: 300_000,
59 },
60);