alchemy 2.0.0-beta.40 → 2.0.0-beta.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/bin/exec.js +16 -3
  2. package/bin/exec.js.map +1 -1
  3. package/lib/AWS/EC2/hosted.js +1 -1
  4. package/lib/AWS/EC2/hosted.js.map +1 -1
  5. package/lib/AWS/ECS/Task.js +1 -1
  6. package/lib/AWS/ECS/Task.js.map +1 -1
  7. package/lib/AWS/Lambda/BucketEventSource.d.ts +1 -1
  8. package/lib/AWS/Lambda/BucketEventSource.d.ts.map +1 -1
  9. package/lib/AWS/Lambda/EventBridgeEventSource.d.ts +1 -1
  10. package/lib/AWS/Lambda/EventBridgeEventSource.d.ts.map +1 -1
  11. package/lib/AWS/Lambda/Function.js +1 -1
  12. package/lib/AWS/Lambda/Function.js.map +1 -1
  13. package/lib/AWS/Lambda/QueueEventSource.d.ts +1 -1
  14. package/lib/AWS/Lambda/QueueEventSource.d.ts.map +1 -1
  15. package/lib/AWS/Lambda/StreamEventSource.d.ts +1 -1
  16. package/lib/AWS/Lambda/StreamEventSource.d.ts.map +1 -1
  17. package/lib/AWS/Lambda/TableEventSource.d.ts +1 -1
  18. package/lib/AWS/Lambda/TableEventSource.d.ts.map +1 -1
  19. package/lib/AWS/Lambda/TopicEventSource.d.ts +1 -1
  20. package/lib/AWS/Lambda/TopicEventSource.d.ts.map +1 -1
  21. package/lib/Apply.d.ts.map +1 -1
  22. package/lib/Apply.js +41 -7
  23. package/lib/Apply.js.map +1 -1
  24. package/lib/Cloudflare/Bridge.d.ts +1 -0
  25. package/lib/Cloudflare/Bridge.d.ts.map +1 -1
  26. package/lib/Cloudflare/Bridge.js +1 -0
  27. package/lib/Cloudflare/Bridge.js.map +1 -1
  28. package/lib/Cloudflare/Container/ContainerApplication.js +1 -1
  29. package/lib/Cloudflare/Container/ContainerApplication.js.map +1 -1
  30. package/lib/Cloudflare/Container/ContainerBinding.d.ts +1 -1
  31. package/lib/Cloudflare/Container/ContainerBinding.d.ts.map +1 -1
  32. package/lib/Cloudflare/Container/ContainerBinding.js +1 -1
  33. package/lib/Cloudflare/Container/ContainerBinding.js.map +1 -1
  34. package/lib/Cloudflare/Fetcher.d.ts +9 -0
  35. package/lib/Cloudflare/Fetcher.d.ts.map +1 -1
  36. package/lib/Cloudflare/Fetcher.js +20 -1
  37. package/lib/Cloudflare/Fetcher.js.map +1 -1
  38. package/lib/Cloudflare/Local/SidecarHandlers.d.ts.map +1 -1
  39. package/lib/Cloudflare/Local/SidecarHandlers.js +1 -1
  40. package/lib/Cloudflare/Local/SidecarHandlers.js.map +1 -1
  41. package/lib/Cloudflare/StateStore/Api.d.ts +2 -2
  42. package/lib/Cloudflare/Website/StaticSite.d.ts +5 -4
  43. package/lib/Cloudflare/Website/StaticSite.d.ts.map +1 -1
  44. package/lib/Cloudflare/Website/StaticSite.js.map +1 -1
  45. package/lib/Cloudflare/Website/Vite.d.ts +4 -4
  46. package/lib/Cloudflare/Website/Vite.d.ts.map +1 -1
  47. package/lib/Cloudflare/Website/Vite.js.map +1 -1
  48. package/lib/Cloudflare/Workers/DurableObjectBridge.d.ts +17 -0
  49. package/lib/Cloudflare/Workers/DurableObjectBridge.d.ts.map +1 -0
  50. package/lib/Cloudflare/Workers/DurableObjectBridge.js +86 -0
  51. package/lib/Cloudflare/Workers/DurableObjectBridge.js.map +1 -0
  52. package/lib/Cloudflare/Workers/DurableObjectNamespace.d.ts +2 -1
  53. package/lib/Cloudflare/Workers/DurableObjectNamespace.d.ts.map +1 -1
  54. package/lib/Cloudflare/Workers/DurableObjectNamespace.js +10 -39
  55. package/lib/Cloudflare/Workers/DurableObjectNamespace.js.map +1 -1
  56. package/lib/Cloudflare/Workers/HttpServer.d.ts +2 -8
  57. package/lib/Cloudflare/Workers/HttpServer.d.ts.map +1 -1
  58. package/lib/Cloudflare/Workers/HttpServer.js +29 -33
  59. package/lib/Cloudflare/Workers/HttpServer.js.map +1 -1
  60. package/lib/Cloudflare/Workers/InferEnv.d.ts +5 -24
  61. package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
  62. package/lib/Cloudflare/Workers/Rpc.d.ts +0 -101
  63. package/lib/Cloudflare/Workers/Rpc.d.ts.map +1 -1
  64. package/lib/Cloudflare/Workers/Rpc.js +9 -286
  65. package/lib/Cloudflare/Workers/Rpc.js.map +1 -1
  66. package/lib/Cloudflare/Workers/RpcAsync.d.ts +8 -0
  67. package/lib/Cloudflare/Workers/RpcAsync.d.ts.map +1 -0
  68. package/lib/Cloudflare/Workers/RpcAsync.js +45 -0
  69. package/lib/Cloudflare/Workers/RpcAsync.js.map +1 -0
  70. package/lib/Cloudflare/Workers/Worker.d.ts +16 -162
  71. package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
  72. package/lib/Cloudflare/Workers/Worker.js +49 -354
  73. package/lib/Cloudflare/Workers/Worker.js.map +1 -1
  74. package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts +8 -0
  75. package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts.map +1 -0
  76. package/lib/Cloudflare/Workers/WorkerAsyncBindings.js +129 -0
  77. package/lib/Cloudflare/Workers/WorkerAsyncBindings.js.map +1 -0
  78. package/lib/Cloudflare/Workers/WorkerBinding.d.ts +154 -0
  79. package/lib/Cloudflare/Workers/WorkerBinding.d.ts.map +1 -0
  80. package/lib/Cloudflare/Workers/WorkerBinding.js +51 -0
  81. package/lib/Cloudflare/Workers/WorkerBinding.js.map +1 -0
  82. package/lib/Cloudflare/Workers/WorkerBridge.d.ts +35 -0
  83. package/lib/Cloudflare/Workers/WorkerBridge.d.ts.map +1 -0
  84. package/lib/Cloudflare/Workers/WorkerBridge.js +149 -0
  85. package/lib/Cloudflare/Workers/WorkerBridge.js.map +1 -0
  86. package/lib/Cloudflare/Workers/WorkerBundle.d.ts.map +1 -1
  87. package/lib/Cloudflare/Workers/WorkerBundle.js +18 -84
  88. package/lib/Cloudflare/Workers/WorkerBundle.js.map +1 -1
  89. package/lib/Cloudflare/Workers/WorkerRuntimeContext.d.ts +8 -0
  90. package/lib/Cloudflare/Workers/WorkerRuntimeContext.d.ts.map +1 -0
  91. package/lib/Cloudflare/Workers/WorkerRuntimeContext.js +113 -0
  92. package/lib/Cloudflare/Workers/WorkerRuntimeContext.js.map +1 -0
  93. package/lib/Cloudflare/Workers/WorkflowBridge.d.ts +26 -0
  94. package/lib/Cloudflare/Workers/WorkflowBridge.d.ts.map +1 -0
  95. package/lib/Cloudflare/Workers/WorkflowBridge.js +41 -0
  96. package/lib/Cloudflare/Workers/WorkflowBridge.js.map +1 -0
  97. package/lib/Cloudflare/Workers/index.d.ts +4 -0
  98. package/lib/Cloudflare/Workers/index.d.ts.map +1 -1
  99. package/lib/Cloudflare/Workers/index.js +4 -0
  100. package/lib/Cloudflare/Workers/index.js.map +1 -1
  101. package/lib/Cloudflare/index.d.ts +4 -2
  102. package/lib/Cloudflare/index.d.ts.map +1 -1
  103. package/lib/Cloudflare/index.js +4 -2
  104. package/lib/Cloudflare/index.js.map +1 -1
  105. package/lib/Neon/Project.d.ts.map +1 -1
  106. package/lib/Neon/Project.js +2 -1
  107. package/lib/Neon/Project.js.map +1 -1
  108. package/lib/Platform.d.ts +3 -4
  109. package/lib/Platform.d.ts.map +1 -1
  110. package/lib/Platform.js.map +1 -1
  111. package/lib/Rpc.d.ts +17 -0
  112. package/lib/Rpc.d.ts.map +1 -0
  113. package/lib/Rpc.js +1 -0
  114. package/lib/Rpc.js.map +1 -0
  115. package/lib/RuntimeContext.d.ts +1 -0
  116. package/lib/RuntimeContext.d.ts.map +1 -1
  117. package/lib/RuntimeContext.js.map +1 -1
  118. package/lib/Sidecar/RpcHandler.d.ts.map +1 -1
  119. package/lib/Sidecar/RpcHandler.js +13 -9
  120. package/lib/Sidecar/RpcHandler.js.map +1 -1
  121. package/lib/State/HttpStateApi.d.ts +10 -0
  122. package/lib/State/HttpStateApi.d.ts.map +1 -1
  123. package/lib/State/HttpStateApi.js +10 -0
  124. package/lib/State/HttpStateApi.js.map +1 -1
  125. package/lib/State/HttpStateStore.d.ts.map +1 -1
  126. package/lib/State/HttpStateStore.js +2 -1
  127. package/lib/State/HttpStateStore.js.map +1 -1
  128. package/lib/State/InMemoryState.d.ts.map +1 -1
  129. package/lib/State/InMemoryState.js +2 -0
  130. package/lib/State/InMemoryState.js.map +1 -1
  131. package/lib/State/LocalState.d.ts.map +1 -1
  132. package/lib/State/LocalState.js +2 -0
  133. package/lib/State/LocalState.js.map +1 -1
  134. package/lib/State/State.d.ts +8 -0
  135. package/lib/State/State.d.ts.map +1 -1
  136. package/lib/State/StateEncoding.d.ts.map +1 -1
  137. package/lib/State/StateEncoding.js +5 -1
  138. package/lib/State/StateEncoding.js.map +1 -1
  139. package/lib/index.d.ts +2 -1
  140. package/lib/index.d.ts.map +1 -1
  141. package/lib/index.js +1 -1
  142. package/lib/index.js.map +1 -1
  143. package/lib/tsconfig.test.tsbuildinfo +1 -1
  144. package/package.json +1 -1
  145. package/src/Apply.ts +44 -10
  146. package/src/Cli/Event.ts +1 -1
  147. package/src/Cloudflare/Bridge.ts +1 -0
  148. package/src/Cloudflare/Container/ContainerBinding.ts +1 -1
  149. package/src/Cloudflare/Fetcher.ts +38 -1
  150. package/src/Cloudflare/Local/SidecarHandlers.ts +3 -6
  151. package/src/Cloudflare/Website/StaticSite.ts +10 -5
  152. package/src/Cloudflare/Website/Vite.ts +7 -4
  153. package/src/Cloudflare/Workers/DurableObjectBridge.ts +180 -0
  154. package/src/Cloudflare/Workers/DurableObjectNamespace.ts +22 -70
  155. package/src/Cloudflare/Workers/HttpServer.ts +25 -39
  156. package/src/Cloudflare/Workers/InferEnv.ts +42 -78
  157. package/src/Cloudflare/Workers/Rpc.ts +18 -417
  158. package/src/Cloudflare/Workers/RpcAsync.ts +63 -0
  159. package/src/Cloudflare/Workers/Worker.ts +107 -548
  160. package/src/Cloudflare/Workers/WorkerAsyncBindings.ts +149 -0
  161. package/src/Cloudflare/Workers/WorkerBinding.ts +103 -0
  162. package/src/Cloudflare/Workers/WorkerBridge.ts +304 -0
  163. package/src/Cloudflare/Workers/WorkerBundle.ts +17 -83
  164. package/src/Cloudflare/Workers/WorkerRuntimeContext.ts +164 -0
  165. package/src/Cloudflare/Workers/WorkflowBridge.ts +92 -0
  166. package/src/Cloudflare/Workers/index.ts +4 -0
  167. package/src/Cloudflare/index.ts +4 -2
  168. package/src/Neon/Project.ts +3 -1
  169. package/src/Platform.ts +3 -4
  170. package/src/Rpc.ts +25 -0
  171. package/src/RuntimeContext.ts +1 -0
  172. package/src/Sidecar/RpcHandler.ts +18 -9
  173. package/src/State/HttpStateApi.ts +11 -0
  174. package/src/State/HttpStateStore.ts +7 -2
  175. package/src/State/InMemoryState.ts +2 -0
  176. package/src/State/LocalState.ts +2 -0
  177. package/src/State/State.ts +8 -0
  178. package/src/State/StateEncoding.ts +8 -1
  179. package/src/index.ts +7 -6
