effect-cf 0.30.0 → 0.32.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.32.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#119](https://github.com/danieljvdm/effect-cf/pull/119) [`34b1abf`](https://github.com/danieljvdm/effect-cf/commit/34b1abfab7ee963b9d28c143ad29c678ee88483e) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Add hibernation-aware Durable Object Effect RPC WebSockets that restore idle connections, reset lost non-resumable operations instead of hanging, and use Cloudflare auto-responses for idle heartbeats. Applications can opt specific cursor-backed streams into logical subscription reconstruction on the same socket and Effect request ID. Declaration schemas validate persisted resume state before reconstruction. Explicit application checkpoints establish the replay boundary, report attachment persistence failures in the typed error channel, and prevent stale stock acknowledgements from advancing a reconstructed stream.
8
+
9
+ ## 0.31.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#116](https://github.com/danieljvdm/effect-cf/pull/116) [`98d343b`](https://github.com/danieljvdm/effect-cf/commit/98d343ba7d5a427789ec8e7fc030668987eab1ea) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Move the optional `effect-cf/vitest` peer from `@cloudflare/vitest-pool-workers` to `@cloudflare/vitest-plugin` `^1.0.0`. The package API is unchanged: keep using `cloudflareTest()` and `cloudflare:test`.
14
+
15
+ - [#118](https://github.com/danieljvdm/effect-cf/pull/118) [`80730a8`](https://github.com/danieljvdm/effect-cf/commit/80730a82b26728e824ba6e4ed8bdbe290428baa6) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Pin the Cloudflare Workers runtime stack to workerd `1.20260820.1` (`@cloudflare/workers-types@^5.20260820.1`, wrangler `4.125.0`, recommended `compatibility_date` `2026-08-20`).
16
+
17
+ Images gains text rasterization (`text` / `process` text input), hosted `createDirectUpload` and `signedUrl`, and `response(options?)` for extra headers. Workflow instances gain `delete`, optional `terminate({ rollback })`, and `create`/`createBatch` `locationHint` via the updated types. `Worker.WorkerContext` now wraps the non-experimental `ExecutionContext.abort`.
18
+
3
19
  ## 0.30.0
4
20
 
5
21
  ### Minor Changes
package/README.md CHANGED
@@ -4,7 +4,8 @@ Effect-native Cloudflare primitives for Workers, Durable Objects, Containers, bi
4
4
 
5
5
  ## Install
6
6
 
7
- `effect-cf` targets Effect `^4.0.0-beta.105`.
7
+ `effect-cf` targets Effect `^4.0.0-beta.105` and Cloudflare workerd `1.20260820.1`
8
+ (`@cloudflare/workers-types@5.20260820.1`, recommended `compatibility_date` `2026-08-20`).
8
9
 
9
10
  ```bash
10
11
  bun add effect-cf "effect@^4.0.0-beta.105"
@@ -72,12 +73,12 @@ Runtime creation belongs at Cloudflare entrypoints, not inside binding helpers.
72
73
  - `Rpc` - Cloudflare RPC type helpers and scoped disposal utilities
73
74
  - `WebTransport` - truthful WebTransport/HTTP-3 boundary: typed runtime capabilities and decoded inbound protocol metadata
74
75
  - `WorkerConfig` - Effect `Config` helpers backed by Cloudflare `env`
75
- - `effect-cf/vitest` - Effect-native runners and scoped test helpers for Cloudflare's Vitest Workers pool
76
+ - `effect-cf/vitest` - Effect-native runners and scoped test helpers for Cloudflare's Workers Vitest plugin
76
77
 
77
- ## Vitest Workers Pool
78
+ ## Vitest Workers Plugin
78
79
 
79
- Install and configure a `^0.21.3` release of
80
- [`@cloudflare/vitest-pool-workers`](https://github.com/cloudflare/workers-sdk/tree/main/packages/vitest-pool-workers#readme),
80
+ Install and configure a `^1.0.0` release of
81
+ [`@cloudflare/vitest-plugin`](https://github.com/cloudflare/workers-sdk/tree/main/packages/vitest-plugin#readme),
81
82
  then import the test-only helpers from `effect-cf/vitest`. The `fetch` runner
82
83
  constructs the Worker with the current test environment and waits for all
83
84
  `waitUntil` work before completing the Effect.
@@ -109,7 +110,7 @@ it.effect("reads Wrangler vars", () =>
109
110
  ```
110
111
 
111
112
  Queue consumers can be invoked with typed message bodies while retaining the
112
- pool's acknowledgement and retry result:
113
+ plugin's acknowledgement and retry result:
113
114
 
114
115
  ```ts
115
116
  it.effect("acknowledges a job", () =>
@@ -130,7 +131,7 @@ it.effect("acknowledges a job", () =>
130
131
 
131
132
  Scheduled handlers and Pages Functions use the same lifecycle behavior: their
132
133
  Effects complete only after the event's `waitUntil` work has settled. Pages
133
- tests must configure the `ASSETS` binding required by Pool Workers.
134
+ tests must configure the `ASSETS` binding required by the Workers Vitest plugin.
134
135
 
135
136
  ```ts
136
137
  it.effect("runs the cron handler", () =>
@@ -719,10 +720,26 @@ export const resizeAvatar = (image: Images.ImageInputValue) =>
719
720
  },
720
721
  );
721
722
 
722
- return yield* result.response;
723
+ return yield* result.response();
723
724
  });
724
725
  ```
725
726
 
727
+ ## Cloudflare runtime pin
728
+
729
+ `effect-cf` develops and tests against a fixed Cloudflare Workers runtime stack. Keep consumer
730
+ `compatibility_date` and optional `@cloudflare/workers-types` peers at or above this pin:
731
+
732
+ | Pin | Version |
733
+ | ------------------------------------------- | -------------- |
734
+ | workerd | `1.20260820.1` |
735
+ | `@cloudflare/workers-types` (optional peer) | `5.20260820.1` |
736
+ | wrangler (repo catalog / examples) | `4.125.0` |
737
+ | Recommended `compatibility_date` | `2026-08-20` |
738
+
739
+ The date in the `workerd` / `@cloudflare/workers-types` version is the API surface this package wraps.
740
+ Repo catalog pins live in the root `package.json` `catalog` field (`@cloudflare/workers-types`, `wrangler`).
741
+ `wrangler@4.125.0` pulls `workerd@1.20260820.1` and peers `@cloudflare/workers-types@^5.20260820.1`.
742
+
726
743
  ## Email Example
727
744
 
728
745
  Email tags expose Cloudflare Email Service `send_email` bindings as Effect-wrapped `send(...)` operations. Structured messages are validated against documented Email Sending limits before reaching the binding, and Cloudflare's `E_*` error codes are surfaced on `EmailOperationError.code`.
@@ -962,7 +979,100 @@ if (Worker.isWebSocketUpgrade(request)) {
962
979
  }
963
980
  ```
