1import * as Cloudflare from "@/Cloudflare";
2import * as Provider from "@/Provider";
3import * as Test from "@/Test/Alchemy";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8
9const { test } = Test.make({ providers: Cloudflare.providers() });
10
11const logLevel = Effect.provideService(
12 MinimumLogLevel,
13 process.env.DEBUG ? "Debug" : "Info",
14);
15
16// A freshly minted scoped token propagates eventually-consistently across
17// Cloudflare's edge — retry the typed `Forbidden` blips on out-of-band calls.
18const forbiddenRetrySchedule = Schedule.exponential("500 millis");
19
20const retryForbidden = <A, E extends { _tag: string }, R>(
21 effect: Effect.Effect<A, E, R>,
22) =>
23 effect.pipe(
24 Effect.retry({
25 while: (e) => e._tag === "Forbidden",
26 schedule: forbiddenRetrySchedule,
27 times: 8,
28 }),
29 );
30
31// `list()` fans out over account BYOIP IP prefixes (the read-only catalog
32// endpoint, available regardless of the BYOIP entitlement) and pages the BGP
33// prefixes under each. On an account with no onboarded BYOIP prefixes the
34// result is naturally an empty `BgpPrefixAttributes[]` — the exact
35// shape `read` produces. This exercises the distilled wiring live on every run
36// without requiring the BYOIP contract/entitlement.
37test.provider(
38 "list enumerates BGP prefixes across BYOIP prefixes",
39 (stack) =>
40 Effect.gen(function* () {
41 yield* stack.destroy();
42
43 const provider = yield* Provider.findProvider(
44 Cloudflare.Addressing.BgpPrefix,
45 );
46 const all = yield* retryForbidden(provider.list());
47
48 expect(Array.isArray(all)).toBe(true);
49 for (const p of all) {
50 expect(typeof p.bgpPrefixId).toBe("string");
51 expect(typeof p.prefixId).toBe("string");
52 expect(typeof p.accountId).toBe("string");
53 expect(typeof p.cidr).toBe("string");
54 expect(typeof p.onDemand.advertised).toBe("boolean");
55 }
56
57 yield* stack.destroy();
58 }).pipe(logLevel),
59 { tags: ["provider:cloudflare", "provider:cloudflare:addressing", "live"] },
60);