@@ -1,51 +1,36 @@
1
1
  import * as workers from "@distilled.cloud/cloudflare/workers";
2
2
  import * as zones from "@distilled.cloud/cloudflare/zones";
3
- import * as Cause from "effect/Cause";
4
3
  import * as Context from "effect/Context";
5
4
  import * as Data from "effect/Data";
6
5
  import * as Effect from "effect/Effect";
7
- import * as Exit from "effect/Exit";
8
6
  import * as Layer from "effect/Layer";
9
- import * as Option from "effect/Option";
10
7
  import * as Path from "effect/Path";
11
8
  import * as Redacted from "effect/Redacted";
12
9
  import * as Schedule from "effect/Schedule";
13
- import * as Scope from "effect/Scope";
14
- import * as Stream from "effect/Stream";
15
10
  import { Unowned } from "../../AdoptPolicy.js";
16
11
  import { AlchemyContext } from "../../AlchemyContext.js";
17
12
  import * as Artifacts from "../../Artifacts.js";
18
- import * as Binding from "../../Binding.js";
19
13
  import { hashDirectory } from "../../Build/Memo.js";
20
14
  import * as Bundle from "../../Bundle/Bundle.js";
21
15
  import { isResolved } from "../../Diff.js";
22
- import { ExecutionContext } from "../../ExecutionContext.js";
23
- import * as Output from "../../Output.js";
24
- import { Platform, } from "../../Platform.js";
16
+ import { Platform } from "../../Platform.js";
25
17
  import * as Provider from "../../Provider.js";