964
981
 
965
- Use `DurableObjectRpcWebSocket.layer(...)` for Effect RPC-over-WebSocket transports. It owns protocol parsing and RPC client bookkeeping; use `DurableWebSocket` for general application sockets, rooms, presence, and broadcast flows.
982
+ ### Hibernation-aware Effect RPC WebSockets
983
+
984
+ `DurableObjectRpcWebSocket.layer(...)` adapts Effect RPC to Cloudflare's hibernatable WebSocket API. Build the layer in the Durable Object runtime and forward all three WebSocket lifecycle events:
985
+
986
+ ```ts
987
+ import { Effect, Layer } from "effect";
988
+ import { RpcSerialization, RpcServer } from "effect/unstable/rpc";
989
+ import { DurableObject, DurableObjectRpcWebSocket, Worker } from "effect-cf";
990
+
991
+ const RpcLive = RpcServer.layer(MyRpcs).pipe(
992
+ Layer.provideMerge(DurableObjectRpcWebSocket.layer({ tag: "my-rpc" })),
993
+ Layer.provide(MyRpcHandlers),
994
+ Layer.provide(RpcSerialization.layerJson),
995
+ );
996
+
997
+ const MyObjectLive = DurableObject.make(RpcLive, {
998
+ fetch: Effect.gen(function* () {
999
+ const request = yield* Worker.NativeRequest;
1000
+
1001
+ if (!Worker.isWebSocketUpgrade(request)) {
1002
+ return new Response("Expected WebSocket upgrade", { status: 426 });
1003
+ }
1004
+
1005
+ const transport = yield* DurableObjectRpcWebSocket.DurableObjectRpcWebSocket;
1006
+ const upgrade = yield* transport.acceptUpgrade({
1007
+ tags: ["room:general"],
1008
+ attachment: { roomId: "general" },
1009
+ });
1010
+
1011
+ return upgrade.response;
1012
+ }),
1013
+ webSocketMessage: (socket, message) =>
1014
+ Effect.gen(function* () {
1015
+ const transport = yield* DurableObjectRpcWebSocket.DurableObjectRpcWebSocket;
1016
+
1017
+ yield* transport.message(socket, message);
1018
+ }),
1019
+ webSocketClose: (socket) =>
1020
+ Effect.gen(function* () {
1021
+ const transport = yield* DurableObjectRpcWebSocket.DurableObjectRpcWebSocket;
1022
+
1023
+ yield* transport.close(socket);
1024
+ }),
1025
+ webSocketError: (socket, cause) =>
1026
+ Effect.gen(function* () {
1027
+ const transport = yield* DurableObjectRpcWebSocket.DurableObjectRpcWebSocket;
1028
+
1029
+ yield* transport.error(socket, cause);
1030
+ }),
1031
+ });
1032
+
1033
+ export class MyDurableObject extends MyObjectLive {}
1034
+ ```
1035
+
1036
+ `DurableObject.make` builds a new managed runtime whenever Cloudflare constructs or reconstructs the object. During that build, the RPC layer calls `getWebSockets(tag)` and registers tagged sockets before the triggering lifecycle handler runs. A completed finite call can therefore be followed by idle hibernation and another finite call on the same physical socket.
1037
+
1038
+ This is a hibernation-aware RPC transport, not a durable RPC runtime. The adapter stores versioned state under the `attachmentKey` namespace, which defaults to `effectCloudflareRpcClientId`, and shallow-merges it with application-owned object fields. Its RPC tag is added alongside application tags. Application code that later replaces an attachment must preserve the reserved namespace; the adapter requires object-shaped attachments. Keep resume descriptors compact because Cloudflare caps the entire serialized attachment, including application fields, at 16,384 bytes. Legacy numeric client-ID metadata is migrated when read.
1039
+
1040
+ Each non-notification request stays marked pending until its terminal `Exit` is sent or the request is interrupted. If a new constructor finds a pending non-resumable request, it quarantines the socket and closes it with WebSocket code `1012` before dispatching the event that woke the object. Effect's stock socket protocol reports this as an `RpcClientError` containing `SocketCloseError`, so the affected call or stream fails instead of hanging. The socket transport may reconnect for later calls, but the adapter never replays a non-resumable request. Retrying a mutation requires application-level idempotency or deduplication. Notifications are also not durable and have no delivery acknowledgement.
1041
+
1042
+ The default `heartbeat: "auto-response"` policy installs Cloudflare's exact text Ping/Pong auto-response while at least one RPC socket exists and no non-resumable RPC operation is active. The stock Effect client's five-second Ping therefore does not run Durable Object JavaScript while the socket is idle or while an explicitly resumable subscription waits for data. The adapter creates no timer. A non-resumable call or stream removes the global auto-response so a Ping wakes a newly reconstructed object and triggers its pending-operation reset. Cloudflare provides only one auto-response pair per Durable Object, across every accepted socket. Use `"passthrough"` if unrelated WebSocket protocols share the same object.
1043
+
1044
+ Use `heartbeat: "passthrough"` for a non-text serialization or when the application owns a different auto-response pair. That mode does not alter the pair; the application is responsible for ensuring a lost pending operation still wakes and resets. With the default policy, a conflicting application pair fails layer construction instead of being overwritten.
1045
+
1046
+ Streams are non-resumable unless their RPC tag matches a declaration passed in `resumableStreams`. Constructor recreation resets an ordinary active stream with code `1012`.
1047
+
1048
+ An explicitly resumable stream persists its original Effect request ID, RPC tag, application subscription key, compact resume descriptor, and last application checkpoint in the socket attachment. Each declaration supplies `resumeDescriptorSchema` and `checkpointSchema`; a new constructor validates both persisted values before it rebuilds anything. Invalid state resets that socket with code `1012` instead of reaching application reconstruction. Valid state becomes an encoded request written through the new `RpcServer.Protocol` with the original request ID. Effect runs request decoding, middleware, authorization, and the handler again. The physical socket stays open, so the stock Effect client routes later `Chunk` messages into the existing client `Stream`.
1049
+
1050
+ This reconstructs a declared logical subscription. It does not restore the original Effect fiber, scope, stream, queue, or middleware context. The application must keep a durable event log and rebuild the stream after its cursor. Delivery is at least once. If hibernation lands after a chunk reaches the client but before its checkpoint is stored, the rebuilt handler emits that chunk again. Apply events idempotently by cursor, then call a finite checkpoint RPC. Retention, cursor expiry, snapshots, and resync remain application concerns. This transport does not provide exactly-once delivery or generic stream resumption.
1051
+
1052
+ The declaration also gives the transport a stable token for each encoded chunk value. A cursor/token must identify one logical event for the full lifetime of that subscription. Distinct events must not share it; a replay of the same event reuses it. The adapter ignores stock request-ID-only stream `Ack` messages for resumable requests. It persists the matching explicit checkpoint before releasing the current server chunk latch, and an acknowledgement left over from an earlier activation cannot release a later chunk. If attachment serialization fails, `checkpoint` fails with `DurableWebSocketAttachmentError` and the transport resets the socket with code `1012`; it never releases or sends a chunk whose replay state was not stored. Interrupt and terminal `Exit` remove the persisted descriptor.
1053
+
1054
+ The compiled [`ResumableEventLog.example.ts`](../../examples/todo-rpc-ws/durable-objects/todo-store/src/ResumableEventLog.example.ts) defines a standard `RpcGroup`, cursor-backed Durable Object SQL event log, `RpcServer.layer`, resumable declaration, checkpoint handler using `Rpc.ServerClient.id`, and complete constructor/event wiring. Its client-side ordering is the important part:
1055
+
1056
+ ```ts
1057
+ import { Effect, Stream } from "effect";
1058
+
1059
+ client.SubscribeEvents({ subscriptionKey, topic, after }).pipe(
1060
+ Stream.runForEach((event) =>
1061
+ applyEventIfNew(event).pipe(
1062
+ Effect.andThen(
1063
+ client.CheckpointSubscription({
1064
+ subscriptionKey,
1065
+ cursor: event.cursor,
1066
+ }),
1067
+ ),
1068
+ ),
1069
+ ),
1070
+ );
1071
+ ```
1072
+
1073
+ Checkpoint only after `applyEventIfNew` commits. A replayed cursor must make that function a no-op. `CheckpointSubscription` is an ordinary non-resumable finite RPC, so make it idempotent and safe for the client to retry. Map `DurableWebSocketAttachmentError` into that RPC's declared error channel. The checkpoint call must be able to run while stream handlers are active. Keep Effect's default unbounded RPC server concurrency, or set a bound above the maximum number of simultaneously open streams so checkpoint calls retain capacity. If the activation disappears after checkpoint persistence but before that RPC sends its `Exit`, the socket resets with `1012`. The client reconnects and starts a new subscription after its durably applied cursor. Register the same declaration on every constructor activation and keep its `id`, schemas, and checkpoint token semantics stable for stored attachments.
1074
+
1075
+ `accept(socket, tags)` remains available for a manually created, not-yet-accepted server socket. Prefer `transport.acceptUpgrade(...)` for new upgrades so the socket is accepted exactly once. Use the general `DurableObjectWebSocket` module instead for rooms, presence, broadcasts, or other non-RPC protocols.
966
1076
 
