effect-cf 0.33.0 → 0.35.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 (74) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +31 -1079
  3. package/dist/{Artifacts-DnHQA-Ax.d.mts → Artifacts-B3r3RuTB.d.mts} +1 -48
  4. package/dist/{Artifacts-CSIk1Oml.mjs → Artifacts-CBxWGeZB.mjs} +2 -7
  5. package/dist/{Binding-pfilNJmP.mjs → Binding-C82jRhdr.mjs} +1 -2
  6. package/dist/{Binding-xJJJPmiD.d.mts → Binding-DKcLrQCM.d.mts} +0 -45
  7. package/dist/ComputerArtifacts.d.mts +1 -3
  8. package/dist/ComputerArtifacts.mjs +1 -2
  9. package/dist/ComputerWorkspace.d.mts +11 -12
  10. package/dist/ComputerWorkspace.mjs +31 -10
  11. package/dist/ComputerWorkspaceHost.d.mts +1 -9
  12. package/dist/{ContainerNamespace-CFjiLw8b.d.mts → ContainerNamespace-DbLaeFhN.d.mts} +1 -14
  13. package/dist/{DurableObjectState-CVLLse69.mjs → DurableObjectState-DcqElJ4e.mjs} +82 -89
  14. package/dist/{DurableObjectState-BpRjz6-q.d.mts → DurableObjectState-DpYdNZgT.d.mts} +102 -266
  15. package/dist/{ErrorMessage-BM0K-Nik.mjs → ErrorMessage-Byx2OgNd.mjs} +0 -1
  16. package/dist/{Hyperdrive-z-9fFz15.d.mts → Hyperdrive-HrwFlZ6x.d.mts} +1 -4
  17. package/dist/HyperdrivePg.d.mts +2 -11
  18. package/dist/HyperdrivePg.mjs +0 -8
  19. package/dist/Sandbox.d.mts +2 -32
  20. package/dist/Sandbox.mjs +2 -11
  21. package/dist/Vitest.d.mts +3 -31
  22. package/dist/Vitest.mjs +8 -26
  23. package/dist/{WorkflowBinding-lBR4_-op.d.mts → WorkflowBinding-Cn3AuUyP.d.mts} +2 -5
  24. package/dist/index.d.mts +42 -480
  25. package/dist/index.mjs +267 -380
  26. package/package.json +1 -1
  27. package/src/AiGateway.ts +0 -6
  28. package/src/AnalyticsEngine.ts +8 -10
  29. package/src/Artifacts.ts +0 -47
  30. package/src/Binding.ts +0 -8
  31. package/src/BrowserRendering.ts +0 -4
  32. package/src/Cache.ts +0 -19
  33. package/src/CloudflareOtlp.ts +6 -39
  34. package/src/ComputerArtifacts.ts +0 -2
  35. package/src/ComputerWorkspace.ts +53 -35
  36. package/src/ComputerWorkspaceHost.ts +0 -8
  37. package/src/ContainerNamespace.ts +0 -13
  38. package/src/D1.ts +0 -22
  39. package/src/DurableObject.ts +51 -32
  40. package/src/DurableObjectAlarm.ts +6 -210
  41. package/src/DurableObjectDefinition.ts +8 -20
  42. package/src/DurableObjectNamespace.ts +88 -115
  43. package/src/DurableObjectRpcWebSocket.ts +5 -46
  44. package/src/DurableObjectSqlite.ts +0 -12
  45. package/src/DurableObjectState.ts +18 -38
  46. package/src/DurableObjectStorage.ts +55 -70
  47. package/src/DurableObjectWebSocket.ts +23 -72
  48. package/src/Email.ts +0 -12
  49. package/src/Environment.ts +0 -37
  50. package/src/Hyperdrive.ts +0 -3
  51. package/src/HyperdrivePg.ts +0 -9
  52. package/src/Images.ts +0 -5
  53. package/src/Kv.ts +0 -15
  54. package/src/QueueBinding.ts +0 -2
  55. package/src/R2.ts +0 -5
  56. package/src/RpcDefinition.ts +5 -17
  57. package/src/RpcTracing.ts +133 -0
  58. package/src/Sandbox.ts +0 -30
  59. package/src/ServiceBinding.ts +83 -128
  60. package/src/Vectorize.ts +0 -5
  61. package/src/Vitest.ts +18 -43
  62. package/src/WebTransport.ts +0 -15
  63. package/src/Worker.ts +140 -108
  64. package/src/WorkerDefinition.ts +5 -14
  65. package/src/WorkersAi.ts +21 -18
  66. package/src/Workflow.ts +45 -54
  67. package/src/WorkflowBinding.ts +0 -3
  68. package/src/index.ts +1 -0
  69. package/src/internal/Entrypoint.ts +23 -4
  70. package/src/internal/ErrorMessage.ts +0 -1
  71. package/src/internal/NativeCallback.ts +55 -0
  72. package/src/internal/RpcInvocation.ts +18 -1
  73. package/src/internal/Runtime.ts +12 -7
  74. package/src/internal/WorkerContext.ts +5 -14