26
18
  import { Resource } from "../../Resource.js";
27
- import * as Serverless from "../../Serverless/index.js";
28
19
  import { Stack } from "../../Stack.js";
29
- import { isYieldableEffectLike } from "../../Util/effect.js";
30
- import { isAnalyticsEngineDataset, } from "../AnalyticsEngine/AnalyticsEngineDataset.js";
31
- import { isArtifacts as isArtifactsBinding, } from "../Artifacts/Artifacts.js";
32
20
  import { CloudflareEnvironment } from "../CloudflareEnvironment.js";
33
- import { D1Database } from "../D1/D1Database.js";
34
- import { isSendEmail } from "../Email/SendEmail.js";
35
- import { isImages as isImagesBinding, } from "../Images/Images.js";
36
21
  import { SidecarLive } from "../Local/Sidecar.js";
37
22
  import { CloudflareLogs } from "../Logs.js";
38
- import { isAssets, readAssets, uploadAssets, } from "./Assets.js";
23
+ import { readAssets, uploadAssets, } from "./Assets.js";
39
24
  import { getCompatibility } from "./Compatibility.js";
40
- import { isDurableObjectExport, isDurableObjectNamespaceLike, } from "./DurableObjectNamespace.js";
41
- import { workersHttpHandler } from "./HttpServer.js";
25
+ import { isDurableObjectExport } from "./DurableObjectNamespace.js";
42
26
  import { LocalWorkerProvider } from "./LocalWorkerProvider.js";