967
1077
  ## WebTransport and HTTP/3
968
1078
 
@@ -1,5 +1,5 @@
1
1
  import { ComputerArtifactsClient } from "./ComputerArtifacts.mjs";
2
- import { t as DurableObjectState } from "./DurableObjectState-D3k-WRnd.mjs";
2
+ import { t as DurableObjectState } from "./DurableObjectState-B0A0Y1ef.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";
@@ -1,4 +1,4 @@
1
- import { t as DurableObjectState } from "./DurableObjectState-CepagPkX.mjs";
1
+ import { t as DurableObjectState } from "./DurableObjectState-D1Ibr6k0.mjs";
2
2
  import { fromClient } from "./ComputerArtifacts.mjs";
3
3
  import { t as lookup } from "./ComputerWorkspaceHostRegistry-CY5Fv4Ng.mjs";
4
4
  import { Context, Effect, Layer, Predicate, Schema, Stream } from "effect";
@@ -834,6 +834,8 @@ interface WorkerContextService {
834
834
  waitUntil<A, E, R, R2 = never>(effect: Effect.Effect<A, E, R>, options?: WorkerContextWaitUntilOptions<E, R2>): Effect.Effect<void, never, R | R2>;
835
835
  waitUntilPropagating<A, E, R, R2 = never>(effect: Effect.Effect<A, E, R>, options?: Omit<WorkerContextWaitUntilOptions<E, R2>, "mode">): Effect.Effect<void, never, R | R2>;
836
836
  readonly passThroughOnException: Effect.Effect<void>;
837
+ /** Abort the current stateless Worker invocation (`ExecutionContext.abort`). */
838
+ abort(reason?: string): Effect.Effect<void>;
837
839
  }
838
840
  declare const WorkerContext_base: Context.ServiceClass<WorkerContext, "effect-cf/WorkerContext", WorkerContextService>;
839
841
  /**
@@ -1038,4 +1040,4 @@ declare class DurableObjectState extends DurableObjectState_base {}
1038
1040
  */
1039
1041
  declare const fromDurableObjectState: (state: globalThis.DurableObjectState) => DurableObjectStateService;
1040
1042
  //#endregion
1041
- export { Rpc_d_exports as C, StorageOperationError as D, DurableObjectStorage_d_exports as E, Provider as S, DurableWebSocket as T, Definition$3 as _, NativeRequest as a, RpcDefinition_d_exports as b, WorkerDefinition_d_exports as c, AsyncMethodCloudflareReturn as d, AsyncMethodKey as f, QueueBinding_d_exports as g, QueueDefinition_d_exports as h, ExecutionContext as i, ServiceBinding_d_exports as l, Queue_d_exports as m, DurableObjectStateService as n, WorkerContext as o, AsyncMethodSuccess as p, DurableObjectState_d_exports as r, Worker_d_exports as s, DurableObjectState as t, AsyncMethodArgs as u, Method$2 as v, DurableObjectWebSocket_d_exports as w, ServiceFreeSchema$1 as x, ReservedMethodName$3 as y };
1043
+ export { StorageOperationError as A, Rpc_d_exports as C, DurableWebSocket as D, DurableObjectWebSocket_d_exports as E, DurableWebSocketAttachmentError as O, Provider as S, AcceptedUpgrade as T, Definition$3 as _, NativeRequest as a, RpcDefinition_d_exports as b, WorkerDefinition_d_exports as c, AsyncMethodCloudflareReturn as d, AsyncMethodKey as f, QueueBinding_d_exports as g, QueueDefinition_d_exports as h, ExecutionContext as i, DurableObjectStorage_d_exports as k, ServiceBinding_d_exports as l, Queue_d_exports as m, DurableObjectStateService as n, WorkerContext as o, AsyncMethodSuccess as p, DurableObjectState_d_exports as r, Worker_d_exports as s, DurableObjectState as t, AsyncMethodArgs as u, Method$2 as v, AcceptUpgradeOptions as w, ServiceFreeSchema$1 as x, ReservedMethodName$3 as y };
@@ -308,7 +308,8 @@ const fromExecutionContext = (ctx, runPromiseExit = (effect) => Effect.runPromis
308
308
  raw: ctx,
309
309
  waitUntil: (effect, options) => schedule(effect, options, options?.mode ?? "observe"),
310
310
  waitUntilPropagating: (effect, options) => schedule(effect, options, "propagate"),
311
- passThroughOnException: Effect.sync(() => ctx.passThroughOnException())
311
+ passThroughOnException: Effect.sync(() => ctx.passThroughOnException()),
312
+ abort: (reason) => Effect.sync(() => ctx.abort(reason))
312
313
  };
