effect-cf 0.41.0 → 0.42.0

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 (67) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +28 -0
  3. package/dist/AiGateway.d.mts +2 -2
  4. package/dist/AnalyticsEngine.d.mts +2 -2
  5. package/dist/Artifacts.d.mts +2 -2
  6. package/dist/BrowserRendering.d.mts +2 -2
  7. package/dist/ContainerNamespace.d.mts +2 -2
  8. package/dist/ContainerNamespace.mjs +23 -20
  9. package/dist/D1.d.mts +9 -12
  10. package/dist/DurableObject.d.mts +5 -3
  11. package/dist/DurableObject.mjs +4 -3
  12. package/dist/DurableObjectDefinition.d.mts +15 -12
  13. package/dist/DurableObjectDefinition.mjs +5 -3
  14. package/dist/DurableObjectNamespace.d.mts +10 -8
  15. package/dist/DurableObjectNamespace.mjs +1 -1
  16. package/dist/Email.d.mts +2 -2
  17. package/dist/Hyperdrive.d.mts +2 -2
  18. package/dist/Images.d.mts +2 -2
  19. package/dist/Kv.d.mts +2 -2
  20. package/dist/Queue.d.mts +5 -4
  21. package/dist/QueueDefinition.d.mts +4 -4
  22. package/dist/R2.d.mts +2 -2
  23. package/dist/RpcDefinition.d.mts +26 -12
  24. package/dist/RpcDefinition.mjs +22 -5
  25. package/dist/RpcTargets.mjs +1 -2
  26. package/dist/Sandbox.d.mts +1 -1
  27. package/dist/Sandbox.mjs +87 -65
  28. package/dist/ServiceBinding.d.mts +17 -18
  29. package/dist/Vectorize.d.mts +2 -2
  30. package/dist/Worker.d.mts +5 -3
  31. package/dist/Worker.mjs +5 -4
  32. package/dist/WorkerDefinition.d.mts +15 -11
  33. package/dist/WorkerDefinition.mjs +5 -3
  34. package/dist/WorkersAi.d.mts +2 -2
  35. package/dist/Workflow.d.mts +5 -4
  36. package/dist/WorkflowDefinition.d.mts +4 -4
  37. package/dist/index.d.mts +2 -2
  38. package/dist/index.mjs +1 -1
  39. package/dist/internal/RpcTargets.mjs +5 -0
  40. package/package.json +1 -1
  41. package/src/AiGateway.ts +2 -0
  42. package/src/AnalyticsEngine.ts +2 -0
  43. package/src/Artifacts.ts +2 -0
  44. package/src/BrowserRendering.ts +2 -0
  45. package/src/ContainerNamespace.ts +34 -39
  46. package/src/D1.ts +16 -8
  47. package/src/DurableObject.ts +14 -1
  48. package/src/DurableObjectDefinition.ts +33 -17
  49. package/src/DurableObjectNamespace.ts +19 -35
  50. package/src/Email.ts +2 -0
  51. package/src/Hyperdrive.ts +2 -0
  52. package/src/Images.ts +2 -0
  53. package/src/Kv.ts +2 -0
  54. package/src/Queue.ts +4 -7
  55. package/src/QueueDefinition.ts +7 -4
  56. package/src/R2.ts +2 -0
  57. package/src/RpcDefinition.ts +64 -25
  58. package/src/RpcTargets.ts +2 -8
  59. package/src/Sandbox.ts +133 -146
  60. package/src/ServiceBinding.ts +39 -34
  61. package/src/Vectorize.ts +2 -0
  62. package/src/Worker.ts +12 -1
  63. package/src/WorkerDefinition.ts +28 -17
  64. package/src/WorkersAi.ts +2 -0
  65. package/src/Workflow.ts +9 -8
  66. package/src/WorkflowDefinition.ts +12 -4
  67. package/src/internal/RpcTargets.ts +10 -0
@@ -1,5 +1,5 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
2
- import { assertNoReservedMethods, decodeArgs, encodeSuccess, make as make$1, method as method$1 } from "./RpcDefinition.mjs";
2
+ import { assertNoReservedMethods, decodeArgs, encodeSuccess, make as make$1, method as method$1, native as native$1 } from "./RpcDefinition.mjs";
3
3
  import { recordDecodedArgs } from "./internal/RpcInvocation.mjs";
4
4
  import { layer, makeDirectMethods } from "./ServiceBinding.mjs";
5
5
  import { make as make$2 } from "./Worker.mjs";
@@ -11,7 +11,8 @@ var WorkerDefinition_exports = /* @__PURE__ */ __exportAll({
11
11
  Worker: () => Worker,
12
12
  implement: () => implement,
13
13
  make: () => make,
14
- method: () => method
14
+ method: () => method,
15
+ native: () => native
15
16
  });