43
27
  import { Request } from "./Request.js";
44
- import { encodeRpcError, ErrorTag, makeRpcStub, toRpcStream, } from "./Rpc.js";
45
28
  import * as Vite from "./Vite.js";
29
+ import { bindWorkerAsyncBindings, getCronBindings, } from "./WorkerAsyncBindings.js";
46
30
  import { WorkerBundle } from "./WorkerBundle.js";
47
31
  import { createWorkerName } from "./WorkerName.js";
48
- const WorkerTypeId = "Cloudflare.Worker";
32
+ import { makeWorkerRuntimeContext, } from "./WorkerRuntimeContext.js";
33
+ export const WorkerTypeId = "Cloudflare.Worker";
49
34
  export const isWorker = (value) => typeof value === "object" &&
50
35
  value !== null &&
51
36
  "Type" in value &&
@@ -423,342 +408,11 @@ export const ExportedHandlerMethods = [
423
408
  * ```
424
409
  */
425
410
  export const Worker = Platform(WorkerTypeId, {
426
- onCreate: Effect.fnUntraced(function* (resource, props) {
427
- if (props.bindings) {
428
- for (const bindingName in props.bindings) {
429
- // @ts-expect-error
430
- const bindingEff = props.bindings?.[bindingName];
431
- // Bindings can be passed as a plain resource value, an Effect that
432
- // yields a resource, or an effect-class (e.g. a `Cloudflare.Worker`
433
- // class). Resolve the yieldable forms before deriving binding metadata.
434
- const binding = isYieldableEffectLike(bindingEff)
435
- ? (yield* bindingEff)
436
- : bindingEff;
437
- const bindingMeta = isAssets(binding)
438
- ? {
439
- type: "assets",
440
- name: bindingName,
441
- }
442
- : isArtifactsBinding(binding)
443
- ? {
444
- type: "artifacts",
445
- name: bindingName,
446
- namespace: binding.namespace,
447
- }
448
- : isImagesBinding(binding)
449
- ? {
450
- type: "images",
451
- name: bindingName,
452
- }
453
- : isAnalyticsEngineDataset(binding)
454
- ? {
455
- type: "analytics_engine",
456
- name: bindingName,
457
- dataset: binding.dataset,
458
- }
459
- : isSendEmail(binding)
460
- ? {
461
- type: "send_email",
462
- name: bindingName,
463
- destinationAddress: binding.destinationAddress,
464
- allowedDestinationAddresses: binding.allowedDestinationAddresses,
465
- allowedSenderAddresses: binding.allowedSenderAddresses,
466
- }
467
- : isDurableObjectNamespaceLike(binding)
468
- ? {
469
- type: "durable_object_namespace",
470
- name: bindingName,
471
- className: binding.className ?? binding.name,
472
- }
473
- : binding.Type === "Cloudflare.D1Database"
474
- ? {
475
- type: "d1",
476
- id: binding.databaseId,
477
- name: bindingName,
478
- }
479
- : binding.Type === "Cloudflare.R2Bucket"
480
- ? {
481
- type: "r2_bucket",
482
- name: bindingName,
483
- bucketName: binding.bucketName,
484
- jurisdiction: binding.jurisdiction.pipe(Output.map((jurisdiction) => jurisdiction === "default"
485
- ? undefined
486
- : jurisdiction)),
487
- }
488
- : binding.Type === "Cloudflare.KVNamespace"
489
- ? {
490
- type: "kv_namespace",
491
- name: bindingName,
492
- namespaceId: binding.namespaceId,
493
- }
494
- : binding.Type === "Cloudflare.Queue"
495
- ? {
496
- type: "queue",
497
- name: bindingName,
498
- queueName: binding.queueName,
499
- }
500
- : binding.Type === "Cloudflare.AiGateway"
501
- ? {
502
- type: "ai",
503
- name: bindingName,
504
- }
505
- : binding.Type === "Cloudflare.Hyperdrive"
506
- ? {
507
- type: "hyperdrive",
508
- name: bindingName,
509
- id: binding.hyperdriveId,
510
- }
511
- : isWorker(binding)
512
- ? {
513
- type: "service",
514
- name: bindingName,
515
- service: binding.workerName,
516
- }
517
- : // TODO(sam): handle others
518
- undefined;
519
- if (bindingMeta) {
520
- yield* resource.bind `${bindingName}`({
521
- bindings: [bindingMeta],
522
- });
523
- }
524
- else {
525
- return yield* Effect.die(`Unknown binding type: ${bindingName}`);
526
- }
527
- }
528
- }
529
- }),
530
- createRuntimeContext: (id) => {
531
- const listeners = [];
532
- const exports = {};
533
- const env = {};
534
- let userShape;
535
- const ctx = {
536
- Type: WorkerTypeId,
537
- id,
538
- env,
539
- get: (key) => Effect.serviceOption(WorkerEnvironment).pipe(Effect.map(Option.getOrUndefined), Effect.flatMap((env) => env
540
- ? Effect.succeed(env[key])
541
- : Effect.die("WorkerEnvironment not found")), Effect.flatMap((value) => value
542
- ? Effect.succeed(value)
543
- : Effect.die(`Environment variable '${key}' not found`)), Effect.map((json) => {
544
- try {
545
- const value = JSON.parse(json);
546
- // The `set` path serializes Redacted values as
547
- // `{_tag: "Redacted", value: ...}`. After JSON.parse the
548
- // result is a plain object — `Redacted.isRedacted` would
549
- // always return `false` on it — so detect the marker shape
550
- // and rebuild the Redacted wrapper. Plain values pass
551
- // through unchanged.
552
- if (value !== null &&
553
- typeof value === "object" &&
554
- value._tag === "Redacted" &&
555
- "value" in value) {
556
- return Redacted.make(value.value);
557
- }
558
- return value;
559
- }
560
- catch {
561
- return json;
562
- }
563
- })),
564
- set: (id, output) => Effect.sync(() => {
565
- const key = id.replaceAll(/[^a-zA-Z0-9]/g, "_");
566
- // Preserve `Redacted`-ness across the Output → env → Cloudflare
567
- // binding boundary so the put-worker loop can deploy secrets via
568
- // `secret_text` instead of leaking them as `plain_text`. The JSON
569
- // payload still carries the `{_tag: "Redacted", …}` marker so the
570
- // runtime `get` accessor can rebuild the wrapper after Cloudflare
571
- // hands the binding back as a plain string.
572
- env[key] = output.pipe(Output.map((value) => Redacted.isRedacted(value)
573
- ? Redacted.make(JSON.stringify({
574
- _tag: "Redacted",
575
- value: Redacted.value(value),
576
- }))
577
- : JSON.stringify(value)));
578
- return key;
579
- }),
580
- serve: (handler, options) => {
581
- // Capture the user's full default-export shape so `exports` can
582
- // expose any non-handler methods on it as RPC methods on the
583
- // deployed `WorkerEntrypoint` subclass — see `__rpc__` below.
584
- if (options?.shape)
585
- userShape = options.shape;
586
- return ctx.listen(workersHttpHandler(handler));
587
- },
588
- listen: ((handler) => Effect.sync(() => Effect.isEffect(handler)
589
- ? listeners.push(handler)
590
- : listeners.push(Effect.succeed(handler)))),
591
- export: (name, value) => Effect.sync(() => {
592
- exports[name] = value;
593
- }),
594
- exports: Effect.gen(function* () {
595
- const handlers = yield* Effect.all(listeners, {
596
- concurrency: "unbounded",
597
- });
598
- const services = yield* Effect.context();
599
- // Provide the per-request runtime layer (services + `WorkerExecutionContext`
600
- // + a fresh `ExecutionContext`/`Scope`) to a user effect, then run it.
601
- // This is the bridge between Cloudflare's request-time callback and
602
- // the user's Effect-native handler. Used by both the standard
603
- // `handle()` dispatch (fetch/scheduled/…) and the per-RPC dispatchers
604
- // below — keeping them on a single layer-provision path.
605
- const runUserEffect = (eff, context) => {
606
- const scope = Scope.makeUnsafe();
607
- return eff
608
- .pipe(Effect.provideContext(services), Scope.provide(scope), Effect.provide(Layer.succeed(WorkerExecutionContext, context)), Effect.provide(Layer.succeed(ExecutionContext, { scope, cache: {} })), Effect.runPromiseExit)
609
- .finally(() => context.waitUntil(Effect.runPromise(Scope.close(scope, Exit.void))));
610
- };
611
- const handle = (type) => (request, env, context) => {
612
- const event = {
613
- kind: "Cloudflare.Workers.WorkerEvent",
614
- type,
615
- input: request,
616
- env,
617
- context,
618
- };
619
- for (const handler of handlers) {
620
- const eff = handler(event);
621
- if (Effect.isEffect(eff)) {
622
- return runUserEffect(eff, context).then((exit) => {
623
- if (exit._tag === "Success")
624
- return exit.value;
625
- throw Cause.squash(exit.cause);
626
- });
627
- }
628
- }
629
- return Promise.reject(new Error("No event handler found"));
630
- };
631
- // RPC method dispatchers — one per non-handler method on the user's
632
- // shape. Each dispatcher is invoked by the WorkerEntrypoint bridge
633
- // as `dispatcher(args, ctx)`: `args` are the user-facing call args,
634
- // `ctx` is the `this.ctx` that Cloudflare hands the bridge per RPC
635
- // request. The dispatcher runs the user effect with the same runtime
636
- // layer the fetch path uses, then envelope-encodes the result so
637
- // `Effect.fail` round-trips as `RpcErrorEnvelope` and `Stream` as
638
- // `RpcStreamEnvelope` (consumers wrap the binding with
639
- // `toPromiseApi`/`bindWorker` to decode).
640
- const exportedHandlerSet = new Set(ExportedHandlerMethods);
641
- const rpcDispatchers = {};
642
- if (userShape) {
643
- for (const [name, value] of Object.entries(userShape)) {
644
- if (exportedHandlerSet.has(name))
645
- continue;
646
- if (typeof value !== "function")
647
- continue;
648
- rpcDispatchers[name] = async (args, context) => {
649
- const result = value(...args);
650
- if (!Effect.isEffect(result))
651
- return result;
652
- const exit = await runUserEffect(result, context);
653
- if (exit._tag === "Success") {
654
- if (Stream.isStream(exit.value)) {
655
- return await Effect.runPromise(toRpcStream(exit.value));
656
- }
657
- return exit.value;
658
- }
659
- const failReason = exit.cause.reasons.find(Cause.isFailReason);
660
- if (failReason) {
661
- return {
662
- _tag: ErrorTag,
663
- error: encodeRpcError(failReason.error),
664
- };
665
- }
666
- const dieReason = exit.cause.reasons.find(Cause.isDieReason);
667
- throw (dieReason?.defect ??
668
- new Error("RPC method failed with an unexpected cause"));
669
- };
670
- }
671
- }
672
- return {
673
- ...exports,
674
- default: Object.fromEntries(ExportedHandlerMethods.map((method) => [method, handle(method)])),
675
- __rpc__: rpcDispatchers,
676
- };
677
- }),
678
- };
679
- return ctx;
680
- },
681
- });
682
- export const bindWorker = Effect.fnUntraced(function* (workerEff) {
683
- // Worker classes and regular Effects are both yieldable here.
684
- const worker = isYieldableEffectLike(workerEff)
685
- ? yield* workerEff
686
- : workerEff;
687
- const self = yield* Worker;
688
- yield* self.bind `${worker}`({
689
- bindings: [
690
- {
691
- type: "service",
692
- name: worker.LogicalId,
693
- service: worker.workerName,
694
- },
695
- ],
696
- });
697
- // `bindWorker` runs at *init* phase (both at plantime and at runtime
698
- // cold-start). `WorkerEnvironment` only exists at exec phase on the
699
- // deployed worker, so we hand `makeRpcStub` an `Effect<stub>` that
700
- // resolves the binding lazily on each method call.
701
- const stubEff = WorkerEnvironment.pipe(Effect.map((env) => env[worker.LogicalId]));
702
- return makeRpcStub(stubEff);
411
+ onCreate: bindWorkerAsyncBindings,
412
+ createRuntimeContext: makeWorkerRuntimeContext,
703
413
  });
704
- export class BindWorkerPolicy extends Binding.Policy()("Cloudflare.Worker.Bind") {
705
- }
706
- export const BindWorkerPolicyLive = BindWorkerPolicy.layer.succeed(Effect.fn(function* (host, worker) {
707
- if (isWorker(host)) {
708
- yield* host.bind `${worker}`({
709
- bindings: [
710
- {
711
- type: "service",
712
- name: worker.LogicalId,
713
- service: worker.workerName,
714
- },
715
- ],
716
- });
717
- }
718
- else {
719
- return yield* Effect.die(new Error(`BindWorkerPolicy does not support runtime '${host.Type}'`));
720
- }
721
- }));
722
414
  class MissingDurableObjectNamespaces extends Data.TaggedError("MissingDurableObjectNamespaces") {
723
415
  }
724
- function bumpMigrationTagVersion(oldTag) {
725
- if (!oldTag)
726
- return undefined;
727
- const version = oldTag.match(/^(alchemy:)?v(\d+)$/)?.[2];
728
- if (!version)
729
- return "alchemy:v1";
730
- return `alchemy:v${parseInt(version, 10) + 1}`;
731
- }
732
- function getDurableObjectBindings(bindings, workerName) {
733
- return bindings.flatMap((binding) => (binding.data.bindings ?? []).flatMap((item) => item.type === "durable_object_namespace" &&
734
- "className" in item &&
735
- item.className &&
736
- (!("scriptName" in item) ||
737
- !item.scriptName ||
738
- item.scriptName === workerName)
739
- ? [
740
- {
741
- logicalId: binding.sid,
742
- bindingName: item.name,
743
- className: item.className,
744
- },
745
- ]
746
- : []));
747
- }
748
- export function getCronBindings(bindings) {
749
- return Array.from(new Set(bindings.flatMap((b) => b.data.crons ?? [])));
750
- }
751
- function getDurableObjectTagMap(tags) {
752
- return Object.fromEntries(tags.flatMap((tag) => {
753
- if (!tag.startsWith("alchemy:do:")) {
754
- return [];
755
- }
756
- const parts = tag.split(":");
757
- const logicalId = parts[2];
758
- const className = parts.slice(3).join(":");
759
- return logicalId && className ? [[logicalId, className]] : [];
760
- }));
761
- }
762
416
  const selectLayer = (input) => Layer.unwrap(AlchemyContext.useSync((context) => context.dev ? input.dev() : input.live()));
763
417
  export const WorkerProvider = () => selectLayer({
764
418
  live: LiveWorkerProvider,
@@ -1677,6 +1331,12 @@ export const LiveWorkerProvider = () => Provider.effect(Worker, Effect.gen(funct
1677
1331
  yield* deleteScript({
1678
1332
  accountId: output.accountId,
1679
1333
  scriptName: output.workerName,
1334
+ // Force teardown of queue consumers, durable object classes, and
1335
+ // service bindings hanging off this worker. Without `force`, those
1336
+ // conditions raise QueueConsumerConflict / ServiceBindingConflict
1337
+ // and leave the script in CF. Alchemy is the source of truth for
1338
+ // the worker, so we want a hard delete on teardown.
1339
+ force: true,
1680
1340
  }).pipe(Effect.catchTag("WorkerNotFound", () => Effect.void));
1681
1341
  }),
1682
1342
  tail: ({ output }) => telemetry.tailScript({
@@ -1719,4 +1379,39 @@ const contentTypeFromExtension = (extension) => {
1719
1379
  return "application/octet-stream";
1720
1380
  }
1721
1381
  };
1382
+ function bumpMigrationTagVersion(oldTag) {
1383
+ if (!oldTag)
1384
+ return undefined;
1385
+ const version = oldTag.match(/^(alchemy:)?v(\d+)$/)?.[2];
1386
+ if (!version)
1387
+ return "alchemy:v1";
1388
+ return `alchemy:v${parseInt(version, 10) + 1}`;
1389
+ }
1390
+ function getDurableObjectBindings(bindings, workerName) {
1391
+ return bindings.flatMap((binding) => (binding.data.bindings ?? []).flatMap((item) => item.type === "durable_object_namespace" &&
1392
+ "className" in item &&
1393
+ item.className &&
1394
+ (!("scriptName" in item) ||
1395
+ !item.scriptName ||
1396
+ item.scriptName === workerName)
1397
+ ? [
1398
+ {
1399
+ logicalId: binding.sid,
1400
+ bindingName: item.name,
1401
+ className: item.className,
1402
+ },
1403
+ ]
1404
+ : []));
1405
+ }
1406
+ function getDurableObjectTagMap(tags) {
1407
+ return Object.fromEntries(tags.flatMap((tag) => {
1408
+ if (!tag.startsWith("alchemy:do:")) {
1409
+ return [];
1410
+ }
1411
+ const parts = tag.split(":");
1412
+ const logicalId = parts[2];
1413
+ const className = parts.slice(3).join(":");
1414
+ return logicalId && className ? [[logicalId, className]] : [];
1415
+ }));
1416
+ }
1722
1417
  //# sourceMappingURL=Worker.js.map