313
314
  };
314
315
  //#endregion
@@ -351,4 +352,4 @@ const runPromiseExitPreservingTypedFailures = async (context, effect) => {
351
352
  return exit;
352
353
  };
353
354
  //#endregion
354
- export { DurableObjectWebSocket_exports as a, fromExecutionContext as i, DurableObjectState_exports as n, fromWebSocket as o, fromDurableObjectState as r, DurableObjectStorage_exports as s, DurableObjectState as t };
355
+ export { DurableObjectWebSocket_exports as a, DurableObjectStorage_exports as c, fromExecutionContext as i, DurableObjectState_exports as n, DurableWebSocketAttachmentError as o, fromDurableObjectState as r, fromWebSocket as s, DurableObjectState as t };
package/dist/Vitest.d.mts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { c as WorkerEnvironment, s as WorkerEnv } from "./Binding-xJJJPmiD.mjs";
2
- import { n as DurableObjectStateService, t as DurableObjectState } from "./DurableObjectState-D3k-WRnd.mjs";
3
- import { o as WorkflowInstanceStatusName } from "./WorkflowBinding-CtrmxfdT.mjs";
2
+ import { n as DurableObjectStateService, t as DurableObjectState } from "./DurableObjectState-B0A0Y1ef.mjs";
3
+ import { o as WorkflowInstanceStatusName } from "./WorkflowBinding-B9_S8tX2.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";
7
7
  //#region src/Vitest.d.ts
8
8
  /**
9
- * Provides the Workers pool environment as both {@link WorkerEnvironment} and
9
+ * Provides the Workers test environment as both {@link WorkerEnvironment} and
10
10
  * the active Effect `ConfigProvider`.
11
11
  */
12
12
  declare const layer: Layer.Layer<WorkerEnvironment>;
@@ -54,7 +54,7 @@ type PagesEventContextInitData<Context> = Context extends globalThis.EventContex
54
54
  } : {
55
55
  readonly data: Data;
56
56
  } : never;
57
- /** Initialization accepted by Pool Workers for a Pages Function. */
57
+ /** Initialization accepted by the Workers Vitest plugin for a Pages Function. */
58
58
  type PagesEventContextInit<Function extends AnyPagesFunction> = PagesEventContextInitBase & PagesEventContextInitParams<Parameters<Function>[0]> & PagesEventContextInitData<Parameters<Function>[0]>;
59
59
  /**
60
60
  * Invokes a Pages Function with a typed event context and drains its
@@ -64,7 +64,7 @@ declare const pages: <Function extends AnyPagesFunction>(handler: Function, init
64
64
  interface QueueWorker {
65
65
  queue(batch: globalThis.MessageBatch): Promise<void>;
66
66
  }
67
- /** Input message accepted by Pool Workers' `createMessageBatch` helper. */
67
+ /** Input message accepted by the Workers Vitest plugin's `createMessageBatch` helper. */
68
68
  type QueueMessage<Body> = {
69
69
  readonly id: string;
70
70
  readonly timestamp: Date;
@@ -74,7 +74,7 @@ type QueueMessage<Body> = {
74
74
  } | {
75
75
  readonly serializedBody: ArrayBuffer | ArrayBufferView;
76
76
  });
77
- /** Acknowledgement and retry result returned by Pool Workers. */
77
+ /** Acknowledgement and retry result returned by the Workers Vitest plugin. */
78
78
  type QueueResult = Awaited<ReturnType<typeof getQueueResult>>;
79
79
  /** Result of invoking a queue consumer through {@link queue}. */