16
17
  const reservedMethodNames = /* @__PURE__ */ new Set([
17
18
  "constructor",
@@ -36,6 +37,7 @@ const assumeTagClass = (value) => {
36
37
  * Defines a single RPC method schema in a worker definition.
37
38
  */
38
39
  const method = method$1;
40
+ const native = native$1;
39
41
  const makeDefinition = (id, methods) => {
40
42
  assertNoReservedMethods("Worker", methods, reservedMethodNames);
41
43
  const definition = make$1(id, methods);
@@ -100,4 +102,4 @@ const wrapHandlers = (definition, handlers) => {
100
102
  */
101
103
  const implement = (_definition, handlers) => handlers;
102
104
  //#endregion
103
- export { Tag, Worker, WorkerDefinition_exports, implement, make, method };
105
+ export { Tag, Worker, WorkerDefinition_exports, implement, make, method, native };
@@ -5,7 +5,7 @@ import * as Effect from "effect/Effect";
5
5
  import * as S from "effect/Schema";
6
6
  import { Layer } from "effect";
7
7
  declare namespace WorkersAi_d_exports {
8
- export { LayerOptions, Tag, TagClass, WorkersAiAsyncBatchResponse, WorkersAiBinding, WorkersAiClient, WorkersAiDefinition, WorkersAiEmbeddingInput, WorkersAiEmbeddingResponse, WorkersAiModelsSearchObject, WorkersAiModelsSearchParams, WorkersAiOperationError, WorkersAiOptions, WorkersAiService, embeddingResponse, isWorkersAiBinding, layer, make, makeClient };
8
+ export { BindingNotFoundError, BindingValidationError, LayerOptions, Tag, TagClass, WorkersAiAsyncBatchResponse, WorkersAiBinding, WorkersAiClient, WorkersAiDefinition, WorkersAiEmbeddingInput, WorkersAiEmbeddingResponse, WorkersAiModelsSearchObject, WorkersAiModelsSearchParams, WorkersAiOperationError, WorkersAiOptions, WorkersAiService, embeddingResponse, isWorkersAiBinding, layer, make, makeClient };
9
9
  }
10
10
  declare const WorkersAiOperationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
11
11
  readonly _tag: "WorkersAiOperationError";
@@ -81,4 +81,4 @@ declare const layer: <Self, ModelList extends AiModelListType = AiModels>(tag: C
81
81
  declare const make: <Id extends string>(id: Id) => TagClass<WorkersAiService<Id>, Id, AiModels>;
82
82
  declare const Tag: <Self>() => <Id extends string, ModelList extends AiModelListType = AiModels>(id: Id) => TagClass<Self, Id, ModelList>;
83
83
  //#endregion
84
- export { LayerOptions, Tag, TagClass, WorkersAiAsyncBatchResponse, WorkersAiBinding, WorkersAiClient, WorkersAiDefinition, WorkersAiEmbeddingInput, WorkersAiEmbeddingResponse, WorkersAiModelsSearchObject, WorkersAiModelsSearchParams, WorkersAiOperationError, WorkersAiOptions, WorkersAiService, WorkersAi_d_exports, embeddingResponse, isWorkersAiBinding, layer, make, makeClient };
84
+ export { type BindingNotFoundError, type BindingValidationError, LayerOptions, Tag, TagClass, WorkersAiAsyncBatchResponse, WorkersAiBinding, WorkersAiClient, WorkersAiDefinition, WorkersAiEmbeddingInput, WorkersAiEmbeddingResponse, WorkersAiModelsSearchObject, WorkersAiModelsSearchParams, WorkersAiOperationError, WorkersAiOptions, WorkersAiService, WorkersAi_d_exports, embeddingResponse, isWorkersAiBinding, layer, make, makeClient };
@@ -1,6 +1,8 @@
1
1
  import { WorkerEnv, WorkerEnvironment } from "./Environment.mjs";
2
+ import { BindingNotFoundError, BindingValidationError } from "./Binding.mjs";
2
3
  import { ExecutionContext, WorkerContext } from "./Worker.mjs";
3
- import { Definition as Definition$1, Handler as Handler$1, LayerOptions as LayerOptions$1, Options as Options$1, Tag, TagClass as TagClass$1, implement } from "./WorkflowDefinition.mjs";
4
+ import { WorkflowInstance, WorkflowInstanceCreateBatchOptions, WorkflowInstanceCreateOptions, WorkflowOperationError } from "./WorkflowBinding.mjs";
5
+ import { Definition as Definition$1, Handler as Handler$1, LayerOptions as LayerOptions$1, Options as Options$1, Tag, TagClass, implement } from "./WorkflowDefinition.mjs";
4
6
  import * as Context$1 from "effect/Context";
5
7
  import * as Effect from "effect/Effect";
6
8
  import * as Layer$1 from "effect/Layer";
@@ -8,7 +10,7 @@ import * as Cause$1 from "effect/Cause";
8
10
  import { WorkflowEntrypoint, WorkflowEvent, WorkflowSleepDuration, WorkflowStep, WorkflowStepConfig, WorkflowStepContext, WorkflowStepEvent, WorkflowTimeoutDuration } from "cloudflare:workers";
9
11
  import { Scope } from "effect";
10
12
  declare namespace Workflow_d_exports {
11
- export { Definition, Handler, LayerOptions, Options, Tag, TagClass, WorkflowClass, WorkflowEvent$1 as WorkflowEvent, WorkflowEventService, WorkflowHandler, WorkflowOptions, WorkflowRunContext, WorkflowStep$1 as WorkflowStep, WorkflowStepContext$1 as WorkflowStepContext, WorkflowStepError, WorkflowStepNonRetryableError, WorkflowStepService, implement, make, sleep, sleepUntil, step, waitForEvent };
13
+ export { BindingNotFoundError, BindingValidationError, Definition, Handler, LayerOptions, Options, Tag, TagClass, WorkflowClass, WorkflowEvent$1 as WorkflowEvent, WorkflowEventService, WorkflowHandler, WorkflowInstance, WorkflowInstanceCreateBatchOptions, WorkflowInstanceCreateOptions, WorkflowOperationError, WorkflowOptions, WorkflowRunContext, WorkflowStep$1 as WorkflowStep, WorkflowStepContext$1 as WorkflowStepContext, WorkflowStepError, WorkflowStepNonRetryableError, WorkflowStepService, implement, make, sleep, sleepUntil, step, waitForEvent };
12
14
  }
13
15
  interface WorkflowEventService<Payload = unknown> {
14
16
  readonly raw: WorkflowEvent<unknown>;
@@ -79,8 +81,7 @@ declare namespace Definition {
79
81
  type Any = Definition$1.Any;
80
82
  }
81
83
  type LayerOptions = LayerOptions$1;
82
- type TagClass<Self, Id extends string, Payload extends Definition$1.Any["payload"], Result extends Definition$1.Any["result"]> = TagClass$1<Self, Id, Payload, Result>;
83
84
  type Handler<ROut, Self extends Definition$1.Any> = Handler$1<ROut, Self>;
84
85
  type Options<ROut, Self extends Definition$1.Any> = Options$1<ROut, Self>;
85
86
  //#endregion
86
- export { Definition, Handler, LayerOptions, Options, Tag, TagClass, WorkflowClass, WorkflowEvent$1 as WorkflowEvent, WorkflowEventService, WorkflowHandler, WorkflowOptions, WorkflowRunContext, WorkflowStep$1 as WorkflowStep, WorkflowStepContext$1 as WorkflowStepContext, WorkflowStepError, WorkflowStepNonRetryableError, WorkflowStepService, Workflow_d_exports, implement, make, sleep, sleepUntil, step, waitForEvent };
87
+ export { type BindingNotFoundError, type BindingValidationError, Definition, Handler, LayerOptions, Options, Tag, type TagClass, WorkflowClass, WorkflowEvent$1 as WorkflowEvent, WorkflowEventService, WorkflowHandler, type WorkflowInstance, type WorkflowInstanceCreateBatchOptions, type WorkflowInstanceCreateOptions, type WorkflowOperationError, WorkflowOptions, WorkflowRunContext, WorkflowStep$1 as WorkflowStep, WorkflowStepContext$1 as WorkflowStepContext, WorkflowStepError, WorkflowStepNonRetryableError, WorkflowStepService, Workflow_d_exports, implement, make, sleep, sleepUntil, step, waitForEvent };
@@ -9,7 +9,7 @@ import * as Effect from "effect/Effect";
9
9
  import * as S from "effect/Schema";
10
10
  import { Layer } from "effect";
11
11
  declare namespace WorkflowDefinition_d_exports {
12
- export { Definition, Handler, LayerOptions, Options, Tag, TagClass, Workflow, implement, make };
12
+ export { BindingNotFoundError, BindingValidationError, Definition, Handler, LayerOptions, Options, Tag, TagClass, Workflow, WorkflowInstance, WorkflowInstanceCreateBatchOptions, WorkflowInstanceCreateOptions, WorkflowOperationError, implement, make };
13
13
  }
14
14
  interface Definition<Id extends string = string, Payload extends ServiceFreeSchema = ServiceFreeSchema, Result extends ServiceFreeSchema = ServiceFreeSchema> {
15
15
  readonly id: Id;
@@ -26,7 +26,7 @@ interface Options<ROut, Self extends Definition.Any> {
26
26
  type LayerOptions = {
27
27
  readonly binding: string;
28
28
  };
29
- interface TagClass<Self, Id extends string, Payload extends ServiceFreeSchema, Result extends ServiceFreeSchema> extends Context$1.ServiceClass<Self, `effect-cf/Workflow/${Id}`, WorkflowBindingClient<Payload, Result>> {
29
+ type TagClass<Self, Id extends string, Payload extends ServiceFreeSchema, Result extends ServiceFreeSchema> = Context$1.ServiceClass<Self, `effect-cf/Workflow/${Id}`, WorkflowBindingClient<Payload, Result>> & {
30
30
  readonly id: Id;
31
31
  readonly payload: Payload;
32
32
  readonly result: Result;
@@ -36,7 +36,7 @@ interface TagClass<Self, Id extends string, Payload extends ServiceFreeSchema, R
36
36
  readonly createBatch: (batch: WorkflowInstanceCreateBatchOptions<S.Schema.Type<Payload>, S.Codec.Encoded<Payload>>) => Effect.Effect<ReadonlyArray<WorkflowInstance<S.Schema.Type<Result>>>, WorkflowOperationError | S.SchemaError, Self>;
37
37
  readonly get: (instanceId: string) => Effect.Effect<WorkflowInstance<S.Schema.Type<Result>>, WorkflowOperationError, Self>;
38
38
  readonly rawUnsafe: Effect.Effect<globalThis.Workflow<S.Codec.Encoded<Payload>>, never, Self>;
39
- }
39
+ };
40
40
  declare const make: <Id extends string, Payload extends ServiceFreeSchema, Result extends ServiceFreeSchema>(id: Id, definition: {
41
41
  readonly payload: Payload;
42
42
  readonly result: Result;
@@ -48,4 +48,4 @@ declare const Tag: <Self>() => <Id extends string, Payload extends ServiceFreeSc
48
48
  declare const Workflow: typeof Tag;
49
49
  declare const implement: <ROut, const Self extends Definition.Any>(_definition: Self, handler: Handler<ROut, Self>) => Handler<ROut, Self>;
50
50
  //#endregion
51
- export { Definition, Handler, LayerOptions, Options, Tag, TagClass, Workflow, WorkflowDefinition_d_exports, implement, make };
51
+ export { type BindingNotFoundError, type BindingValidationError, Definition, Handler, LayerOptions, Options, Tag, TagClass, Workflow, WorkflowDefinition_d_exports, type WorkflowInstance, type WorkflowInstanceCreateBatchOptions, type WorkflowInstanceCreateOptions, type WorkflowOperationError, implement, make };
package/dist/index.d.mts CHANGED
@@ -9,8 +9,8 @@ import { QueueBinding_d_exports } from "./QueueBinding.mjs";
9
9
  import { QueueDefinition_d_exports } from "./QueueDefinition.mjs";
10
10
  import { Queue_d_exports } from "./Queue.mjs";
11
11
  import { RpcTracing_d_exports } from "./RpcTracing.mjs";
12
- import { ServiceBinding_d_exports } from "./ServiceBinding.mjs";
13
12
  import { WorkerDefinition_d_exports } from "./WorkerDefinition.mjs";
13
+ import { ServiceBinding_d_exports } from "./ServiceBinding.mjs";
14
14
  import { Worker_d_exports } from "./Worker.mjs";
15
15
  import { DurableObjectState_d_exports } from "./DurableObjectState.mjs";
16
16
  import { Hyperdrive_d_exports } from "./Hyperdrive.mjs";
@@ -25,8 +25,8 @@ import { CloudflareOtlp_d_exports } from "./CloudflareOtlp.mjs";
25
25
  import { CloudflareTracer_d_exports } from "./CloudflareTracer.mjs";
26
26
  import { D1_d_exports } from "./D1.mjs";
27
27
  import { DurableObjectAlarm_d_exports } from "./DurableObjectAlarm.mjs";
28
- import { DurableObjectNamespace_d_exports } from "./DurableObjectNamespace.mjs";
29
28
  import { DurableObjectDefinition_d_exports } from "./DurableObjectDefinition.mjs";
29
+ import { DurableObjectNamespace_d_exports } from "./DurableObjectNamespace.mjs";
30
30
  import { DurableObject_d_exports } from "./DurableObject.mjs";
31
31
  import { DurableObjectRpcWebSocket_d_exports } from "./DurableObjectRpcWebSocket.mjs";
32
32
  import { DurableObjectSqlite_d_exports } from "./DurableObjectSqlite.mjs";
package/dist/index.mjs CHANGED
@@ -11,13 +11,13 @@ import { DurableObjectWebSocket_exports } from "./DurableObjectWebSocket.mjs";
11
11
  import { DurableObjectState_exports } from "./DurableObjectState.mjs";
12
12
  import { CloudflareOtlp_exports } from "./CloudflareOtlp.mjs";
13
13
  import { CloudflareTracer_exports } from "./CloudflareTracer.mjs";
14
+ import { RpcTargets_exports } from "./RpcTargets.mjs";
14
15
  import { ContainerNamespace_exports } from "./ContainerNamespace.mjs";
15
16
  import { D1_exports } from "./D1.mjs";
16
17
  import { QueueBinding_exports } from "./QueueBinding.mjs";
17
18
  import { QueueDefinition_exports } from "./QueueDefinition.mjs";
18
19
  import { Queue_exports } from "./Queue.mjs";
19
20
  import { RpcDefinition_exports } from "./RpcDefinition.mjs";
20
- import { RpcTargets_exports } from "./RpcTargets.mjs";
21
21
  import { RpcTracing_exports } from "./RpcTracing.mjs";
22
22
  import { Rpc_exports } from "./Rpc.mjs";
23
23
  import { ServiceBinding_exports } from "./ServiceBinding.mjs";
@@ -0,0 +1,5 @@
1
+ import * as Context from "effect/Context";
2
+ //#region src/internal/RpcTargets.ts
3
+ var CurrentTargets = class extends Context.Service()("effect-cf/RpcTargets") {};
4
+ //#endregion
5
+ export { CurrentTargets };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-cf",
3
- "version": "0.41.0",
3
+ "version": "0.42.0",
4
4
  "description": "Effect-native primitives for Cloudflare Workers and bindings.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/AiGateway.ts CHANGED
@@ -10,6 +10,8 @@ import type { WorkerEnvironment } from "./Environment";
10
10
  import { isWorkersAiBinding, type WorkersAiBinding } from "./WorkersAi";
11
11
  import * as ErrorMessage from "./internal/ErrorMessage";
12
12
 
13
+ export type { BindingNotFoundError, BindingValidationError } from "./Binding";
14
+
13
15
  const expectedAiGatewayBinding = "Workers AI binding with gateway()";
14
16
 
15
17
  export class AiGatewayOperationError extends Data.TaggedError("AiGatewayOperationError")<{
@@ -21,6 +21,8 @@ import * as Binding from "./Binding";
21
21
  import type { WorkerEnvironment } from "./Environment";
22
22
  import * as ErrorMessage from "./internal/ErrorMessage";
23
23
 
24
+ export type { BindingNotFoundError, BindingValidationError } from "./Binding";
25
+
24
26
  const expectedAnalyticsEngineDataset = "Analytics Engine dataset binding with writeDataPoint()";
25
27
  const defaultQueryApiBaseUrl = "https://api.cloudflare.com/client/v4";
26
28
  const textEncoder = new TextEncoder();
package/src/Artifacts.ts CHANGED
@@ -17,6 +17,8 @@ import * as Binding from "./Binding";
17
17
  import type { WorkerEnvironment } from "./Environment";
18
18
  import * as ErrorMessage from "./internal/ErrorMessage";
19
19
 
20
+ export type { BindingNotFoundError, BindingValidationError } from "./Binding";
21
+
20
22
  const expectedArtifactsBinding =
21
23
  "Artifacts binding with create(), get(), import(), list(), and delete()";
22
24
 
@@ -8,6 +8,8 @@ import * as Binding from "./Binding";
8
8
  import type { WorkerEnvironment } from "./Environment";
9
9
  import * as ErrorMessage from "./internal/ErrorMessage";
10
10
 
11
+ export type { BindingNotFoundError, BindingValidationError } from "./Binding";
12
+
11
13
  const expectedBrowserRenderingBinding = "Browser Rendering binding resource";
12
14
 
13
15
  export class BrowserRenderingOperationError extends Data.TaggedError(
@@ -6,9 +6,12 @@ import * as S from "effect/Schema";
6
6
  import type { Layer } from "effect";
7
7
 
8
8
  import * as Binding from "./Binding";
9
+ import * as RpcTargets from "./RpcTargets";
9
10
  import type { WorkerEnvironment } from "./Environment";
10
11
  import * as ErrorMessage from "./internal/ErrorMessage";
11
12
 
13
+ export type { BindingNotFoundError, BindingValidationError } from "./Binding";
14
+
12
15
  const expectedContainerNamespace = "Container namespace binding with getByName()";
13
16
 
14
17
  export type ContainerSignal = "SIGKILL" | "SIGINT" | "SIGTERM";
@@ -231,6 +234,7 @@ const tryContainerPromise = <A>(
231
234
  instance: string,
232
235
  operation: string,
233
236
  evaluate: () => Promise<A>,
237
+ target: ContainerStub,
234
238
  ): Effect.Effect<A, ContainerOperationError> =>
235
239
  Effect.tryPromise({
236
240
  try: evaluate,
@@ -241,13 +245,15 @@ const tryContainerPromise = <A>(
241
245
  operation,
242
246
  cause,
243
247
  }),
244
- });
248
+ }).pipe(Effect.tapCause(() => RpcTargets.invalidate(target)));
245
249
 
246
250
  const makeInstanceClient = <Stub extends ContainerStub>(
247
251
  definition: ContainerNamespaceDefinition,
248
252
  instance: string,
249
253
  stub: Stub,
250
254
  ): ContainerInstanceClient<Stub> => {
255
+ const attempt = <A>(operation: string, evaluate: () => Promise<A>) =>
256
+ tryContainerPromise(definition, instance, operation, evaluate, stub);
251
257
  const spanOptions = (operation: string) => ({
252
258
  attributes: { binding: definition.binding, instance, operation },
253
259
  });
@@ -256,9 +262,7 @@ const makeInstanceClient = <Stub extends ContainerStub>(
256
262
  `ContainerNamespace.${operation}`,
257
263
  spanOptions(operation),
258
264
  )(function* (hosts: ReadonlyArray<string>) {
259
- return yield* tryContainerPromise(definition, instance, operation, () =>
260
- stub[operation]([...hosts]),
261
- );
265
+ return yield* attempt(operation, () => stub[operation]([...hosts]));
262
266
  });
263
267
  const hostnameOperation = (
264
268
  operation: "allowHost" | "denyHost" | "removeAllowedHost" | "removeDeniedHost",
@@ -267,14 +271,12 @@ const makeInstanceClient = <Stub extends ContainerStub>(
267
271
  `ContainerNamespace.${operation}`,
268
272
  spanOptions(operation),
269
273
  )(function* (hostname: string) {
270
- return yield* tryContainerPromise(definition, instance, operation, () =>
271
- stub[operation](hostname),
272
- );
274
+ return yield* attempt(operation, () => stub[operation](hostname));
273
275
  });
274
276
 
275
277
  return {
276
278
  rawUnsafe: Effect.succeed(stub),
277
- state: tryContainerPromise(definition, instance, "state", () => stub.getState()).pipe(
279
+ state: attempt("state", () => stub.getState()).pipe(
278
280
  Effect.flatMap(S.decodeUnknownEffect(ContainerState)),
279
281
  Effect.mapError((cause) =>
280
282
  cause instanceof ContainerOperationError
@@ -292,41 +294,33 @@ const makeInstanceClient = <Stub extends ContainerStub>(
292
294
  "ContainerNamespace.fetch",
293
295
  spanOptions("fetch"),
294
296
  )(function* (input: RequestInfo | URL, init?: RequestInit) {
295
- return yield* tryContainerPromise(definition, instance, "fetch", () =>
296
- stub.fetch(input, init),
297
- );
297
+ return yield* attempt("fetch", () => stub.fetch(input, init));
298
298
  }),
299
299
  start: Effect.fn(
300
300
  "ContainerNamespace.start",
301
301
  spanOptions("start"),
302
302
  )(function* (options?: ContainerStartOptions, waitOptions?: ContainerWaitOptions) {
303
- return yield* tryContainerPromise(definition, instance, "start", () =>
304
- stub.start(options, waitOptions),
305
- );
303
+ return yield* attempt("start", () => stub.start(options, waitOptions));
306
304
  }),
307
305
  startAndWaitForPorts: Effect.fn(
308
306
  "ContainerNamespace.startAndWaitForPorts",
309
307
  spanOptions("startAndWaitForPorts"),
310
308
  )(function* (options?: ContainerStartAndWaitForPortsOptions) {
311
- return yield* tryContainerPromise(definition, instance, "startAndWaitForPorts", () =>
312
- stub.startAndWaitForPorts(options),
313
- );
309
+ return yield* attempt("startAndWaitForPorts", () => stub.startAndWaitForPorts(options));
314
310
  }),
315
311
  waitForPort: Effect.fn(
316
312
  "ContainerNamespace.waitForPort",
317
313
  spanOptions("waitForPort"),
318
314
  )(function* (options: ContainerWaitOptions) {
319
- return yield* tryContainerPromise(definition, instance, "waitForPort", () =>
320
- stub.waitForPort(options),
321
- );
315
+ return yield* attempt("waitForPort", () => stub.waitForPort(options));
322
316
  }),
323
317
  stop: Effect.fn(
324
318
  "ContainerNamespace.stop",
325
319
  spanOptions("stop"),
326
320
  )(function* (signal?: ContainerStopSignal) {
327
- return yield* tryContainerPromise(definition, instance, "stop", () => stub.stop(signal));
321
+ return yield* attempt("stop", () => stub.stop(signal));
328
322
  }),
329
- destroy: tryContainerPromise(definition, instance, "destroy", () => stub.destroy()).pipe(
323
+ destroy: attempt("destroy", () => stub.destroy()).pipe(
330
324
  Effect.withSpan("ContainerNamespace.destroy", spanOptions("destroy")),
331
325
  ),
332
326
  setAllowedHosts: hostListOperation("setAllowedHosts"),
@@ -352,23 +346,24 @@ export const makeClient =
352
346
  name: string,
353
347
  options?: globalThis.DurableObjectNamespaceGetDurableObjectOptions,
354
348
  ) =>
355
- Effect.try({
356
- try: () =>
357
- makeInstanceClient(
358
- definition,
359
- name,
360
- // SAFETY: getByName has a single call signature, so its return type is
361
- // exactly the namespace's stub type.
362
- namespace.getByName(name, options) as ContainerStubOf<Namespace>,
363
- ),
364
- catch: (cause) =>
365
- new ContainerOperationError({
366
- binding: definition.binding,
367
- instance: name,
368
- operation: "getByName",
369
- cause,
370
- }),
371
- });
349
+ RpcTargets.get(
350
+ namespace,
351
+ JSON.stringify(["container", name, options]),
352
+ () =>
353
+ // SAFETY: getByName returns the namespace's declared native stub type.
354
+ namespace.getByName(name, options) as ContainerStubOf<Namespace>,
355
+ ).pipe(
356
+ Effect.map((stub) => makeInstanceClient(definition, name, stub)),
357
+ Effect.mapError(
358
+ (error) =>
359
+ new ContainerOperationError({
360
+ binding: definition.binding,
361
+ instance: name,
362
+ operation: "getByName",
363
+ cause: error.cause,
364
+ }),
365
+ ),
366
+ );
372
367
 
373
368
  const byName = (
374
369
  name: string,
package/src/D1.ts CHANGED
@@ -8,6 +8,8 @@ import type { SqlClient } from "effect/unstable/sql";
8
8
  import * as Binding from "./Binding";
9
9
  import type { WorkerEnvironment } from "./Environment";
10
10
 
11
+ export type { BindingNotFoundError, BindingValidationError } from "./Binding";
12
+
11
13
  const TypeId = "~effect-cf/D1" as const;
12
14
 
13
15
  export type TypeId = typeof TypeId;
@@ -19,6 +21,18 @@ export interface D1Definition {
19
21
 
20
22
  export type D1SqlLayerOptions = Omit<D1Client.D1ClientConfig, "db">;
21
23
 
24
+ export type ServiceClass<Self, Id extends string> = Binding.BindingService<Self, Id, D1Database> & {
25
+ [TypeId]: typeof TypeId;
26
+ definition: D1Definition;
27
+ sqlLayer: (
28
+ options?: D1SqlLayerOptions,
29
+ ) => Layer.Layer<
30
+ D1Client.D1Client | SqlClient.SqlClient,
31
+ Config.ConfigError | Binding.BindingNotFoundError | Binding.BindingValidationError,
32
+ WorkerEnvironment
33
+ >;
34
+ };
35
+
22
36
  declare const D1ServiceTypeId: unique symbol;
23
37
 
24
38
  export interface D1Service<Id extends string> {
@@ -40,18 +54,12 @@ export const make = <Id extends string>(id: Id, definition: D1Definition) =>
40
54
 
41
55
  export const Service =
42
56
  <Self>() =>
43
- <Id extends string>(id: Id, definition: D1Definition) => {
57
+ <Id extends string>(id: Id, definition: D1Definition): ServiceClass<Self, Id> => {
44
58
  const tag = Binding.Service<Self>()(id, definition.binding, isD1Database, undefined, {
45
59
  expected: expectedD1Database,
46
60
  });
47
61
 
48
- const sqlLayer = (
49
- options?: D1SqlLayerOptions,
50
- ): Layer.Layer<
51
- D1Client.D1Client | SqlClient.SqlClient,
52
- Config.ConfigError | Binding.BindingNotFoundError | Binding.BindingValidationError,
53
- WorkerEnvironment
54
- > =>
62
+ const sqlLayer: ServiceClass<Self, Id>["sqlLayer"] = (options) =>
55
63
  Layer.unwrap(
56
64
  Effect.gen(function* () {
57
65
  const db = yield* tag;
@@ -19,6 +19,17 @@ import * as Runtime from "./internal/Runtime";
19
19
  import * as Telemetry from "./internal/Telemetry";
20
20
  import type { ReceiverOptions, RpcInvocationInfo } from "./RpcTracing";
21
21
 
22
+ export type { BindingNotFoundError, BindingValidationError } from "./Binding";
23
+ export type {
24
+ DurableObjectFetchError,
25
+ DurableObjectNamespaceClient,
26
+ DurableObjectRpcError,
27
+ DurableObjectStubClient,
28
+ StubCall,
29
+ StubRpc,
30
+ StubScopedCall,
31
+ } from "./DurableObjectNamespace";
32
+
22
33
  const reservedMethodNames: ReadonlySet<string> = RpcDefinition.reservedMethodNames;
23
34
 
24
35
  export type RuntimeContext<ROut> =
@@ -403,15 +414,17 @@ export type {
403
414
  LayerOptions,
404
415
  Method,
405
416
  Methods,
417
+ NativeSchema,
406
418
  NoReservedMethods,
407
419
  Options,
408
420
  ReservedMethodName,
421
+ RpcSchema,
409
422
  ServerApi,
410
423
  ServiceFreeSchema,
411
424
  TagClass,
412
425
  } from "./DurableObjectDefinition";
413
426
 
414
- export { implement, method, Tag } from "./DurableObjectDefinition";
427
+ export { implement, method, native, Tag } from "./DurableObjectDefinition";
415
428
 
416
429
  // Preserve the original public type export while using a domain-role name internally.
417
430
  export type { DurableObjectRpcApi as "DurableObjectRpcShape" };
@@ -11,41 +11,55 @@ import * as RpcDefinition from "./RpcDefinition";
11
11
  import { recordDecodedArgs } from "./internal/RpcInvocation";
12
12
  import type { WorkerEnvironment } from "./Environment";
13
13
 
14
+ export type { BindingNotFoundError, BindingValidationError } from "./Binding";
15
+ export type {
16
+ DurableObjectFetchError,
17
+ DurableObjectNamespaceClient,
18
+ DurableObjectRpcError,
19
+ DurableObjectStubClient,
20
+ StubCall,
21
+ StubRpc,
22
+ StubScopedCall,
23
+ } from "./DurableObjectNamespace";
24
+
14
25
  type ErasedInvoke<E> = (...args: ReadonlyArray<unknown>) => Effect.Effect<unknown, E>;
15
26
 
16
27
  export type ServiceFreeSchema = S.Codec<any, any, never, never>;
28
+ export type NativeSchema<Schema extends ServiceFreeSchema = ServiceFreeSchema> =
29
+ RpcDefinition.NativeSchema<Schema>;
30
+ export type RpcSchema = RpcDefinition.RpcSchema;
17
31
 
18
32
  export interface Method<
19
- Args extends ReadonlyArray<ServiceFreeSchema> = ReadonlyArray<ServiceFreeSchema>,
20
- Success extends ServiceFreeSchema = ServiceFreeSchema,
33
+ Args extends ReadonlyArray<RpcSchema> = ReadonlyArray<RpcSchema>,
34
+ Success extends RpcSchema = RpcSchema,
21
35
  > {
22
36
  readonly args: Args;
23
37
  readonly success: Success;
24
38
  }
25
39
 
26
40
  export namespace Method {
27
- export type Any = Method<ReadonlyArray<ServiceFreeSchema>, ServiceFreeSchema>;
41
+ export type Any = Method<ReadonlyArray<RpcSchema>, RpcSchema>;
28
42
 
29
- type ArgsFromSchemas<Args extends ReadonlyArray<ServiceFreeSchema>> = Args extends readonly []
43
+ type ArgsFromSchemas<Args extends ReadonlyArray<RpcSchema>> = Args extends readonly []
30
44
  ? []
31
45
  : Args extends readonly [
32
- infer Head extends ServiceFreeSchema,
33
- ...infer Tail extends ReadonlyArray<ServiceFreeSchema>,
46
+ infer Head extends RpcSchema,
47
+ ...infer Tail extends ReadonlyArray<RpcSchema>,
34
48
  ]
35
- ? [S.Schema.Type<Head>, ...ArgsFromSchemas<Tail>]
36
- : Array<S.Schema.Type<Args[number]>>;
49
+ ? [RpcDefinition.SchemaType<Head>, ...ArgsFromSchemas<Tail>]
50
+ : Array<RpcDefinition.SchemaType<Args[number]>>;
37
51
 
38
- type EncodedArgsFromSchemas<Args extends ReadonlyArray<ServiceFreeSchema>> = {
39
- [Index in keyof Args]: S.Json;
52
+ type EncodedArgsFromSchemas<Args extends ReadonlyArray<RpcSchema>> = {
53
+ [Index in keyof Args]: RpcDefinition.WireEncoded<Args[Index]>;
40
54
  };
41
55
 
42
56
  export type Args<Self extends Any> = ArgsFromSchemas<Self["args"]>;
43
57
 
44
58
  export type EncodedArgs<Self extends Any> = EncodedArgsFromSchemas<Self["args"]>;
45
59
 
46
- export type Success<Self extends Any> = S.Schema.Type<Self["success"]>;
60
+ export type Success<Self extends Any> = RpcDefinition.SchemaType<Self["success"]>;
47
61
 
48
- export type EncodedSuccess<_Self extends Any> = S.Json;
62
+ export type EncodedSuccess<Self extends Any> = RpcDefinition.WireEncoded<Self["success"]>;
49
63
  }
50
64
 
51
65
  export type Methods = Record<string, Method.Any>;
@@ -178,20 +192,22 @@ export type TagClass<
178
192
  /**
179
193
  * Defines a single RPC method schema in a Durable Object definition.
180
194
  */
181
- export function method<Success extends ServiceFreeSchema>(definition: {
195
+ export function method<Success extends RpcSchema>(definition: {
182
196
  readonly success: Success;
183
197
  }): Method<readonly [], Success>;
184
198
  export function method<
185
- const Args extends ReadonlyArray<ServiceFreeSchema>,
186
- Success extends ServiceFreeSchema,
199
+ const Args extends ReadonlyArray<RpcSchema>,
200
+ Success extends RpcSchema,
187
201
  >(definition: { readonly args: Args; readonly success: Success }): Method<Args, Success>;
188
202
  export function method(definition: {
189
- readonly args?: ReadonlyArray<ServiceFreeSchema>;
190
- readonly success: ServiceFreeSchema;
203
+ readonly args?: ReadonlyArray<RpcSchema>;
204
+ readonly success: RpcSchema;
191
205
  }): Method {
192
206
  return RpcDefinition.method(definition);
193
207
  }
194
208
 
209
+ export const native = RpcDefinition.native;
210
+
195
211
  const makeDefinition = <Id extends string, const MethodDefinitions extends Methods>(
196
212
  id: Id,
197
213
  methods: MethodDefinitions & NoReservedMethods<MethodDefinitions>,
@@ -120,12 +120,24 @@ type StubMethodCloudflareReturn<
120
120
  Method extends keyof Api,
121
121
  > = RpcInvocation.AsyncMethodCloudflareReturn<Api, Method>;
122
122
 
123
- type StubCall<R, Api extends object> = <Method extends StubMethodKey<Api>>(
123
+ export type StubCall<R, Api extends object> = <Method extends StubMethodKey<Api>>(
124
124
  stub: DurableObjectStubClient<Api>,
125
125
  method: Method,
126
126
  ...args: StubMethodArgs<Api, Method>
127
127
  ) => Effect.Effect<StubMethodSuccess<Api, Method>, DurableObjectRpcError, R>;
128
128
 
129
+ export type StubRpc<R, Api extends object> = <Method extends StubMethodKey<Api>>(
130
+ stub: DurableObjectStubClient<Api>,
131
+ method: Method,
132
+ ...args: StubMethodArgs<Api, Method>
133
+ ) => Effect.Effect<StubMethodCloudflareReturn<Api, Method>, DurableObjectRpcError, R>;
134
+
135
+ export type StubScopedCall<R, Api extends object> = <Method extends StubMethodKey<Api>>(
136
+ stub: DurableObjectStubClient<Api>,
137
+ method: Method,
138
+ ...args: StubMethodArgs<Api, Method>
139
+ ) => Effect.Effect<Awaited<StubMethodSuccess<Api, Method>>, DurableObjectRpcError, Scope.Scope | R>;
140
+
129
141
  type DurableObjectDirectClient<R, Api extends object> = {
130
142
  readonly fetch: (
131
143
  input: RequestInfo | URL,
@@ -227,22 +239,14 @@ export type DurableObjectNamespaceEffectClient<
227
239
  *
228
240
  * Most application code should use {@link call} instead.
229
241
  */
230
- readonly rpc: <Method extends StubMethodKey<Api>>(
231
- stub: DurableObjectStubClient<Api>,
232
- method: Method,
233
- ...args: StubMethodArgs<Api, Method>
234
- ) => Effect.Effect<StubMethodCloudflareReturn<Api, Method>, DurableObjectRpcError>;
242
+ readonly rpc: StubRpc<never, Api>;
235
243
  /**
236
244
  * Invokes a Durable Object RPC method, resolves Cloudflare's RPC result, and
237
245
  * decodes the success value when the namespace was created from a definition.
238
246
  *
239
247
  * This is the normal choice when application code wants the final typed value.
240
248
  */
241
- readonly call: <Method extends StubMethodKey<Api>>(
242
- stub: DurableObjectStubClient<Api>,
243
- method: Method,
244
- ...args: StubMethodArgs<Api, Method>
245
- ) => Effect.Effect<StubMethodSuccess<Api, Method>, DurableObjectRpcError>;
249
+ readonly call: StubCall<never, Api>;
246
250
  /**
247
251
  * Invokes a Durable Object RPC method in the current `Scope`, resolves
248
252
  * Cloudflare's RPC result, decodes definition-backed success values, and
@@ -252,11 +256,7 @@ export type DurableObjectNamespaceEffectClient<
252
256
  * Use this for RPC methods that return Cloudflare RPC resources or other
253
257
  * disposable objects whose lifetime should be tied to an Effect scope.
254
258
  */
255
- readonly scopedCall: <Method extends StubMethodKey<Api>>(
256
- stub: DurableObjectStubClient<Api>,
257
- method: Method,
258
- ...args: StubMethodArgs<Api, Method>
259
- ) => Effect.Effect<Awaited<StubMethodSuccess<Api, Method>>, DurableObjectRpcError, Scope.Scope>;
259
+ readonly scopedCall: StubScopedCall<never, Api>;
260
260
  /**
261
261
  * Exposes the underlying native Durable Object namespace binding.
262
262
  *
@@ -292,25 +292,9 @@ export type DurableObjectNamespaceStaticClient<
292
292
  input: RequestInfo | URL,
293
293
  init?: RequestInit,
294
294
  ) => Effect.Effect<globalThis.Response, DurableObjectFetchError, R>;
295
- readonly rpc: <Method extends StubMethodKey<Api>>(
296
- stub: DurableObjectStubClient<Api>,
297
- method: Method,
298
- ...args: StubMethodArgs<Api, Method>
299
- ) => Effect.Effect<StubMethodCloudflareReturn<Api, Method>, DurableObjectRpcError, R>;
300
- readonly call: <Method extends StubMethodKey<Api>>(
301
- stub: DurableObjectStubClient<Api>,
302
- method: Method,
303
- ...args: StubMethodArgs<Api, Method>
304
- ) => Effect.Effect<StubMethodSuccess<Api, Method>, DurableObjectRpcError, R>;
305
- readonly scopedCall: <Method extends StubMethodKey<Api>>(
306
- stub: DurableObjectStubClient<Api>,
307
- method: Method,
308
- ...args: StubMethodArgs<Api, Method>
309
- ) => Effect.Effect<
310
- Awaited<StubMethodSuccess<Api, Method>>,
311
- DurableObjectRpcError,
312
- Scope.Scope | R
313
- >;
295
+ readonly rpc: StubRpc<R, Api>;
296
+ readonly call: StubCall<R, Api>;
297
+ readonly scopedCall: StubScopedCall<R, Api>;
314
298
  readonly rawUnsafe: () => Effect.Effect<DurableObjectNamespaceClient<Api>, never, R>;
315
299
  };
316
300
 
package/src/Email.ts CHANGED
@@ -14,6 +14,8 @@ import * as Binding from "./Binding";
14
14
  import type { WorkerEnvironment } from "./Environment";
15
15
  import * as ErrorMessage from "./internal/ErrorMessage";
16
16
 
17
+ export type { BindingNotFoundError, BindingValidationError } from "./Binding";
18
+
17
19
  const expectedSendEmailBinding = "Send Email binding with send()";
18
20
  const textEncoder = new TextEncoder();
19
21