effect-cf 0.39.0 → 0.40.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # effect-cf
2
2
 
3
+ ## 0.40.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#146](https://github.com/danieljvdm/effect-cf/pull/146) [`376c9cc`](https://github.com/danieljvdm/effect-cf/commit/376c9ccb16c7ee6a3d6ac2c6f8d6c91ad0b237fc) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Add schema-bound scheduling, cancellation, and transactions through `DurableObjectAlarm.Tag`. Register the service's complete `handlers(...)` implementation in a Durable Object's `alarms:` option, then yield the service to schedule work. Missing registration or handlers fail typechecking. Scheduling checks tag/payload pairs and schema-encodes payloads before storage.
8
+
9
+ Durable Object entrypoints provide registered alarm services to application layers and handlers. The raw scheduler is provided automatically and remains available for dynamic tags; existing explicit layers and handler-only `define(...)` calls remain supported.
10
+
11
+ Unknown stored alarm tags now report `StoredAlarmDecodeError` and follow the delivery failure policy instead of being silently acknowledged. Applications intentionally retiring tags can handle them through `onFailure`.
12
+
13
+ ## 0.39.1
14
+
15
+ ### Patch Changes
16
+
17
+ - [#142](https://github.com/danieljvdm/effect-cf/pull/142) [`4ecf192`](https://github.com/danieljvdm/effect-cf/commit/4ecf192733193f4c3b5869abd992c1658f5ad7a6) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Rebuild with Vite+ 0.3.0 and apply its formatter's source layout updates. Public APIs and runtime behavior are unchanged.
18
+
3
19
  ## 0.39.0
4
20
 
5
21
  ### Minor Changes
package/README.md CHANGED
@@ -45,10 +45,18 @@ const greeting = Effect.gen(function* () {
45
45
 
46
46
  Declare `SETTINGS` in `wrangler.jsonc` and pass `SettingsLive` to `Worker.make`. Other bindings use the same tag/layer pattern.
47
47
 
48
- The [counter example](https://github.com/danieljvdm/effect-cf/tree/main/examples/counter) shows `DurableObject.Tag`, storage, a typed RPC call, and the complete Wrangler configuration.
48
+ The [document outbox example](https://github.com/danieljvdm/effect-cf/tree/main/examples/outbox) saves document revisions and their delivery alarms atomically, then archives them to R2 outside the transaction.
49
49
 
50
50
  For atomic application writes and alarm changes, see the [alarm transaction example](tests/fixtures/alarm-transaction-consumer.ts) and [API contract](src/DurableObjectAlarm.ts).
51
51
 
52
+ Define a typed alarm service with `class Alarms extends DurableObjectAlarm.Tag<Alarms>()("Alarms", { ...schemas }) {}`. Pass `Alarms.handlers({ ...implementations })` to the DO's `alarms:` option, then `yield* Alarms` to schedule or cancel alarms and open transactions. All declared handlers are required. The registration provides the service to application layers, initialization, and event handlers; declaring schemas alone does not provide a scheduler.
53
+
54
+ Scheduling accepts decoded payloads, encodes them with the declared schema, and checks that the result is JSON before storage. Transaction callbacks expose the same typed mutations and retain the raw scheduler's rollback and callback-lifetime rules.
55
+
56
+ `DurableObject.make` and tagged definitions' `.make` still provide the raw `DurableObjectAlarm` service automatically for dynamic tags and JSON payloads. `DurableObjectAlarm.define({ ... }).handlers(...)` remains a handler-only helper for raw scheduling. No alarm tables or native alarms are created until the scheduler is used. Outside these entrypoints, provide the raw scheduler layer explicitly. A typed registration exposes `layer` and `run` for custom runtimes and tests; custom runtimes must install both.
57
+
58
+ Unknown stored tags produce `StoredAlarmDecodeError` and follow the configured delivery failure policy rather than being acknowledged silently. Use the raw scheduler's `cancelAlarm` to remove retired tags, including repeating alarms.
59
+
52
60
  ## Cloudflare Observability traces
53
61
 
54
62
  `CloudflareTracer.layer` sends existing `Effect.withSpan` and named `Effect.fn`
@@ -1,5 +1,5 @@
1
1
  import { ComputerArtifactsClient } from "./ComputerArtifacts.mjs";
2
- import { t as DurableObjectState } from "./DurableObjectState-CpgAmFqo.mjs";
2
+ import { t as DurableObjectState } from "./DurableObjectState-DJ0K-zyd.mjs";
3
3
  import { Context, Effect, Layer, Schema, Scope, Stream } from "effect";
4
4
  import { CommitView, GitClient, GitCloneOptions, GitCommitOptions, GitDiffOptions, GitFetchOptions, GitLogOptions, GitUpdateRefOptions } from "@cloudflare/computer/git";
5
5
  import { ExecSyncResult, RuntimeExecOptions, RuntimeGetOptions, RuntimeKillOptions, ShellValue, SkippedEntry, ThinkWorkspaceCompatibility, WorkspaceClient, WorkspaceRuntimeResult, WorkspaceRuntimeValue as WorkspaceRuntimeValue$1 } from "@cloudflare/computer";
@@ -581,7 +581,8 @@ var ComputerWorkspace = class ComputerWorkspace extends Context.Service()("effec
581
581
  * releases its RPC client when the layer scope closes.
582
582
  */
583
583
  static layer = Layer.effect(ComputerWorkspace, Effect.gen(function* () {
584
- const host = lookup((yield* DurableObjectState).raw);
584
+ const state = yield* DurableObjectState;
585
+ const host = lookup(state.raw);
585
586
  if (host === void 0) return yield* Effect.die("ComputerWorkspace.layer requires a Durable Object class built with withComputerWorkspace");
586
587
  const computer = yield* Effect.tryPromise({
587
588
  try: () => import("@cloudflare/computer"),
@@ -1,4 +1,4 @@
1
- import { i as WorkerContextWaitUntilOptions } from "./Worker-Dl6_Pijl.mjs";
1
+ import { i as WorkerContextWaitUntilOptions } from "./Worker-gV4mDqIs.mjs";
2
2
  import { Cause, Context, Duration, Effect, Option, Schema } from "effect";
3
3
  declare namespace DurableObjectStorage_d_exports {
4
4
  export { DurableObjectStorage, DurableObjectTransaction, SchemaBackedSyncKvStorage, SqlCursor, SqlStorage, SqlStorageValue, StorageOperationError, SyncKvDefinition, SyncKvStorage, fromDurableObjectStorage };
package/dist/Mcp.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as NativeRequest } from "./Worker-Dl6_Pijl.mjs";
1
+ import { n as NativeRequest } from "./Worker-gV4mDqIs.mjs";
2
2
  import { Effect, Option } from "effect";
3
3
  import { CreateMcpHandlerOptions, ServerOptions } from "@modelcontextprotocol/server";
4
4
  import { Tool, Toolkit } from "effect/unstable/ai";
package/dist/Vitest.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { c as WorkerEnvironment, s as WorkerEnv } from "./Binding-DKcLrQCM.mjs";
2
- import { n as DurableObjectStateService, t as DurableObjectState } from "./DurableObjectState-CpgAmFqo.mjs";
3
- import { o as WorkflowInstanceStatusName } from "./WorkflowBinding-CvJT9hB5.mjs";
2
+ import { n as DurableObjectStateService, t as DurableObjectState } from "./DurableObjectState-DJ0K-zyd.mjs";
3
+ import { o as WorkflowInstanceStatusName } from "./WorkflowBinding-DtVykUCz.mjs";
4
4
  import { Effect, Layer, Schema } from "effect";
5
5
  import { DurableObject } from "cloudflare:workers";
6
6
  import { adminSecretsStore as adminSecretsStore$1, getQueueResult, introspectWorkflow as introspectWorkflow$1, introspectWorkflowInstance as introspectWorkflowInstance$1 } from "cloudflare:test";
@@ -330,14 +330,14 @@ interface ServiceFetcher {
330
330
  type RpcClient<Api> = { readonly [Key in keyof Api as Key extends string ? Api[Key] extends ((...args: Array<any>) => any) ? Key : never : never]: Api[Key]; };
331
331
  type ReservedMethodName$2 = ReservedMethodName$1 | "fetch";
332
332
  type ServiceBindingClient<Api extends object> = ServiceFetcher & RpcClient<Provider<Api, ReservedMethodName$2>>;
333
- type ApiFromDefinition<Definition$12> = Definition$12 extends Definition.Any ? ServerApi$1<Definition$12> : never;
333
+ type ApiFromDefinition<Definition$4> = Definition$4 extends Definition.Any ? ServerApi$1<Definition$4> : never;
334
334
  type ApiOrDefinition<Api extends object, Definition> = [Api] extends [never] ? ApiFromDefinition<Definition> : Api;
335
335
  /**
336
336
  * Binding metadata used to create an Effect service from a Worker binding.
337
337
  */
338
- interface ServiceBindingDefinition<Definition$7 extends Definition.Any | undefined = undefined> {
338
+ interface ServiceBindingDefinition<Definition$5 extends Definition.Any | undefined = undefined> {
339
339
  readonly binding: string;
340
- readonly definition?: Definition$7;
340
+ readonly definition?: Definition$5;
341
341
  /** Append live trace context only when the receiver also enables rpcTracing. */
342
342
  readonly rpcTracing?: boolean;
343
343
  }
@@ -371,9 +371,9 @@ type ServiceMethodArgs<Api, Method extends keyof Api> = AsyncMethodArgs<Api, Met
371
371
  type ServiceMethodSuccess<Api, Method extends keyof Api> = AsyncMethodSuccess<Api, Method>;
372
372
  type ServiceMethodCloudflareReturn<Api, Method extends keyof Api> = AsyncMethodCloudflareReturn<Api, Method>;
373
373
  type ServiceCall<R, Api> = <Method extends ServiceMethodKey<Api>>(method: Method, ...args: ServiceMethodArgs<Api, Method>) => Effect.Effect<ServiceMethodSuccess<Api, Method>, ServiceBindingRpcError, R>;
374
- type DefinitionDirectMethods<R, Definition$4 extends Definition.Any> = { readonly [Method in Definition$3.MethodNames<Definition$4>]: (...args: Method$2.Args<Definition$4["methods"][Method]>) => Effect.Effect<Method$2.Success<Definition$4["methods"][Method]>, ServiceBindingRpcError, R>; };
375
- type DirectMethods<R, Definition$13> = Definition$13 extends Definition.Any ? DefinitionDirectMethods<R, Definition$13> : {};
376
- type ServiceBindingEffectClient<Api extends object, Definition$8 extends Definition.Any | undefined = undefined> = DirectMethods<never, Definition$8> & {
374
+ type DefinitionDirectMethods<R, Definition$9 extends Definition.Any> = { readonly [Method in Definition$3.MethodNames<Definition$9>]: (...args: Method$2.Args<Definition$9["methods"][Method]>) => Effect.Effect<Method$2.Success<Definition$9["methods"][Method]>, ServiceBindingRpcError, R>; };
375
+ type DirectMethods<R, Definition$12> = Definition$12 extends Definition.Any ? DefinitionDirectMethods<R, Definition$12> : {};
376
+ type ServiceBindingEffectClient<Api extends object, Definition$10 extends Definition.Any | undefined = undefined> = DirectMethods<never, Definition$10> & {
377
377
  readonly fetch: (input: RequestInfo | URL, init?: RequestInit) => Effect.Effect<globalThis.Response, ServiceBindingFetchError>;
378
378
  /**
379
379
  * Invokes a Worker RPC method and returns Cloudflare's raw RPC result.
@@ -402,7 +402,7 @@ type ServiceBindingEffectClient<Api extends object, Definition$8 extends Definit
402
402
  */
403
403
  readonly scopedCall: <Method extends ServiceMethodKey<Api>>(method: Method, ...args: ServiceMethodArgs<Api, Method>) => Effect.Effect<Awaited<ServiceMethodSuccess<Api, Method>>, ServiceBindingRpcError, Scope.Scope>;
404
404
  };
405
- type ServiceBindingStaticClient<R, Api extends object, Definition$5 extends Definition.Any | undefined = undefined> = DirectMethods<R, Definition$5> & {
405
+ type ServiceBindingStaticClient<R, Api extends object, Definition$11 extends Definition.Any | undefined = undefined> = DirectMethods<R, Definition$11> & {
406
406
  readonly fetch: (input: RequestInfo | URL, init?: RequestInit) => Effect.Effect<globalThis.Response, ServiceBindingFetchError, R>;
407
407
  readonly rpc: <Method extends ServiceMethodKey<Api>>(method: Method, ...args: ServiceMethodArgs<Api, Method>) => Effect.Effect<ServiceMethodCloudflareReturn<Api, Method>, ServiceBindingRpcError, R>;
408
408
  readonly call: <Method extends ServiceMethodKey<Api>>(method: Method, ...args: ServiceMethodArgs<Api, Method>) => Effect.Effect<ServiceMethodSuccess<Api, Method>, ServiceBindingRpcError, R>;
@@ -410,17 +410,17 @@ type ServiceBindingStaticClient<R, Api extends object, Definition$5 extends Defi
410
410
  };
411
411
  type ServiceBindingValue = Schema.Schema.Type<typeof Schema.Unknown>;
412
412
  declare const isServiceBindingClient: <Api extends object>(value: ServiceBindingValue) => value is ServiceBindingClient<Api>;
413
- declare const makeClient: <Api extends object, const Definition$10 extends Definition.Any | undefined = undefined>(definition: ServiceBindingDefinition<Definition$10>) => ((service: ServiceBindingClient<Api>) => ServiceBindingEffectClient<Api, Definition$10>);
414
- declare const layer: <Self, Api extends object, const Definition$11 extends Definition.Any | undefined = undefined>(tag: Context.Service<Self, ServiceBindingEffectClient<Api, Definition$11>>, definition: ServiceBindingDefinition<Definition$11>) => import("effect/Layer").Layer<Self, BindingNotFoundError | BindingValidationError, WorkerEnvironment>;
415
- declare const Service: <Self, Api extends object = never>() => <Id extends string, const Definition$6 extends Definition.Any | undefined = undefined>(id: Id, definition: ServiceBindingDefinition<Definition$6>) => BindingService<Self, Id, ServiceBindingEffectClient<ApiOrDefinition<Api, Definition$6>, Definition$6>> & DirectMethods<Self, Definition$6> & {
413
+ declare const makeClient: <Api extends object, const Definition$6 extends Definition.Any | undefined = undefined>(definition: ServiceBindingDefinition<Definition$6>) => ((service: ServiceBindingClient<Api>) => ServiceBindingEffectClient<Api, Definition$6>);
414
+ declare const layer: <Self, Api extends object, const Definition$13 extends Definition.Any | undefined = undefined>(tag: Context.Service<Self, ServiceBindingEffectClient<Api, Definition$13>>, definition: ServiceBindingDefinition<Definition$13>) => import("effect/Layer").Layer<Self, BindingNotFoundError | BindingValidationError, WorkerEnvironment>;
415
+ declare const Service: <Self, Api extends object = never>() => <Id extends string, const Definition$8 extends Definition.Any | undefined = undefined>(id: Id, definition: ServiceBindingDefinition<Definition$8>) => BindingService<Self, Id, ServiceBindingEffectClient<ApiOrDefinition<Api, Definition$8>, Definition$8>> & DirectMethods<Self, Definition$8> & {
416
416
  readonly [TypeId]: typeof TypeId;
417
- readonly definition: ServiceBindingDefinition<Definition$6>;
417
+ readonly definition: ServiceBindingDefinition<Definition$8>;
418
418
  readonly fetch: (input: URL | RequestInfo<unknown, CfProperties<unknown>>, init?: RequestInit<CfProperties<unknown>> | undefined) => Effect.Effect<Response, ServiceBindingFetchError, Self>;
419
- readonly rpc: <Method extends ServiceMethodKey<ApiOrDefinition<Api, Definition$6>>>(method: Method, ...args: AsyncMethodArgs<ApiOrDefinition<Api, Definition$6>, Method>) => Effect.Effect<Result$1<AsyncMethodSuccess<ApiOrDefinition<Api, Definition$6>, Method>>, ServiceBindingRpcError, Self>;
420
- readonly call: <Method extends ServiceMethodKey<ApiOrDefinition<Api, Definition$6>>>(method: Method, ...args: AsyncMethodArgs<ApiOrDefinition<Api, Definition$6>, Method>) => Effect.Effect<AsyncMethodSuccess<ApiOrDefinition<Api, Definition$6>, Method>, ServiceBindingRpcError, Self>;
421
- readonly scopedCall: <Method extends ServiceMethodKey<ApiOrDefinition<Api, Definition$6>>>(method: Method, ...args: AsyncMethodArgs<ApiOrDefinition<Api, Definition$6>, Method>) => Effect.Effect<Awaited<AsyncMethodSuccess<ApiOrDefinition<Api, Definition$6>, Method>>, ServiceBindingRpcError, Self | Scope.Scope>;
419
+ readonly rpc: <Method extends ServiceMethodKey<ApiOrDefinition<Api, Definition$8>>>(method: Method, ...args: AsyncMethodArgs<ApiOrDefinition<Api, Definition$8>, Method>) => Effect.Effect<Result$1<AsyncMethodSuccess<ApiOrDefinition<Api, Definition$8>, Method>>, ServiceBindingRpcError, Self>;
420
+ readonly call: <Method extends ServiceMethodKey<ApiOrDefinition<Api, Definition$8>>>(method: Method, ...args: AsyncMethodArgs<ApiOrDefinition<Api, Definition$8>, Method>) => Effect.Effect<AsyncMethodSuccess<ApiOrDefinition<Api, Definition$8>, Method>, ServiceBindingRpcError, Self>;
421
+ readonly scopedCall: <Method extends ServiceMethodKey<ApiOrDefinition<Api, Definition$8>>>(method: Method, ...args: AsyncMethodArgs<ApiOrDefinition<Api, Definition$8>, Method>) => Effect.Effect<Awaited<AsyncMethodSuccess<ApiOrDefinition<Api, Definition$8>, Method>>, ServiceBindingRpcError, Self | Scope.Scope>;
422
422
  };
423
- declare const makeDirectMethods: <R, Api, Definition$9 extends Definition.Any | undefined>(rpcDefinition: Definition$9 | undefined, call: ServiceCall<R, Api>) => DirectMethods<R, Definition$9>;
423
+ declare const makeDirectMethods: <R, Api, Definition$7 extends Definition.Any | undefined>(rpcDefinition: Definition$7 | undefined, call: ServiceCall<R, Api>) => DirectMethods<R, Definition$7>;
424
424
  declare namespace WorkerDefinition_d_exports {
425
425
  export { Api, Definition, HandlerEffect, Handlers, LayerOptions, Method$1 as Method, Methods, NoReservedMethods, Options, ReservedMethodName$1 as ReservedMethodName, ServerApi$1 as ServerApi, ServiceFreeSchema, Tag, TagClass, Worker, implement, make$1 as make, method };
426
426
  }
@@ -1,5 +1,5 @@
1
1
  import { c as WorkerEnvironment, r as BindingValidationError, t as BindingNotFoundError } from "./Binding-DKcLrQCM.mjs";
2
- import { S as ServiceFreeSchema } from "./Worker-Dl6_Pijl.mjs";
2
+ import { S as ServiceFreeSchema } from "./Worker-gV4mDqIs.mjs";
3
3
  import { Context, Effect, Option, Schema } from "effect";
4
4
  declare namespace WorkflowBinding_d_exports {
5
5
  export { WorkflowBindingClient, WorkflowBindingDefinition, WorkflowInstance, WorkflowInstanceCreateBatchOptions, WorkflowInstanceCreateOptions, WorkflowInstanceEvent, WorkflowInstanceLocationHint, WorkflowInstanceRestartOptions, WorkflowInstanceStatus, WorkflowInstanceStatusName, WorkflowInstanceTerminateOptions, WorkflowOperationError, WorkflowResultDecodeError, isWorkflow, layer, makeClient };