80
80
  interface QueueRunResult<Body> {
@@ -83,7 +83,7 @@ interface QueueRunResult<Body> {
83
83
  }
84
84
  /**
85
85
  * Invokes an Effect-backed queue consumer, drains its `waitUntil` work, and
86
- * returns Pool Workers' acknowledgement and retry result.
86
+ * returns the Workers Vitest plugin's acknowledgement and retry result.
87
87
  */
88
88
  declare const queue: <Body, Instance extends QueueWorker>(Worker: WorkerConstructor<Instance>, queueName: string, messages: readonly QueueMessage<Body>[], workerEnv?: Cloudflare.Env | undefined) => Effect.Effect<QueueRunResult<Body>, never, never>;
89
89
  /**
@@ -110,7 +110,7 @@ declare const reset: () => Effect.Effect<void, never, never>;
110
110
  declare const abortAllDurableObjects: () => Effect.Effect<void, never, never>;
111
111
  /** Gracefully evicts all running Durable Objects while preserving durable storage. */
112
112
  declare const evictAllDurableObjects: (options?: DurableObjectEvictionOptions | undefined) => Effect.Effect<void, never, never>;
113
- /** A D1 migration accepted by Pool Workers. */
113
+ /** A D1 migration accepted by the Workers Vitest plugin. */
114
114
  interface D1Migration {
115
115
  readonly name: string;
116
116
  readonly queries: ReadonlyArray<string>;
@@ -125,7 +125,7 @@ interface SecretsStoreSecret {
125
125
  readonly uuid: string;
126
126
  };
127
127
  }
128
- /** Effect-native wrapper around Pool Workers' Secrets Store admin API. */
128
+ /** Effect-native wrapper around the Workers Vitest plugin's Secrets Store admin API. */
129
129
  interface SecretsStoreAdmin {
130
130
  readonly raw: NativeSecretsStoreAdmin;
131
131
  readonly create: (value: string) => Effect.Effect<string>;
package/dist/Vitest.mjs CHANGED
@@ -1,18 +1,18 @@
1
1
  import { a as WorkerEnvironment, i as WorkerConfig } from "./ErrorMessage-BM0K-Nik.mjs";
2
- import { r as fromDurableObjectState, t as DurableObjectState } from "./DurableObjectState-CepagPkX.mjs";
2
+ import { r as fromDurableObjectState, t as DurableObjectState } from "./DurableObjectState-D1Ibr6k0.mjs";
3
3
  import { ConfigProvider, Effect, Exit, Layer } from "effect";
4
4
  import { env } from "cloudflare:workers";
5
5
  import { abortAllDurableObjects as abortAllDurableObjects$1, adminSecretsStore as adminSecretsStore$1, applyD1Migrations as applyD1Migrations$1, createExecutionContext, createMessageBatch, createPagesEventContext, createScheduledController, evictAllDurableObjects as evictAllDurableObjects$1, evictDurableObject as evictDurableObject$1, getQueueResult, introspectWorkflow as introspectWorkflow$1, introspectWorkflowInstance as introspectWorkflowInstance$1, listDurableObjectIds as listDurableObjectIds$1, reset as reset$1, runDurableObjectAlarm as runDurableObjectAlarm$1, runInDurableObject as runInDurableObject$1, waitOnExecutionContext } from "cloudflare:test";
6
6
  //#region src/Vitest.ts
7
7
  /**
8
- * Effect-native helpers for tests running in Cloudflare's Vitest Workers pool.
8
+ * Effect-native helpers for tests running in Cloudflare's Workers Vitest plugin.
9
9
  *
10
10
  * Import this module through the `effect-cf/vitest` subpath. It is intended to
11
11
  * run inside the Workers test runtime, where `cloudflare:test` is available.
12
12
  */
13
13
  const currentEnv = env;
14
14
  /**
15
- * Provides the Workers pool environment as both {@link WorkerEnvironment} and
15
+ * Provides the Workers test environment as both {@link WorkerEnvironment} and
16
16
  * the active Effect `ConfigProvider`.
17
17
  */
18
18
  const layer = Layer.mergeAll(Layer.succeed(WorkerEnvironment, currentEnv), ConfigProvider.layer(WorkerConfig.providerFromEnv(currentEnv)));
@@ -50,7 +50,7 @@ const pages = Effect.fn("effect-cf/vitest/pages")(function* (handler, init) {
50
50
  });
51
51
  /**
52
52
  * Invokes an Effect-backed queue consumer, drains its `waitUntil` work, and
53
- * returns Pool Workers' acknowledgement and retry result.
53
+ * returns the Workers Vitest plugin's acknowledgement and retry result.
54
54
  */
55
55
  const queue = Effect.fn("effect-cf/vitest/queue")(function* (Worker, queueName, messages, workerEnv = currentEnv) {
56
56
  return yield* withExecutionContext(Effect.fnUntraced(function* (context) {
@@ -146,7 +146,7 @@ const runWorkflowModifier = Effect.fnUntraced(function* (register, use) {
146
146
  if (callbackExit !== void 0 && Exit.isFailure(callbackExit)) return callbackExit;
147
147
  throw cause;
148
148
  }
149
- if (callbackExit === void 0) throw new Error("Pool Workers did not invoke the Workflow modifier callback");
149
+ if (callbackExit === void 0) throw new Error("The Workers Vitest plugin did not invoke the Workflow modifier callback");
150
150
  return callbackExit;
151
151
  });
152
152
  });
@@ -1,14 +1,16 @@
1
1
  import { c as WorkerEnvironment, r as BindingValidationError, t as BindingNotFoundError } from "./Binding-xJJJPmiD.mjs";
2
- import { x as ServiceFreeSchema } from "./DurableObjectState-D3k-WRnd.mjs";
2
+ import { x as ServiceFreeSchema } from "./DurableObjectState-B0A0Y1ef.mjs";
3
3
  import { Context, Effect, Option, Schema } from "effect";
4
4
  declare namespace WorkflowBinding_d_exports {
5
- export { WorkflowBindingClient, WorkflowBindingDefinition, WorkflowInstance, WorkflowInstanceCreateBatchOptions, WorkflowInstanceCreateOptions, WorkflowInstanceEvent, WorkflowInstanceRestartOptions, WorkflowInstanceStatus, WorkflowInstanceStatusName, WorkflowOperationError, WorkflowResultDecodeError, isWorkflow, layer, makeClient };
5
+ export { WorkflowBindingClient, WorkflowBindingDefinition, WorkflowInstance, WorkflowInstanceCreateBatchOptions, WorkflowInstanceCreateOptions, WorkflowInstanceEvent, WorkflowInstanceLocationHint, WorkflowInstanceRestartOptions, WorkflowInstanceStatus, WorkflowInstanceStatusName, WorkflowInstanceTerminateOptions, WorkflowOperationError, WorkflowResultDecodeError, isWorkflow, layer, makeClient };
6
6
  }
7
7
  type WorkflowInstanceCreateOptions<Payload> = Omit<CloudflareWorkflowInstanceCreateOptions<Payload>, "params">;
8
8
  type WorkflowInstanceCreateBatchOptions<Payload, EncodedPayload = unknown> = ReadonlyArray<{
9
9
  readonly payload: Payload;
10
10
  } & WorkflowInstanceCreateOptions<EncodedPayload>>;
11
11
  type WorkflowInstanceRestartOptions = CloudflareWorkflowInstanceRestartOptions;
12
+ type WorkflowInstanceTerminateOptions = CloudflareWorkflowInstanceTerminateOptions;
13
+ type WorkflowInstanceLocationHint = CloudflareWorkflowInstanceLocationHint;
12
14
  type WorkflowInstanceStatusName = CloudflareInstanceStatus["status"];
13
15
  interface WorkflowInstanceStatus<Result> {
14
16
  readonly status: WorkflowInstanceStatusName;
@@ -23,8 +25,9 @@ interface WorkflowInstance<Result> {
23
25
  readonly id: string;
24
26
  readonly pause: Effect.Effect<void, WorkflowOperationError>;
25
27
  readonly resume: Effect.Effect<void, WorkflowOperationError>;
26
- readonly terminate: Effect.Effect<void, WorkflowOperationError>;
28
+ readonly terminate: (options?: WorkflowInstanceTerminateOptions) => Effect.Effect<void, WorkflowOperationError>;
27
29
  readonly restart: (options?: WorkflowInstanceRestartOptions) => Effect.Effect<void, WorkflowOperationError>;
30
+ readonly delete: Effect.Effect<void, WorkflowOperationError>;
28
31
  readonly status: Effect.Effect<WorkflowInstanceStatus<Result>, WorkflowOperationError | WorkflowResultDecodeError>;
29
32
  readonly sendEvent: (event: WorkflowInstanceEvent) => Effect.Effect<void, WorkflowOperationError>;
30
33
  }
package/dist/index.d.mts CHANGED
@@ -1,14 +1,15 @@
1
1
  import { a as Environment_d_exports, c as WorkerEnvironment, i as Binding_d_exports, n as BindingService, o as WorkerConfig, r as BindingValidationError, s as WorkerEnv, t as BindingNotFoundError } from "./Binding-xJJJPmiD.mjs";
2
2
  import { l as Artifacts_d_exports } from "./Artifacts-DnHQA-Ax.mjs";
3
- import { C as Rpc_d_exports, D as StorageOperationError, E as DurableObjectStorage_d_exports, S as Provider, T as DurableWebSocket, _ as Definition$4, a as NativeRequest, b as RpcDefinition_d_exports, c as WorkerDefinition_d_exports, d as AsyncMethodCloudflareReturn, f as AsyncMethodKey, g as QueueBinding_d_exports, h as QueueDefinition_d_exports, i as ExecutionContext, l as ServiceBinding_d_exports, m as Queue_d_exports, o as WorkerContext, p as AsyncMethodSuccess, r as DurableObjectState_d_exports, s as Worker_d_exports, t as DurableObjectState, u as AsyncMethodArgs, v as Method$2, w as DurableObjectWebSocket_d_exports, x as ServiceFreeSchema$1, y as ReservedMethodName$2 } from "./DurableObjectState-D3k-WRnd.mjs";
3
+ import { A as StorageOperationError, C as Rpc_d_exports, D as DurableWebSocket, E as DurableObjectWebSocket_d_exports, O as DurableWebSocketAttachmentError, S as Provider, T as AcceptedUpgrade, _ as Definition$4, a as NativeRequest, b as RpcDefinition_d_exports, c as WorkerDefinition_d_exports, d as AsyncMethodCloudflareReturn, f as AsyncMethodKey, g as QueueBinding_d_exports, h as QueueDefinition_d_exports, i as ExecutionContext, k as DurableObjectStorage_d_exports, l as ServiceBinding_d_exports, m as Queue_d_exports, o as WorkerContext, p as AsyncMethodSuccess, r as DurableObjectState_d_exports, s as Worker_d_exports, t as DurableObjectState, u as AsyncMethodArgs, v as Method$2, w as AcceptUpgradeOptions, x as ServiceFreeSchema$1, y as ReservedMethodName$2 } from "./DurableObjectState-B0A0Y1ef.mjs";
4
4
  import { t as Hyperdrive_d_exports } from "./Hyperdrive-z-9fFz15.mjs";
5
5
  import { t as ContainerNamespace_d_exports } from "./ContainerNamespace-CFjiLw8b.mjs";
6
- import { a as WorkflowInstanceCreateOptions, i as WorkflowInstanceCreateBatchOptions, n as WorkflowBinding_d_exports, r as WorkflowInstance, s as WorkflowOperationError, t as WorkflowBindingClient } from "./WorkflowBinding-CtrmxfdT.mjs";
6
+ import { a as WorkflowInstanceCreateOptions, i as WorkflowInstanceCreateBatchOptions, n as WorkflowBinding_d_exports, r as WorkflowInstance, s as WorkflowOperationError, t as WorkflowBindingClient } from "./WorkflowBinding-B9_S8tX2.mjs";
7
7
  import { Cause, Config, Context, Data, DateTime, Duration, Effect, Layer, Option, Predicate, Redacted, Schema, Scope } from "effect";
8
8
  import { Headers as Headers$1, HttpClient, HttpClientResponse } from "effect/unstable/http";
9
9
  import { OtlpExporter, OtlpResource } from "effect/unstable/observability";
10
10
  import { D1Client } from "@effect/sql-d1";
11
11
  import { DurableObject, WorkflowEntrypoint, WorkflowEvent, WorkflowSleepDuration, WorkflowStep, WorkflowStepConfig, WorkflowStepContext, WorkflowStepEvent, WorkflowTimeoutDuration } from "cloudflare:workers";
12
+ import * as RpcMessage from "effect/unstable/rpc/RpcMessage";
12
13
  import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
13
14
  import * as RpcServer from "effect/unstable/rpc/RpcServer";
14
15
  import { SqliteClient } from "@effect/sql-sqlite-do";
@@ -1331,16 +1332,77 @@ declare class DurableObjectAlarm extends DurableObjectAlarm_base {
1331
1332
  static readonly layer: Layer.Layer<DurableObjectAlarm, never, DurableObjectState>;
1332
1333
  }
1333
1334
  declare namespace DurableObjectRpcWebSocket_d_exports {
1334
- export { DurableObjectRpcWebSocket, DurableObjectRpcWebSocketService, LayerOptions$7 as LayerOptions, NativeWebSocketMessage, layer$6 as layer };
1335
+ export { DurableObjectRpcWebSocket, DurableObjectRpcWebSocketService, HeartbeatPolicy, LayerOptions$7 as LayerOptions, NativeWebSocketMessage, ResumableStreamDeclaration, RpcWebSocketAttachment, layer$6 as layer, resumableStream };
1336
+ }
1337
+ /** Heartbeat handling for Effect's application-level RPC Ping messages. */
1338
+ type HeartbeatPolicy = "auto-response" | "passthrough";
1339
+ /** Object-shaped application attachment fields that can coexist with adapter metadata. */
1340
+ type RpcWebSocketAttachment = object;
1341
+ /** A resumable RPC stream declaration understood by the websocket transport. */
1342
+ interface ResumableStreamDeclaration<ResumeDescriptor = unknown, Checkpoint = unknown> {
1343
+ /** Stable declaration identifier. Change it when the persisted representation changes. */
1344
+ readonly id: string;
1345
+ /** RPC tag matched against encoded client requests. */
1346
+ readonly rpcTag: string;
1347
+ /** Validates a resume descriptor restored from a websocket attachment. */
1348
+ readonly resumeDescriptorSchema: Schema.Decoder<ResumeDescriptor>;
1349
+ /** Validates an acknowledged checkpoint restored from a websocket attachment. */
1350
+ readonly checkpointSchema: Schema.Decoder<Checkpoint>;
1351
+ /**
1352
+ * Extracts compact persisted state from an initial encoded request. Do not
1353
+ * recycle a subscription key for an unrelated logical subscription while a
1354
+ * delayed checkpoint for the previous subscription can still arrive.
1355
+ */
1356
+ readonly identify: (request: RpcMessage.RequestEncoded) => Option.Option<{
1357
+ readonly subscriptionKey: string;
1358
+ readonly resumeDescriptor: ResumeDescriptor;
1359
+ readonly acknowledgedCheckpoint: Checkpoint;
1360
+ }>;
1361
+ /** Rebuilds the encoded request fields used to restart a handler. */
1362
+ readonly rebuild: (options: {
1363
+ readonly subscriptionKey: string;
1364
+ readonly resumeDescriptor: ResumeDescriptor;
1365
+ readonly acknowledgedCheckpoint: Checkpoint;
1366
+ }) => {
1367
+ readonly payload: unknown;
1368
+ readonly headers?: ReadonlyArray<readonly [string, string]> | undefined;
1369
+ readonly traceId?: string | undefined;
1370
+ readonly spanId?: string | undefined;
1371
+ readonly sampled?: boolean | undefined;
1372
+ };
1373
+ /** Extracts the durable checkpoint represented by one encoded stream value. */
1374
+ readonly checkpointFromValue: (value: RpcMessage.ResponseChunkEncoded["values"][number]) => Option.Option<Checkpoint>;
1375
+ /**
1376
+ * Produces the checkpoint wire token. A logical event must keep the same
1377
+ * token when replayed, and unrelated events must never reuse it during the
1378
+ * lifetime of a subscription key.
1379
+ */
1380
+ readonly checkpointToken: (checkpoint: Checkpoint) => string;
1335
1381
  }
1382
+ type AnyResumableStreamDeclaration = ResumableStreamDeclaration<any, any>;
1383
+ /** Declares an explicitly resumable RPC stream. */
1384
+ declare const resumableStream: <ResumeDescriptor, Checkpoint>(declaration: ResumableStreamDeclaration<ResumeDescriptor, Checkpoint>) => ResumableStreamDeclaration<ResumeDescriptor, Checkpoint>;
1336
1385
  /**
1337
1386
  * Configuration for {@link layer}.
1338
1387
  */
1339
1388
  interface LayerOptions$7 {
1340
1389
  /** Tag used to select hibernated sockets. */
1341
1390
  readonly tag?: string | undefined;
1342
- /** Socket attachment key used to persist client ids across hibernation. */
1391
+ /** Socket attachment namespace used to persist adapter metadata across hibernation. */
1343
1392
  readonly attachmentKey?: string | undefined;
1393
+ /**
1394
+ * Heartbeat behavior. `"auto-response"` (the default) installs Cloudflare's
1395
+ * hibernation-safe text Ping/Pong response while an RPC socket exists and no
1396
+ * non-resumable RPC operation is active, then removes it while one is pending.
1397
+ * `"passthrough"` leaves the Durable Object's existing auto-response
1398
+ * configuration unchanged and makes the application responsible for waking a
1399
+ * lost pending operation.
1400
+ * Cloudflare's pair is global to the Durable Object, so use `"passthrough"`
1401
+ * when RPC and unrelated websocket protocols share one object.
1402
+ */
1403
+ readonly heartbeat?: HeartbeatPolicy | undefined;
1404
+ /** Explicit stream declarations that may be reconstructed after activation loss. */
1405
+ readonly resumableStreams?: ReadonlyArray<AnyResumableStreamDeclaration> | undefined;
1344
1406
  }
1345
1407
  /** Native websocket event payload accepted by Cloudflare Durable Objects. */
1346
1408
  type NativeWebSocketMessage = string | ArrayBuffer;
@@ -1348,10 +1410,28 @@ type NativeWebSocketMessage = string | ArrayBuffer;
1348
1410
  * Service API used to wire websocket lifecycle events to Effect RPC server protocol.
1349
1411
  */
1350
1412
  interface DurableObjectRpcWebSocketService {
1351
- readonly accept: (socket: DurableWebSocket) => Effect.Effect<void>;
1413
+ /** Accepts a new, not-yet-accepted socket with the RPC tag and any application tags. */
1414
+ readonly accept: (socket: DurableWebSocket, tags?: ReadonlyArray<string>) => Effect.Effect<void>;
1415
+ /**
1416
+ * Creates and accepts a websocket upgrade without double-accepting the server
1417
+ * socket. Application attachment fields are shallow-merged with the adapter's
1418
+ * metadata namespace.
1419
+ */
1420
+ readonly acceptUpgrade: <Attachment extends RpcWebSocketAttachment = RpcWebSocketAttachment>(options?: AcceptUpgradeOptions<Attachment>) => Effect.Effect<AcceptedUpgrade<Attachment>, DurableWebSocketAttachmentError>;
1352
1421
  readonly message: (socket: DurableWebSocket, message: NativeWebSocketMessage) => Effect.Effect<void>;
1353
1422
  readonly close: (socket: DurableWebSocket) => Effect.Effect<void>;
1354
1423
  readonly error: (socket: DurableWebSocket, cause: unknown) => Effect.Effect<void>;
1424
+ /**
1425
+ * Persists forward checkpoint progress for a resumable stream. Returns `true`
1426
+ * only when the checkpoint advances the current pending chunk batch. A failed
1427
+ * websocket attachment write resets the connection and fails with
1428
+ * `DurableWebSocketAttachmentError`.
1429
+ */
1430
+ readonly checkpoint: <ResumeDescriptor, Checkpoint>(declaration: ResumableStreamDeclaration<ResumeDescriptor, Checkpoint>, options: {
1431
+ readonly clientId: number;
1432
+ readonly subscriptionKey: string;
1433
+ readonly checkpoint: Checkpoint;
1434
+ }) => Effect.Effect<boolean, DurableWebSocketAttachmentError>;
1355
1435
  }
1356
1436
  declare const DurableObjectRpcWebSocket_base: Context.ServiceClass<DurableObjectRpcWebSocket, "effect-cf/DurableObjectRpcWebSocket", DurableObjectRpcWebSocketService>;
1357
1437
  /**
@@ -1359,7 +1439,13 @@ declare const DurableObjectRpcWebSocket_base: Context.ServiceClass<DurableObject
1359
1439
  */
1360
1440
  declare class DurableObjectRpcWebSocket extends DurableObjectRpcWebSocket_base {}
1361
1441
  /**
1362
- * Builds a layer that bridges Durable Object websocket events to `RpcServer.Protocol`.
1442
+ * Builds a hibernation-aware transport that bridges Durable Object websocket
1443
+ * events to `RpcServer.Protocol`.
1444
+ *
1445
+ * The layer restores idle tagged sockets and explicitly declared resumable
1446
+ * streams after constructor recreation. A socket that lost any other in-flight
1447
+ * request is closed with code 1012, which the stock Effect socket protocol
1448
+ * reports as an `RpcClientError` containing `SocketCloseError`.
1363
1449
  */
1364
1450
  declare const layer$6: (options?: LayerOptions$7) => Layer.Layer<RpcServer.Protocol | DurableObjectRpcWebSocket, never, DurableObjectState | RpcSerialization.RpcSerialization>;
1365
1451
  declare namespace DurableObjectSqlite_d_exports {
@@ -1491,7 +1577,7 @@ declare const layer$4: <Self>(tag: Context.Service<Self, EmailClient>, definitio
1491
1577
  declare const make$5: <Id extends string>(id: Id) => TagClass$6<EmailService<Id>, Id>;
1492
1578
  declare const Tag$7: <Self>() => <Id extends string>(id: Id) => TagClass$6<Self, Id>;
1493
1579
  declare namespace Images_d_exports {
1494
- export { DrawStepOptions, HostedImagesClient, ImageDrawOptions, ImageHandleClient, ImageInfoResponse, ImageInputOptions, ImageInputValue, ImageList, ImageListOptions, ImageMetadata, ImageOutputOptions, ImageTransform, ImageTransformationOutputOptions, ImageTransformationResult, ImageUpdateOptions, ImageUploadOptions, ImageUploadValue, ImagesClient, ImagesDefinition, ImagesOperationError, ImagesRuntimeBinding, ImagesService, ImagesTransformationResultClient, LayerOptions$5 as LayerOptions, ProcessOptions, Step, Steps, Tag$6 as Tag, TagClass$5 as TagClass, TypeId, draw, empty, isImagesBinding, layer$3 as layer, make$4 as make, makeClient$3 as makeClient, transform };
1580
+ export { DrawStepOptions, HostedImagesClient, ImageDirectUploadOptions, ImageDirectUploadResult, ImageDrawOptions, ImageHandleClient, ImageInfoResponse, ImageInputOptions, ImageInputValue, ImageList, ImageListOptions, ImageMetadata, ImageOutputOptions, ImageSignedUrlOptions, ImageTransform, ImageTransformationOutputOptions, ImageTransformationResponseOptions, ImageTransformationResult, ImageUpdateOptions, ImageUploadOptions, ImageUploadValue, ImagesClient, ImagesDefinition, ImagesOperationError, ImagesRuntimeBinding, ImagesService, ImagesTransformationResultClient, LayerOptions$5 as LayerOptions, ProcessOptions, Step, Steps, Tag$6 as Tag, TagClass$5 as TagClass, TextOptions, TypeId, draw, empty, isImagesBinding, layer$3 as layer, make$4 as make, makeClient$3 as makeClient, transform };
1495
1581
  }
1496
1582
  declare const TypeId: "~effect-cf/Images/Steps";
1497
1583
  type TypeId = typeof TypeId;
@@ -1517,12 +1603,17 @@ type ImageDrawOptions = CloudflareImageDrawOptions;
1517
1603
  type ImageInputOptions = CloudflareImageInputOptions;
1518
1604
  type ImageOutputOptions = CloudflareImageOutputOptions;
1519
1605
  type ImageTransformationOutputOptions = CloudflareImageTransformationOutputOptions;
1606
+ type ImageTransformationResponseOptions = CloudflareImageTransformationResponseOptions;
1520
1607
  type ImageTransformationResult = CloudflareImageTransformationResult;
1521
1608
  type ImageUploadOptions = CloudflareImageUploadOptions;
1522
1609
  type ImageUpdateOptions = CloudflareImageUpdateOptions;
1523
1610
  type ImageListOptions = CloudflareImageListOptions;
1524
1611
  type ImageList = CloudflareImageList;
1525
1612
  type ImageMetadata = CloudflareImageMetadata;
1613
+ type ImageSignedUrlOptions = CloudflareImageSignedUrlOptions;
1614
+ type ImageDirectUploadOptions = CloudflareImageDirectUploadOptions;
1615
+ type ImageDirectUploadResult = CloudflareImageDirectUploadResult;
1616
+ type TextOptions = CloudflareTextOptions;
1526
1617
  type ImageInputValue = ReadableStream<Uint8Array> | ArrayBuffer;
1527
1618
  type ImageUploadValue = ReadableStream<Uint8Array> | ArrayBuffer;
1528
1619
  interface DrawStepOptions {
@@ -1598,14 +1689,18 @@ interface Steps {
1598
1689
  readonly [TypeId]: typeof TypeId;
1599
1690
  readonly steps: ReadonlyArray<Step>;
1600
1691
  }
1601
- interface ProcessOptions {
1692
+ type ProcessOptions = {
1602
1693
  readonly stream: ImageInputValue;
1603
1694
  readonly inputOptions?: ImageInputOptions;
1604
1695
  readonly outputOptions: ImageOutputOptions;
1605
- }
1696
+ } | {
1697
+ readonly text: string;
1698
+ readonly textOptions: TextOptions;
1699
+ readonly outputOptions: ImageOutputOptions;
1700
+ };
1606
1701
  interface ImagesTransformationResultClient {
1607
1702
  readonly raw: CloudflareImageTransformationResult;
1608
- readonly response: Effect.Effect<CloudflareResponse, ImagesOperationError>;
1703
+ readonly response: (options?: ImageTransformationResponseOptions) => Effect.Effect<CloudflareResponse, ImagesOperationError>;
1609
1704
  readonly contentType: Effect.Effect<string, ImagesOperationError>;
1610
1705
  readonly image: (options?: ImageTransformationOutputOptions) => Effect.Effect<ReadableStream<Uint8Array>, ImagesOperationError>;
1611
1706
  }
@@ -1613,6 +1708,7 @@ interface ImageHandleClient {
1613
1708
  readonly raw: CloudflareImageHandle;
1614
1709
  readonly details: Effect.Effect<Option.Option<ImageMetadata>, ImagesOperationError>;
1615
1710
  readonly bytes: Effect.Effect<Option.Option<ReadableStream<Uint8Array>>, ImagesOperationError>;
1711
+ readonly signedUrl: (options: ImageSignedUrlOptions) => Effect.Effect<string, ImagesOperationError>;
1616
1712
  readonly update: (options: ImageUpdateOptions) => Effect.Effect<ImageMetadata, ImagesOperationError>;
1617
1713
  readonly delete: Effect.Effect<boolean, ImagesOperationError>;
1618
1714
  }
@@ -1620,16 +1716,19 @@ interface HostedImagesClient {
1620
1716
  readonly image: (imageId: string) => ImageHandleClient;
1621
1717
  readonly upload: (image: ImageUploadValue, options?: ImageUploadOptions) => Effect.Effect<ImageMetadata, ImagesOperationError>;
1622
1718
  readonly list: (options?: ImageListOptions) => Effect.Effect<ImageList, ImagesOperationError>;
1719
+ readonly createDirectUpload: (options?: ImageDirectUploadOptions) => Effect.Effect<ImageDirectUploadResult, ImagesOperationError>;
1623
1720
  readonly rawUnsafe: Effect.Effect<CloudflareHostedImagesBinding>;
1624
1721
  }
1625
1722
  interface ImagesRuntimeBinding {
1626
1723
  readonly info: (image: ImageInputValue, options?: ImageInputOptions) => Promise<ImageInfoResponse>;
1627
1724
  readonly input: (image: ImageInputValue, options?: ImageInputOptions) => CloudflareImageTransformer;
1725
+ readonly text?: (content: string, options: TextOptions) => CloudflareImageTransformer;
1628
1726
  readonly hosted?: CloudflareHostedImagesBinding;
1629
1727
  }
1630
1728
  interface ImagesClient {
1631
1729
  readonly info: (image: ImageInputValue, options?: ImageInputOptions) => Effect.Effect<ImageInfoResponse, ImagesOperationError>;
1632
1730
  readonly input: (image: ImageInputValue, options?: ImageInputOptions) => Effect.Effect<CloudflareImageTransformer, ImagesOperationError>;
1731
+ readonly text: (content: string, options: TextOptions) => Effect.Effect<CloudflareImageTransformer, ImagesOperationError>;
1633
1732
  readonly process: (steps: Steps, options: ProcessOptions) => Effect.Effect<ImagesTransformationResultClient, ImagesOperationError>;
1634
1733
  readonly hosted: Option.Option<HostedImagesClient>;
1635
1734
  readonly rawUnsafe: Effect.Effect<ImagesRuntimeBinding>;