| 1 | import { normalizeTransferredFrom } from "@/Cloudflare/Workers/DurableObject.ts"; |
| 2 | import { Worker } from "@/Cloudflare/Workers/Worker.ts"; |
| 3 | import { |
| 4 | Platform, |
| 5 | type PlatformIdentity, |
| 6 | type PlatformProps, |
| 7 | } from "@/Platform.ts"; |
| 8 | import type { Resource } from "@/Resource.ts"; |
| 9 | import type { BaseRuntimeContext } from "@/RuntimeContext.ts"; |
| 10 | import { expect, test } from "alchemy-test"; |
| 11 | import * as Effect from "effect/Effect"; |
| 12 | |
| 13 | interface TestProps extends PlatformProps { |
| 14 | env?: Record<string, string>; |
| 15 | } |
| 16 | interface TestResource extends Resource< |
| 17 | "Test.PlatformIdentity", |
| 18 | TestProps, |
| 19 | {} |
| 20 | > {} |
| 21 | |
| 22 | const identity = <const Id extends string>( |
| 23 | declaration: PlatformIdentity<Id>, |
| 24 | ): Id => declaration.LogicalId; |
| 25 | |
| 26 | test( |
| 27 | "Platform declarations expose their logical id without evaluating effects", |
| 28 | () => { |
| 29 | const TestPlatform: Platform<TestResource, never, {}, BaseRuntimeContext> = |
| 30 | Platform<TestResource>("Test.PlatformIdentity", { |
| 31 | createRuntimeContext: () => { |
| 32 | throw new Error("Reading identity must not create a runtime context"); |
| 33 | }, |
| 34 | }); |
| 35 | const props = Effect.sync(() => { |
| 36 | throw new Error("Reading identity must not evaluate props"); |
| 37 | }); |
| 38 | const impl = Effect.sync(() => { |
| 39 | throw new Error("Reading identity must not evaluate the implementation"); |
| 40 | }); |
| 41 | |
| 42 | class Modular extends TestPlatform<Modular, {}>()("Modular") {} |
| 43 | class Bare extends TestPlatform<Bare>()("Bare") {} |
| 44 | class Inline extends TestPlatform<Inline>()("Inline", {}, impl) {} |
| 45 | class EffectProps extends TestPlatform<EffectProps>()( |
| 46 | "EffectProps", |
| 47 | props, |
| 48 | impl, |
| 49 | ) {} |
| 50 | const External = TestPlatform("External", {}); |
| 51 | const ExternalEffect = TestPlatform("ExternalEffect", props); |
| 52 | const Functional = TestPlatform("Functional", {}, impl); |
| 53 | const FunctionalEffect = TestPlatform("FunctionalEffect", props, impl); |
| 54 | |
| 55 | Modular.make(props, impl); |
| 56 | Bare.make(props, impl); |
| 57 | |
| 58 | for (const [id, declaration] of Object.entries({ |
| 59 | Modular, |
| 60 | Bare, |
| 61 | Inline, |
| 62 | EffectProps, |
| 63 | External, |
| 64 | ExternalEffect, |
| 65 | Functional, |
| 66 | FunctionalEffect, |
| 67 | })) { |
| 68 | expect(identity(declaration)).toBe(id); |
| 69 | expect(Effect.isEffect(declaration)).toBe(true); |
| 70 | } |
| 71 | expect(Modular.of({})).not.toHaveProperty("LogicalId"); |
| 72 | expect(TestPlatform).not.toHaveProperty("LogicalId"); |
| 73 | }, |
| 74 | { tags: ["unit", "local"] }, |
| 75 | ); |
| 76 | |
| 77 | test( |
| 78 | "ordinary Worker declarations retain logical ids before yielding", |
| 79 | () => { |
| 80 | const props = Effect.sync(() => { |
| 81 | throw new Error("Reading identity must not evaluate Worker props"); |
| 82 | }); |
| 83 | const impl = Effect.sync(() => { |
| 84 | throw new Error( |
| 85 | "Reading identity must not evaluate Worker implementation", |
| 86 | ); |
| 87 | }); |
| 88 | |
| 89 | class Modular extends Worker<Modular, {}>()("Modular") {} |
| 90 | class Inline extends Worker<Inline>()("Inline", {}, impl) {} |
| 91 | class EffectProps extends Worker<EffectProps>()( |
| 92 | "EffectProps", |
| 93 | props, |
| 94 | impl, |
| 95 | ) {} |
| 96 | class External extends Worker<External>()("External", {}) {} |
| 97 | class ExternalEffect extends Worker<ExternalEffect>()( |
| 98 | "ExternalEffect", |
| 99 | props, |
| 100 | ) {} |
| 101 | const Functional = Worker("Functional", {}, impl); |
| 102 | const ExternalFunctional = Worker("ExternalFunctional", {}); |
| 103 | const ExternalFunctionalEffect = Worker("ExternalFunctionalEffect", props); |
| 104 | |
| 105 | Modular.make(props, impl); |
| 106 | |
| 107 | for (const [id, declaration] of Object.entries({ |
| 108 | Modular, |
| 109 | Inline, |
| 110 | EffectProps, |
| 111 | External, |
| 112 | ExternalEffect, |
| 113 | Functional, |
| 114 | ExternalFunctional, |
| 115 | ExternalFunctionalEffect, |
| 116 | })) { |
| 117 | expect(identity(declaration)).toBe(id); |
| 118 | expect(Effect.isEffect(declaration)).toBe(true); |
| 119 | expect(normalizeTransferredFrom(declaration)).toEqual([id]); |
| 120 | } |
| 121 | expect(Modular.of({})).not.toHaveProperty("LogicalId"); |
| 122 | expect(Worker).not.toHaveProperty("LogicalId"); |
| 123 | }, |
| 124 | { |
| 125 | tags: [ |
| 126 | "unit", |
| 127 | "provider:cloudflare", |
| 128 | "provider:cloudflare:worker", |
| 129 | "local", |
| 130 | ], |
| 131 | }, |
| 132 | ); |