@@ -1,11 +1,22 @@
1
- import { Clock, Data, Duration, Effect, Exit, Option, Predicate, Schema as S } from "effect";
1
+ import {
2
+ Cause,
3
+ Clock,
4
+ Data,
5
+ Duration,
6
+ Effect,
7
+ Exit,
8
+ Fiber,
9
+ Option,
10
+ Predicate,
11
+ Result,
12
+ Schema as S,
13
+ } from "effect";
2
14
 
3
15
  import * as ErrorMessage from "./internal/ErrorMessage";
16
+ import { runNativeCallback } from "./internal/NativeCallback";
4
17
 
5
- /** Supported primitive value types for Durable Object SQL APIs. */
6
18
  export type SqlStorageValue = globalThis.SqlStorageValue;
7
19
 
8
- /** Error type used when a storage operation throws or rejects. */
9
20
  export class StorageOperationError extends Data.TaggedError("StorageOperationError")<{
10
21
  readonly operation: string;
11
22
  readonly cause: unknown;
@@ -17,9 +28,6 @@ export class StorageOperationError extends Data.TaggedError("StorageOperationErr
17
28
 
18
29
  type StorageEffect<A> = Effect.Effect<A, StorageOperationError>;
19
30
 
20
- /**
21
- * Effect wrapper for Cloudflare SQL cursor operations.
22
- */
23
31
  export interface SqlCursor<T extends Record<string, SqlStorageValue>> {
24
32
  next(): StorageEffect<{ done?: false; value: T } | { done: true; value?: never }>;
25
33
  toArray(): StorageEffect<Array<T>>;
@@ -30,11 +38,7 @@ export interface SqlCursor<T extends Record<string, SqlStorageValue>> {
30
38
  readonly rowsWritten: StorageEffect<number>;
31
39
  }
32
40
 
33
- /**
34
- * Effect wrapper for Durable Object SQLite APIs.
35
- */
36
41
  export interface SqlStorage {
37
- /** Executes a SQL statement and returns a typed cursor. */
38
42
  exec<T extends Record<string, SqlStorageValue>>(
39
43
  query: string,
40
44
  ...bindings: Array<SqlStorageValue>
@@ -42,9 +46,6 @@ export interface SqlStorage {
42
46
  readonly databaseSize: number;
43
47
  }
44
48
 
45
- /**
46
- * Schema pair used by `SyncKvStorage.schema(...)`.
47
- */
48
49
  export interface SyncKvDefinition<Key, Value, EncodedValue> {
49
50
  readonly key: S.Codec<Key, string>;
50
51
  readonly value: S.Codec<Value, EncodedValue>;
@@ -60,9 +61,6 @@ export interface SchemaBackedSyncKvStorage<Key, Value> {
60
61
  list(options?: globalThis.SyncKvListOptions): Effect.Effect<Array<[Key, Value]>, unknown>;
61
62
  }
62
63
 
63
- /**
64
- * Effect wrapper for synchronous KV attached to Durable Object SQLite storage.
65
- */
66
64
  export interface SyncKvStorage {
67
65
  get<T = unknown>(key: string): StorageEffect<T | undefined>;
68
66
  put<T>(key: string, value: T): StorageEffect<void>;
@@ -99,7 +97,6 @@ export interface DurableObjectTransaction {
99
97
  scheduledTime: number | Date,
100
98
  options?: globalThis.DurableObjectSetAlarmOptions,
101
99
  ): StorageEffect<void>;
102
- /** Schedules the alarm after a delay measured by the Effect clock. */
103
100
  setAlarmAfter(
104
101
  delay: Duration.Input,
105
102
  options?: globalThis.DurableObjectSetAlarmOptions,
@@ -107,19 +104,6 @@ export interface DurableObjectTransaction {
107
104
  deleteAlarm(options?: globalThis.DurableObjectSetAlarmOptions): StorageEffect<void>;
108
105
  }
109
106
 
110
- /**
111
- * Effect wrapper around Cloudflare Durable Object storage.
112
- *
113
- * @example
114
- * ```ts
115
- * const program = Effect.gen(function* () {
116
- * const state = yield* DurableObjectState;
117
- * yield* state.storage.put("counter", 1);
118
- * const value = yield* state.storage.get<number>("counter");
119
- * return value;
120
- * });
121
- * ```
122
- */
123
107
  export interface DurableObjectStorage {
124
108
  get<T = unknown>(
125
109
  key: string,
@@ -137,7 +121,6 @@ export interface DurableObjectStorage {
137
121
  scheduledTime: number | Date,
138
122
  options?: globalThis.DurableObjectSetAlarmOptions,
139
123
  ): StorageEffect<void>;
140
- /** Schedules the alarm after a delay measured by the Effect clock. */
141
124
  setAlarmAfter(
142
125
  delay: Duration.Input,
143
126
  options?: globalThis.DurableObjectSetAlarmOptions,
@@ -161,9 +144,9 @@ export interface DurableObjectStorage {
161
144
  ): Effect.Effect<A, E | StorageOperationError, R>;
162
145
  /** Flushes pending writes to disk. */
163
146
  sync(): StorageEffect<void>;
164
- /** SQLite-backed Durable Object storage point-in-time recovery API only. */
147
+ /** Requires SQLite-backed Durable Object storage. */
165
148
  getCurrentBookmark(): StorageEffect<string>;
166
- /** SQLite-backed Durable Object storage point-in-time recovery API only. */
149
+ /** Requires SQLite-backed Durable Object storage. */
167
150
  onNextSessionRestoreBookmark(bookmark: string): StorageEffect<string>;
168
151
  readonly sql: SqlStorage;
169
152
  readonly kv: SyncKvStorage;
@@ -329,9 +312,6 @@ const fromDurableObjectTransaction = (
329
312
  tryStoragePromise("transaction.deleteAlarm", () => txn.deleteAlarm(options)),
330
313
  }) as DurableObjectTransaction;
331
314
 
332
- /**
333
- * Wraps native Cloudflare storage APIs as Effect-returning helpers.
334
- */
335
315
  export const fromDurableObjectStorage = (
336
316
  storage: globalThis.DurableObjectStorage,
337
317
  ): DurableObjectStorage => ({
@@ -364,6 +344,7 @@ export const fromDurableObjectStorage = (
364
344
  // failed Exit is thrown to abort it. Keep a typed reference to that
365
345
  // Exit rather than recovering its type from the untyped catch binding.
366
346
  let aborted: Exit.Exit<A, E> | undefined;
347
+ let escapedFiber: Fiber.Fiber<unknown, unknown> | undefined;
367
348
 
368
349
  try {
369
350
  return Effect.succeed(
@@ -373,55 +354,59 @@ export const fromDurableObjectStorage = (
373
354
  if (Exit.isSuccess(exit)) {
374
355
  return exit.value;
375
356
  }
357
+ const defect = Cause.findDefect(exit.cause);
358
+
359
+ if (Result.isSuccess(defect) && Cause.isAsyncFiberError(defect.success)) {
360
+ escapedFiber = defect.success.fiber;
361
+ escapedFiber.interruptUnsafe();
362
+ }
376
363
  aborted = exit;
377
364
 
378
365
  throw exit;
379
366
  }),
380
367
  );
381
368
  } catch (cause) {
382
- if (aborted !== undefined && cause === aborted && Exit.isFailure(aborted)) {
383
- return Effect.failCause(aborted.cause);
369
+ const failure: Effect.Effect<never, E | StorageOperationError> =
370
+ aborted !== undefined && cause === aborted && Exit.isFailure(aborted)
371
+ ? Effect.failCause(aborted.cause)
372
+ : Effect.fail(storageError("transactionSync", cause));
373
+ const fiber = escapedFiber;
374
+
375
+ if (fiber !== undefined) {
376
+ return Fiber.interrupt(fiber).pipe(Effect.andThen(failure));
384
377
  }
385
378
 
386
- return Effect.fail(storageError("transactionSync", cause));
379
+ return failure;
387
380
  }
388
381
  }),
389
382
  ),
390
383
  ),
391
384
  transaction: <A, E, R>(closure: (txn: DurableObjectTransaction) => Effect.Effect<A, E, R>) =>
392
- Effect.context<R>().pipe(
393
- Effect.flatMap((context) =>
394
- Effect.callback<A, E | StorageOperationError>((resume) => {
395
- // See `transactionSync`: the thrown Exit aborts Cloudflare's
396
- // transaction, and holding it here keeps its error type.
397
- let aborted: Exit.Exit<A, E> | undefined;
385
+ Effect.suspend(() => {
386
+ // See `transactionSync`: the thrown Exit aborts Cloudflare's
387
+ // transaction, and holding it here keeps its error type.
388
+ let aborted: Exit.Exit<A, E> | undefined;
398
389
 
399
- void storage
400
- .transaction(async (txn) => {
401
- const exit = await Effect.runPromiseExitWith(context)(
402
- closure(fromDurableObjectTransaction(txn)),
403
- );
404
-
405
- if (Exit.isSuccess(exit)) {
406
- return exit.value;
407
- }
408
- aborted = exit;
409
-
410
- throw exit;
411
- })
412
- .then(
413
- (value) => resume(Effect.succeed(value)),
414
- (cause) => {
415
- if (aborted !== undefined && cause === aborted && Exit.isFailure(aborted)) {
416
- resume(Effect.failCause(aborted.cause));
417
- } else {
418
- resume(Effect.fail(storageError("transaction", cause)));
419
- }
420
- },
421
- );
390
+ return runNativeCallback<A, E, R, A>((run) =>
391
+ storage.transaction(async (txn) => {
392
+ const exit = await run(Effect.suspend(() => closure(fromDurableObjectTransaction(txn))));
393
+
394
+ if (Exit.isSuccess(exit)) {
395
+ return exit.value;
396
+ }
397
+ aborted = exit;
398
+
399
+ throw exit;
422
400
  }),
423
- ),
424
- ),
401
+ ).pipe(
402
+ Effect.catch(
403
+ (cause): Effect.Effect<never, E | StorageOperationError> =>
404
+ aborted !== undefined && cause === aborted && Exit.isFailure(aborted)
405
+ ? Effect.failCause(aborted.cause)
406
+ : Effect.fail(storageError("transaction", cause)),
407
+ ),
408
+ );
409
+ }),
425
410
  sync: () => tryStoragePromise("sync", () => storage.sync()),
426
411
  getCurrentBookmark: () =>
427
412
  tryStoragePromise("getCurrentBookmark", () => storage.getCurrentBookmark()),
@@ -3,10 +3,8 @@ import { Data, Effect, Option, Result, Schema as S } from "effect";
3
3
  import { DurableObjectState } from "./DurableObjectState";
4
4
  import * as ErrorMessage from "./internal/ErrorMessage";
5
5
 
6
- /** Data supported by Cloudflare websocket `send`. */
7
6
  export type DurableWebSocketSendData = string | ArrayBuffer | ArrayBufferView;
8
7
 
9
- /** Error raised when sending on a Durable Object websocket fails. */
10
8
  export class DurableWebSocketSendError extends Data.TaggedError("DurableWebSocketSendError")<{
11
9
  readonly cause: unknown;
12
10
  }> {
@@ -15,7 +13,6 @@ export class DurableWebSocketSendError extends Data.TaggedError("DurableWebSocke
15
13
  }
16
14
  }
17
15
 
18
- /** Error raised when closing a Durable Object websocket fails. */
19
16
  export class DurableWebSocketCloseError extends Data.TaggedError("DurableWebSocketCloseError")<{
20
17
  readonly cause: unknown;
21
18
  }> {
@@ -36,95 +33,55 @@ export class DurableWebSocketAttachmentError extends Data.TaggedError(
36
33
  }
37
34
  }
38
35
 
39
- /** Effect-native wrapper around a hibernatable Durable Object websocket. */
40
36
  export interface DurableWebSocket<Attachment = unknown> {
41
- /** Underlying Cloudflare websocket. */
42
37
  readonly raw: WebSocket;
43
- /** Sends a message through the socket. */
44
38
  send(data: DurableWebSocketSendData): Effect.Effect<void, DurableWebSocketSendError>;
45
- /** Closes the socket. */
46
39
  close(code?: number, reason?: string): Effect.Effect<void, DurableWebSocketCloseError>;
47
40
  /** Serializes hibernation attachment metadata onto the socket. */
48
- serializeAttachment<A = Attachment>(
41
+ serializeAttachment<A extends Attachment = Attachment>(
49
42
  value: A,
50
43
  ): Effect.Effect<void, DurableWebSocketAttachmentError>;
51
44
  /** Deserializes hibernation attachment metadata from the socket. */
52
45
  readonly deserializeAttachment: Effect.Effect<unknown, DurableWebSocketAttachmentError>;
53
46
  }
54
47
 
55
- const wrappers = new WeakMap<WebSocket, DurableWebSocket<unknown>>();
56
-
57
- /** Wraps a native Cloudflare websocket in the Effect-native Durable Object API. */
58
48
  export const fromWebSocket = <Attachment = unknown>(
59
49
  raw: WebSocket,
60
- ): DurableWebSocket<Attachment> => {
61
- const existing = wrappers.get(raw);
62
-
63
- if (existing !== undefined) {
64
- // SAFETY: Attachment is phantom; a wrapper's runtime behavior is independent of that type.
65
- return existing as DurableWebSocket<Attachment>;
66
- }
67
-
68
- const socket: DurableWebSocket<unknown> = {
69
- raw,
70
- send: (data) =>
71
- Effect.try({
72
- try: () => raw.send(data),
73
- catch: (cause) => new DurableWebSocketSendError({ cause }),
74
- }),
75
- close: (code, reason) =>
76
- Effect.try({
77
- try: () => raw.close(code, reason),
78
- catch: (cause) => new DurableWebSocketCloseError({ cause }),
79
- }),
80
- serializeAttachment: (value) =>
81
- Effect.try({
82
- try: () => raw.serializeAttachment(value),
83
- catch: (cause) => new DurableWebSocketAttachmentError({ operation: "serialize", cause }),
84
- }),
85
- deserializeAttachment: Effect.try({
86
- try: () => raw.deserializeAttachment(),
87
- catch: (cause) => new DurableWebSocketAttachmentError({ operation: "deserialize", cause }),
50
+ ): DurableWebSocket<Attachment> => ({
51
+ raw,
52
+ send: (data) =>
53
+ Effect.try({
54
+ try: () => raw.send(data),
55
+ catch: (cause) => new DurableWebSocketSendError({ cause }),
88
56
  }),
89
- };
90
-
91
- wrappers.set(raw, socket);
92
-
93
- // SAFETY: Attachment is phantom; the newly created wrapper supports values through its generic serializer.
94
- return socket as DurableWebSocket<Attachment>;
95
- };
57
+ close: (code, reason) =>
58
+ Effect.try({
59
+ try: () => raw.close(code, reason),
60
+ catch: (cause) => new DurableWebSocketCloseError({ cause }),
61
+ }),
62
+ serializeAttachment: <A extends Attachment = Attachment>(value: A) =>
63
+ Effect.try({
64
+ try: () => raw.serializeAttachment(value),
65
+ catch: (cause) => new DurableWebSocketAttachmentError({ operation: "serialize", cause }),
66
+ }),
67
+ deserializeAttachment: Effect.try({
68
+ try: () => raw.deserializeAttachment(),
69
+ catch: (cause) => new DurableWebSocketAttachmentError({ operation: "deserialize", cause }),
70
+ }),
71
+ });
96
72
 
97
- /**
98
- * Options for accepting an incoming websocket request in a Durable Object.
99
- */
100
73
  export interface AcceptUpgradeOptions<Attachment = unknown> {
101
- /** Optional websocket tags for Durable Object hibernation filtering. */
102
74
  readonly tags?: ReadonlyArray<string> | undefined;
103
75
  /** Optional attachment serialized onto the server socket. */
104
76
  readonly attachment?: Attachment | undefined;
105
77
  }
106
78
 
107
- /**
108
- * Result of a websocket upgrade accepted by {@link acceptUpgrade}.
109
- */
110
79
  export interface AcceptedUpgrade<Attachment = unknown> {
111
80
  readonly client: WebSocket;
112
81
  readonly server: DurableWebSocket<Attachment>;
113
82
  readonly response: Response;
114
83
  }
115
84
 
116
- /**
117
- * Accepts a websocket upgrade and registers the server socket on `DurableObjectState`.
118
- *
119
- * @example
120
- * ```ts
121
- * const response = yield* DurableObjectWebSocket.acceptUpgrade({
122
- * tags: ["room:general"],
123
- * });
124
- *
125
- * return response.response;
126
- * ```
127
- */
128
85
  export const acceptUpgrade = Effect.fn("DurableObjectWebSocket.acceptUpgrade")(function* <
129
86
  Attachment = unknown,
130
87
  >(
@@ -158,9 +115,7 @@ export const acceptUpgrade = Effect.fn("DurableObjectWebSocket.acceptUpgrade")(f
158
115
  export type AttachmentInvalidPolicy = "ignore" | "ignore-and-close" | "fail";
159
116
 
160
117
  export interface AttachmentRehydrateOptions {
161
- /** Optional Durable Object websocket tag filter. */
162
118
  readonly tag?: string | undefined;
163
- /** Invalid attachment behavior. Defaults to skipping invalid sockets. */
164
119
  readonly onInvalid?: AttachmentInvalidPolicy | undefined;
165
120
  }
166
121
 
@@ -187,7 +142,6 @@ export interface DurableWebSocketAttachment<Attachment, Encoded> {
187
142
  readonly schema: S.Codec<Attachment, Encoded, never, never>;
188
143
  }
189
144
 
190
- /** Creates typed attachment helpers for accepted and rehydrated sockets. */
191
145
  export const attachment = <const AttachmentSchema extends S.Codec<any, any, never, never>>(
192
146
  schema: AttachmentSchema,
193
147
  ): DurableWebSocketAttachment<
@@ -195,15 +149,13 @@ export const attachment = <const AttachmentSchema extends S.Codec<any, any, neve
195
149
  S.Codec.Encoded<AttachmentSchema>
196
150
  > => {
197
151
  type Attachment = S.Schema.Type<AttachmentSchema>;
198
- type Encoded = S.Codec.Encoded<AttachmentSchema>;
199
152
 
200
153
  const serialize = (socket: DurableWebSocket<unknown>, value: Attachment) =>
201
154
  S.encodeEffect(schema)(value).pipe(
202
155
  Effect.mapError(
203
156
  (cause) => new DurableWebSocketAttachmentError({ operation: "serialize", cause }),
204
157
  ),
205
- // SAFETY: S.encodeEffect returns this codec's declared Encoded representation.
206
- Effect.flatMap((encoded) => socket.serializeAttachment(encoded as Encoded)),
158
+ Effect.flatMap((encoded) => socket.serializeAttachment(encoded)),
207
159
  );
208
160
 
209
161
  const deserialize = (socket: DurableWebSocket<unknown>) =>
@@ -267,7 +219,6 @@ export interface DurableWebSocketHandlers<R = never, E = unknown> {
267
219
  readonly error?: (socket: DurableWebSocket, cause: unknown) => Effect.Effect<void, E, R>;
268
220
  }
269
221
 
270
- /** Maps compact websocket lifecycle handler names to `DurableObject.make` options. */
271
222
  export const handlers = <R = never, E = unknown>(options: DurableWebSocketHandlers<R, E>) => ({
272
223
  webSocketMessage: options.message,
273
224
  webSocketClose: options.close,
package/src/Email.ts CHANGED
@@ -13,17 +13,13 @@ import * as ErrorMessage from "./internal/ErrorMessage";
13
13
  const expectedSendEmailBinding = "Send Email binding with send()";
14
14
  const textEncoder = new TextEncoder();
15
15
 
16
- /** Documented Cloudflare Email Sending limits. */
17
16
  export const sendLimits = {
18
- /** Combined `to`, `cc`, and `bcc` addresses per message. */
19
17
  maxRecipients: 50,
20
18
  maxAttachments: 32,
21
- /** Total message size, including attachments. Not enforced client side. */
22
19
  maxMessageBytes: 5 * 1024 * 1024,
23
20
  maxHeaderNameBytes: 100,
24
21
  maxHeaderValueBytes: 2048,
25
22
  maxHeadersBytes: 16 * 1024,
26
- /** Allowlisted custom headers, excluding `X-` prefixed headers. */
27
23
  maxAllowlistHeaders: 20,
28
24
  } as const;
29
25
 
@@ -58,10 +54,8 @@ export const emailErrorCodes = [
58
54
  "E_HEADERS_TOO_MANY",
59
55
  ] as const;
60
56
 
61
- /** A documented Cloudflare Email Sending error code. */
62
57
  export type EmailErrorCode = (typeof emailErrorCodes)[number];
63
58
 
64
- /** Error raised when a Cloudflare Send Email operation fails. */
65
59
  export class EmailOperationError extends Data.TaggedError("EmailOperationError")<{
66
60
  readonly binding: string;
67
61
  readonly operation: string;
@@ -82,7 +76,6 @@ export class EmailOperationError extends Data.TaggedError("EmailOperationError")
82
76
  }
83
77
  }
84
78
 
85
- /** A single message field that violates a documented Email Sending limit. */
86
79
  export interface EmailViolation {
87
80
  readonly path: string;
88
81
  readonly message: string;
@@ -90,7 +83,6 @@ export interface EmailViolation {
90
83
  readonly actual?: number;
91
84
  }
92
85
 
93
- /** Error raised when a message violates documented Cloudflare Email Sending limits. */
94
86
  export class EmailValidationError extends Data.TaggedError("EmailValidationError")<{
95
87
  readonly binding: string;
96
88
  readonly operation: string;
@@ -101,9 +93,7 @@ export class EmailValidationError extends Data.TaggedError("EmailValidationError
101
93
  }
102
94
  }
103
95
 
104
- /** Typed Cloudflare Send Email binding definition. */
105
96
  export interface EmailDefinition {
106
- /** Binding name as configured in `wrangler.jsonc`. */
107
97
  readonly binding: string;
108
98
  }
109
99
 
@@ -117,7 +107,6 @@ export type EmailSendError = EmailOperationError | EmailValidationError;
117
107
  type EmailFieldCandidate = Parameters<typeof Predicate.isUnknown>[0];
118
108
 
119
109
  export interface EmailSendOptions {
120
- /** Validates builder messages against documented limits. Defaults to `true`. */
121
110
  readonly validate?: boolean;
122
111
  }
123
112
 
@@ -133,7 +122,6 @@ export interface EmailClient {
133
122
 
134
123
  declare const EmailServiceTypeId: unique symbol;
135
124
 
136
- /** Nominal service marker for Send Email services created with {@link make}. */
137
125
  export interface EmailService<Id extends string> {
138
126
  readonly [EmailServiceTypeId]: {
139
127
  readonly id: Id;
@@ -1,6 +1,5 @@
1
1
  import { Config, ConfigProvider, Context, Effect, type Layer, Predicate } from "effect";
2
2
 
3
- /** Cloudflare worker environment object (`env`). */
4
3
  export type WorkerEnv = Cloudflare.Env;
5
4
 
6
5
  /**
@@ -23,38 +22,9 @@ type ScalarConfigKey = Extract<
23
22
  string
24
23
  >;
25
24
 
26
- /**
27
- * Effect `Config` helpers for scalar Cloudflare vars and secrets declared on
28
- * `Cloudflare.Env`.
29
- *
30
- * Users still author their app config explicitly with Effect `Config`:
31
- *
32
- * ```ts
33
- * import { Config, Effect } from "effect";
34
- * import { WorkerConfig } from "effect-cf";
35
- *
36
- * const AppConfig = Config.all({
37
- * databaseUrl: WorkerConfig.redacted("DATABASE_URL"),
38
- * port: WorkerConfig.integer("PORT").pipe(Config.withDefault(8787)),
39
- * });
40
- *
41
- * const program = Effect.gen(function* () {
42
- * const config = yield* AppConfig;
43
- * // ...
44
- * }).pipe(Effect.provide(WorkerConfig.providerLayer));
45
- * ```
46
- *
47
- * Keys are constrained to scalar `Cloudflare.Env` properties (`string`,
48
- * `number`, or `boolean`, including optional scalar properties). Binding
49
- * objects such as `KVNamespace`, `DurableObjectNamespace`, and service
50
- * bindings are intentionally excluded; keep using the package binding helpers
51
- * for those live resources.
52
- */
53
25
  export namespace WorkerConfig {
54
- /** Scalar env value types supported by the typed config key helpers. */
55
26
  export type Scalar = ScalarConfigValue;
56
27
 
57
- /** Scalar keys available on the current consumer's `Cloudflare.Env`. */
58
28
  export type Key = ScalarConfigKey;
59
29
 
60
30
  /** Read a scalar Cloudflare var or secret as a string. */
@@ -72,7 +42,6 @@ export namespace WorkerConfig {
72
42
  /** Read a scalar Cloudflare var or secret as a boolean. */
73
43
  export const boolean = <const Name extends Key>(name: Name) => Config.boolean(name);
74
44
 
75
- /** Options for building a `ConfigProvider` from a Cloudflare worker `env` object. */
76
45
  export interface ProviderOptions {
77
46
  /**
78
47
  * Keep empty-string env values as explicit `""` config values.
@@ -104,14 +73,9 @@ export namespace WorkerConfig {
104
73
  return ConfigProvider.fromEnvRecord(record, options);
105
74
  };
106
75
 
107
- /**
108
- * Build a `ConfigProvider` from the current `WorkerEnvironment` with a custom
109
- * conversion function.
110
- */
111
76
  export const providerWith = (makeProvider: (env: WorkerEnv) => ConfigProvider.ConfigProvider) =>
112
77
  Effect.map(WorkerEnvironment, makeProvider);
113
78
 
114
- /** Build a `ConfigProvider` from the current `WorkerEnvironment`. */
115
79
  export const provider = providerWith(providerFromEnv);
116
80
 
117
81
  /**
@@ -121,7 +85,6 @@ export namespace WorkerConfig {
121
85
  export const providerLayer: Layer.Layer<never, never, WorkerEnvironment> =
122
86
  ConfigProvider.layer(provider);
123
87
 
124
- /** Build a `ConfigProvider` layer with a custom `env` conversion function. */
125
88
  export const layerWith = (
126
89
  makeProvider: (env: WorkerEnv) => ConfigProvider.ConfigProvider,
127
90
  ): Layer.Layer<never, never, WorkerEnvironment> =>
package/src/Hyperdrive.ts CHANGED
@@ -5,9 +5,7 @@ import type { WorkerEnvironment } from "./Environment";
5
5
 
6
6
  const expectedHyperdrive = "Hyperdrive binding with connectionString";
7
7
 
8
- /** Typed Hyperdrive binding definition. */
9
8
  export interface HyperdriveDefinition {
10
- /** Binding name as configured in `wrangler.jsonc`. */
11
9
  readonly binding: string;
12
10
  }
13
11
 
@@ -19,7 +17,6 @@ export interface HyperdriveClient {
19
17
 
20
18
  declare const HyperdriveServiceTypeId: unique symbol;
21
19
 
22
- /** Nominal service marker for Hyperdrive services created with {@link make}. */
23
20
  export interface HyperdriveService<Id extends string> {
24
21
  readonly [HyperdriveServiceTypeId]: {
25
22
  readonly id: Id;
@@ -6,20 +6,11 @@ import type * as Binding from "./Binding";
6
6
  import type { WorkerEnvironment } from "./Environment";
7
7
  import type * as Hyperdrive from "./Hyperdrive";
8
8
 
9
- /** Hyperdrive owns database pooling, so app-side pool and connection options are not exposed. */
10
9
  export type PgLayerOptions = Omit<
11
10
  Parameters<typeof PgClient.makeClient>[0],
12
11
  "url" | "host" | "port" | "path" | "ssl" | "database" | "username" | "password" | "stream"
13
12
  >;
14
13
 
15
- /**
16
- * Provides `PgClient` and `SqlClient` backed by a Hyperdrive binding.
17
- *
18
- * Note: since Effect `4.0.0-beta.99`, `PgClient.makeClient` connects eagerly,
19
- * so the TCP connection to Hyperdrive is opened when this layer is built.
20
- * In per-request Workers runtimes, build the layer within the request
21
- * lifecycle rather than sharing it across requests.
22
- */
23
14
  export const layer = <Self, Id extends string>(
24
15
  tag: Hyperdrive.TagClass<Self, Id>,
25
16
  binding: Hyperdrive.LayerOptions,
package/src/Images.ts CHANGED
@@ -33,7 +33,6 @@ export type TypeId = typeof TypeId;
33
33
 
34
34
  const expectedImagesBinding = "Images binding with info() and input()";
35
35
 
36
- /** Error raised when a Cloudflare Images operation fails. */
37
36
  export class ImagesOperationError extends Data.TaggedError("ImagesOperationError")<{
38
37
  readonly binding: string;
39
38
  readonly operation: string;
@@ -44,9 +43,7 @@ export class ImagesOperationError extends Data.TaggedError("ImagesOperationError
44
43
  }
45
44
  }
46
45
 
47
- /** Typed Cloudflare Images binding definition. */
48
46
  export interface ImagesDefinition {
49
- /** Binding name as configured in `wrangler.jsonc`. */
50
47
  readonly binding: string;
51
48
  }
52
49
 
@@ -175,7 +172,6 @@ export interface ImagesClient {
175
172
 
176
173
  declare const ImagesServiceTypeId: unique symbol;
177
174
 
178
- /** Nominal service marker for Images services created with {@link make}. */
179
175
  export interface ImagesService<Id extends string> {
180
176
  readonly [ImagesServiceTypeId]: {
181
177
  readonly id: Id;
@@ -206,7 +202,6 @@ const makeSteps = (steps: ReadonlyArray<Step>): Steps => ({
206
202
  steps,
207
203
  });
208
204
 
209
- /** Empty Images transformation pipeline. */
210
205
  export const empty: Steps = makeSteps([]);
211
206
 
212
207
  export const transform: {