effect-cf 0.20.1 → 0.22.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 (53) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +2 -2
  3. package/dist/{Hyperdrive-RTjgirMV.d.mts → Hyperdrive-COyg7R26.d.mts} +40 -13
  4. package/dist/HyperdrivePg.d.mts +13 -5
  5. package/dist/HyperdrivePg.mjs +12 -7
  6. package/dist/index.d.mts +708 -549
  7. package/dist/index.mjs +924 -587
  8. package/package.json +10 -5
  9. package/src/AiGateway.ts +82 -47
  10. package/src/AnalyticsEngine.ts +74 -58
  11. package/src/Binding.ts +66 -13
  12. package/src/BrowserRendering.ts +30 -7
  13. package/src/Cache.ts +32 -8
  14. package/src/CloudflareOtlp.ts +32 -9
  15. package/src/ContainerNamespace.ts +87 -55
  16. package/src/D1.ts +13 -3
  17. package/src/DurableObject.ts +27 -164
  18. package/src/DurableObjectAlarm.ts +30 -9
  19. package/src/DurableObjectDefinition.ts +58 -54
  20. package/src/DurableObjectNamespace.ts +99 -96
  21. package/src/DurableObjectRpcWebSocket.ts +14 -6
  22. package/src/DurableObjectSqlite.ts +6 -3
  23. package/src/DurableObjectState.ts +6 -9
  24. package/src/DurableObjectStorage.ts +7 -1
  25. package/src/DurableObjectWebSocket.ts +51 -41
  26. package/src/Email.ts +40 -13
  27. package/src/Environment.ts +26 -6
  28. package/src/Hyperdrive.ts +2 -2
  29. package/src/HyperdrivePg.ts +25 -13
  30. package/src/Images.ts +77 -82
  31. package/src/Kv.ts +37 -27
  32. package/src/Queue.ts +6 -1
  33. package/src/QueueBinding.ts +18 -21
  34. package/src/QueueDefinition.ts +15 -14
  35. package/src/R2.ts +107 -29
  36. package/src/Rpc.ts +3 -1
  37. package/src/RpcDefinition.ts +177 -133
  38. package/src/ServiceBinding.ts +112 -108
  39. package/src/Vectorize.ts +59 -14
  40. package/src/Worker.ts +172 -192
  41. package/src/WorkerDefinition.ts +5 -10
  42. package/src/WorkersAi.ts +27 -17
  43. package/src/Workflow.ts +54 -49
  44. package/src/WorkflowBinding.ts +19 -11
  45. package/src/WorkflowDefinition.ts +24 -27
  46. package/src/index.ts +4 -3
  47. package/src/internal/Entrypoint.ts +3 -1
  48. package/src/internal/ErrorMessage.ts +24 -0
  49. package/src/internal/RpcInvocation.ts +11 -8
  50. package/src/internal/Runtime.ts +52 -0
  51. package/src/internal/WorkerContext.ts +14 -2
  52. package/src/Entry.ts +0 -259
  53. package/src/internal/Clock.ts +0 -37
@@ -4,6 +4,7 @@ import * as Binding from "./Binding";
4
4
  import * as CloudflareRpc from "./Rpc";
5
5
  import * as RpcDefinition from "./RpcDefinition";
6
6
  import type * as WorkerDefinition from "./WorkerDefinition";
7
+ import * as ErrorMessage from "./internal/ErrorMessage";
7
8
  import * as RpcInvocation from "./internal/RpcInvocation";
8
9
 
9
10
  const TypeId = "effect-cf/ServiceBinding" as const;
@@ -58,7 +59,11 @@ export interface ServiceBindingDefinition<
58
59
  export class ServiceBindingFetchError extends Data.TaggedError("ServiceBindingFetchError")<{
59
60
  readonly binding: string;
60
61
  readonly cause: unknown;
61
- }> {}
62
+ }> {
63
+ override get message(): string {
64
+ return `Service binding "${this.binding}" fetch failed: ${ErrorMessage.causeMessage(this.cause)}`;
65
+ }
66
+ }
62
67
 
63
68
  /**
64
69
  * Failure raised when invoking an RPC method on a service binding.
@@ -67,7 +72,11 @@ export class ServiceBindingRpcError extends Data.TaggedError("ServiceBindingRpcE
67
72
  readonly binding: string;
68
73
  readonly method: string;
69
74
  readonly cause: unknown;
70
- }> {}
75
+ }> {
76
+ override get message(): string {
77
+ return `Service binding "${this.binding}" RPC method "${this.method}" failed: ${ErrorMessage.causeMessage(this.cause)}`;
78
+ }
79
+ }
71
80
 
72
81
  type ServiceMethodKey<Api> = RpcInvocation.AsyncMethodKey<Api>;
73
82
  type ServiceMethodArgs<Api, Method extends keyof Api> = RpcInvocation.AsyncMethodArgs<Api, Method>;
@@ -235,107 +244,106 @@ export const makeClient = <
235
244
  definition: ServiceBindingDefinition<Definition>,
236
245
  ): ((service: ServiceBindingClient<Api>) => ServiceBindingEffectClient<Api, Definition>) => {
237
246
  return (service: ServiceBindingClient<Api>) => {
238
- const fetch = (input: RequestInfo | URL, init?: RequestInit) =>
239
- Effect.tryPromise({
247
+ const fetch = Effect.fn("ServiceBinding.fetch")(function* (
248
+ input: RequestInfo | URL,
249
+ init?: RequestInit,
250
+ ) {
251
+ return yield* Effect.tryPromise({
240
252
  try: () => service.fetch(input, init),
241
253
  catch: (cause) => new ServiceBindingFetchError({ binding: definition.binding, cause }),
242
254
  });
255
+ });
243
256
 
244
- const rpc = <Method extends ServiceMethodKey<Api>>(
257
+ const rpc = Effect.fn("ServiceBinding.rpc")(function* <Method extends ServiceMethodKey<Api>>(
245
258
  method: Method,
246
259
  ...args: ServiceMethodArgs<Api, Method>
247
- ) =>
248
- Effect.gen(function* () {
249
- const methodName = String(method);
250
- const encodedArgs =
251
- definition.definition === undefined
252
- ? args
253
- : yield* RpcDefinition.encodeArgs(
254
- definition.definition,
255
- methodName as RpcDefinition.Definition.MethodNames<NonNullable<Definition>>,
256
- args as never,
257
- ).pipe(
258
- Effect.mapError(
259
- (cause) =>
260
- new ServiceBindingRpcError({
261
- binding: definition.binding,
262
- method: methodName,
263
- cause,
264
- }),
265
- ),
266
- );
267
-
268
- return yield* RpcInvocation.invokeRpcMethod(
269
- service,
270
- method,
271
- encodedArgs as ServiceMethodArgs<Api, Method>,
260
+ ) {
261
+ const methodName = String(method);
262
+ const encodedArgs =
263
+ definition.definition === undefined
264
+ ? args
265
+ : yield* RpcDefinition.encodeArgs(
266
+ definition.definition,
267
+ methodName as RpcDefinition.Definition.MethodNames<NonNullable<Definition>>,
268
+ args as never,
269
+ ).pipe(
270
+ Effect.mapError(
271
+ (cause) =>
272
+ new ServiceBindingRpcError({
273
+ binding: definition.binding,
274
+ method: methodName,
275
+ cause,
276
+ }),
277
+ ),
278
+ );
279
+
280
+ return yield* RpcInvocation.invokeRpcMethod(
281
+ service,
282
+ method,
283
+ encodedArgs as ServiceMethodArgs<Api, Method>,
284
+ (cause) =>
285
+ new ServiceBindingRpcError({
286
+ binding: definition.binding,
287
+ method: methodName,
288
+ cause,
289
+ }),
290
+ );
291
+ });
292
+
293
+ const decodeSuccess = Effect.fnUntraced(function* <Method extends ServiceMethodKey<Api>>(
294
+ methodName: string,
295
+ value: Awaited<ServiceMethodCloudflareReturn<Api, Method>>,
296
+ ) {
297
+ if (definition.definition === undefined) {
298
+ return value as ServiceMethodSuccess<Api, Method>;
299
+ }
300
+
301
+ const decoded = yield* RpcDefinition.decodeSuccess(
302
+ definition.definition,
303
+ methodName as RpcDefinition.Definition.MethodNames<NonNullable<Definition>>,
304
+ value,
305
+ ).pipe(
306
+ Effect.mapError(
272
307
  (cause) =>
273
308
  new ServiceBindingRpcError({
274
309
  binding: definition.binding,
275
310
  method: methodName,
276
311
  cause,
277
312
  }),
278
- );
279
- });
313
+ ),
314
+ );
280
315
 
281
- const decodeSuccess = <Method extends ServiceMethodKey<Api>>(
282
- methodName: string,
283
- value: Awaited<ServiceMethodCloudflareReturn<Api, Method>>,
284
- ) =>
285
- Effect.gen(function* () {
286
- if (definition.definition === undefined) {
287
- return value as ServiceMethodSuccess<Api, Method>;
288
- }
289
-
290
- const decoded = yield* RpcDefinition.decodeSuccess(
291
- definition.definition,
292
- methodName as RpcDefinition.Definition.MethodNames<NonNullable<Definition>>,
293
- value,
294
- ).pipe(
295
- Effect.mapError(
296
- (cause) =>
297
- new ServiceBindingRpcError({
298
- binding: definition.binding,
299
- method: methodName,
300
- cause,
301
- }),
302
- ),
303
- );
304
-
305
- return decoded as ServiceMethodSuccess<Api, Method>;
306
- });
316
+ return decoded as ServiceMethodSuccess<Api, Method>;
317
+ });
307
318
 
308
- const call = <Method extends ServiceMethodKey<Api>>(
319
+ const call = Effect.fn("ServiceBinding.call")(function* <Method extends ServiceMethodKey<Api>>(
309
320
  method: Method,
310
321
  ...args: ServiceMethodArgs<Api, Method>
311
- ) =>
312
- Effect.gen(function* () {
313
- const methodName = String(method);
314
- const value = yield* CloudflareRpc.resolve(yield* rpc(method, ...args)).pipe(
315
- Effect.mapError(
316
- (cause) =>
317
- new ServiceBindingRpcError({
318
- binding: definition.binding,
319
- method: methodName,
320
- cause,
321
- }),
322
- ),
323
- );
324
-
325
- return yield* decodeSuccess<Method>(methodName, value);
326
- });
322
+ ) {
323
+ const methodName = String(method);
324
+ const value = yield* CloudflareRpc.resolve(yield* rpc(method, ...args)).pipe(
325
+ Effect.mapError(
326
+ (cause) =>
327
+ new ServiceBindingRpcError({
328
+ binding: definition.binding,
329
+ method: methodName,
330
+ cause,
331
+ }),
332
+ ),
333
+ );
327
334
 
328
- const scopedCall = <Method extends ServiceMethodKey<Api>>(
329
- method: Method,
330
- ...args: ServiceMethodArgs<Api, Method>
331
- ) =>
332
- Effect.gen(function* () {
333
- const methodName = String(method);
334
- const result = yield* rpc(method, ...args);
335
- const value = yield* CloudflareRpc.scoped(result);
335
+ return yield* decodeSuccess<Method>(methodName, value);
336
+ });
336
337
 
337
- return yield* decodeSuccess<Method>(methodName, value);
338
- });
338
+ const scopedCall = Effect.fn("ServiceBinding.scopedCall")(function* <
339
+ Method extends ServiceMethodKey<Api>,
340
+ >(method: Method, ...args: ServiceMethodArgs<Api, Method>) {
341
+ const methodName = String(method);
342
+ const result = yield* rpc(method, ...args);
343
+ const value = yield* CloudflareRpc.scoped(result);
344
+
345
+ return yield* decodeSuccess<Method>(methodName, value);
346
+ });
339
347
 
340
348
  const directMethods = makeDirectMethods<never, Api, Definition>(definition.definition, call);
341
349
 
@@ -411,42 +419,38 @@ export const Service =
411
419
  makeClient<ServiceApi, Definition>(definition),
412
420
  );
413
421
 
414
- const fetch = (input: RequestInfo | URL, init?: RequestInit) =>
415
- Effect.gen(function* () {
416
- const service = yield* tag;
422
+ const fetch = Effect.fnUntraced(function* (input: RequestInfo | URL, init?: RequestInit) {
423
+ const service = yield* tag;
417
424
 
418
- return yield* service.fetch(input, init);
419
- });
425
+ return yield* service.fetch(input, init);
426
+ });
420
427
 
421
- const rpc = <Method extends ServiceMethodKey<ServiceApi>>(
428
+ const rpc = Effect.fnUntraced(function* <Method extends ServiceMethodKey<ServiceApi>>(
422
429
  method: Method,
423
430
  ...args: ServiceMethodArgs<ServiceApi, Method>
424
- ) =>
425
- Effect.gen(function* () {
426
- const service = yield* tag;
431
+ ) {
432
+ const service = yield* tag;
427
433
 
428
- return yield* service.rpc(method, ...args);
429
- });
434
+ return yield* service.rpc(method, ...args);
435
+ });
430
436
 
431
- const call = <Method extends ServiceMethodKey<ServiceApi>>(
437
+ const call = Effect.fnUntraced(function* <Method extends ServiceMethodKey<ServiceApi>>(
432
438
  method: Method,
433
439
  ...args: ServiceMethodArgs<ServiceApi, Method>
434
- ) =>
435
- Effect.gen(function* () {
436
- const service = yield* tag;
440
+ ) {
441
+ const service = yield* tag;
437
442
 
438
- return yield* service.call(method, ...args);
439
- });
443
+ return yield* service.call(method, ...args);
444
+ });
440
445
 
441
- const scopedCall = <Method extends ServiceMethodKey<ServiceApi>>(
446
+ const scopedCall = Effect.fnUntraced(function* <Method extends ServiceMethodKey<ServiceApi>>(
442
447
  method: Method,
443
448
  ...args: ServiceMethodArgs<ServiceApi, Method>
444
- ) =>
445
- Effect.gen(function* () {
446
- const service = yield* tag;
449
+ ) {
450
+ const service = yield* tag;
447
451
 
448
- return yield* service.scopedCall(method, ...args);
449
- });
452
+ return yield* service.scopedCall(method, ...args);
453
+ });
450
454
 
451
455
  const directMethods = makeDirectMethods<Self, ServiceApi, Definition>(
452
456
  definition.definition,
package/src/Vectorize.ts CHANGED
@@ -17,16 +17,31 @@ import type {
17
17
 
18
18
  import * as Binding from "./Binding";
19
19
  import type { WorkerEnvironment } from "./Environment";
20
+ import * as ErrorMessage from "./internal/ErrorMessage";
20
21
 
21
22
  const expectedVectorizeBinding =
22
23
  "Vectorize index binding with describe(), query(), insert(), upsert(), deleteByIds(), and getByIds()";
23
24
 
25
+ /** Vectorize operation represented by {@link VectorizeOperationError}. */
26
+ export type VectorizeOperation =
27
+ | "describe"
28
+ | "query"
29
+ | "queryById"
30
+ | "insert"
31
+ | "upsert"
32
+ | "deleteByIds"
33
+ | "getByIds";
34
+
24
35
  /** Error raised when a Vectorize operation fails. */
25
36
  export class VectorizeOperationError extends Data.TaggedError("VectorizeOperationError")<{
26
37
  readonly binding: string;
27
- readonly operation: string;
38
+ readonly operation: VectorizeOperation;
28
39
  readonly cause: unknown;
29
- }> {}
40
+ }> {
41
+ override get message(): string {
42
+ return `Vectorize ${this.operation} failed for binding "${this.binding}": ${ErrorMessage.causeMessage(this.cause)}`;
43
+ }
44
+ }
30
45
 
31
46
  /** Typed Vectorize binding definition. */
32
47
  export interface VectorizeDefinition {
@@ -93,7 +108,7 @@ export interface VectorizeClient {
93
108
  readonly getByIds: (
94
109
  ids: ReadonlyArray<string>,
95
110
  ) => Effect.Effect<ReadonlyArray<VectorizeVector>, VectorizeOperationError>;
96
- readonly unsafeRaw: Effect.Effect<VectorizeBinding>;
111
+ readonly rawUnsafe: Effect.Effect<VectorizeBinding>;
97
112
  readonly definition: VectorizeDefinition;
98
113
  }
99
114
 
@@ -125,12 +140,12 @@ export interface TagClass<Self, Id extends string> extends Context.ServiceClass<
125
140
  >;
126
141
  }
127
142
 
128
- const vectorizeError = (binding: string, operation: string, cause: unknown) =>
143
+ const vectorizeError = (binding: string, operation: VectorizeOperation, cause: unknown) =>
129
144
  new VectorizeOperationError({ binding, operation, cause });
130
145
 
131
146
  const tryVectorizePromise = <A>(
132
147
  binding: string,
133
- operation: string,
148
+ operation: VectorizeOperation,
134
149
  evaluate: () => Promise<A>,
135
150
  ): Effect.Effect<A, VectorizeOperationError> =>
136
151
  Effect.tryPromise({
@@ -138,6 +153,10 @@ const tryVectorizePromise = <A>(
138
153
  catch: (cause) => vectorizeError(binding, operation, cause),
139
154
  });
140
155
 
156
+ const spanOptions = (binding: string, operation: VectorizeOperation) => ({
157
+ attributes: { binding, operation },
158
+ });
159
+
141
160
  const hasFunction = (value: object, key: string): boolean =>
142
161
  typeof Reflect.get(value, key) === "function";
143
162
 
@@ -155,17 +174,30 @@ export const makeClient =
155
174
  (definition: VectorizeDefinition) =>
156
175
  (index: VectorizeBinding): VectorizeClient => {
157
176
  const runtime = index as VectorizeRuntimeBinding;
158
- const deleteByIds = (ids: ReadonlyArray<string>) =>
159
- tryVectorizePromise(definition.binding, "deleteByIds", () => runtime.deleteByIds([...ids]));
177
+ const deleteByIds = Effect.fn(
178
+ "Vectorize.deleteByIds",
179
+ spanOptions(definition.binding, "deleteByIds"),
180
+ )((ids: ReadonlyArray<string>) =>
181
+ tryVectorizePromise(definition.binding, "deleteByIds", () => runtime.deleteByIds([...ids])),
182
+ );
160
183
 
161
184
  return {
162
185
  definition,
163
- describe: tryVectorizePromise(definition.binding, "describe", () => runtime.describe()),
164
- query: (vector, options) =>
186
+ describe: tryVectorizePromise(definition.binding, "describe", () => runtime.describe()).pipe(
187
+ Effect.withSpan("Vectorize.describe", spanOptions(definition.binding, "describe")),
188
+ ),
189
+ query: Effect.fn(
190
+ "Vectorize.query",
191
+ spanOptions(definition.binding, "query"),
192
+ )((vector: VectorizeValues, options?: VectorizeQueryOptions) =>
165
193
  tryVectorizePromise(definition.binding, "query", () =>
166
194
  runtime.query(vector as Float32Array | Float64Array | number[], options),
167
195
  ),
168
- queryById: (vectorId, options) =>
196
+ ),
197
+ queryById: Effect.fn(
198
+ "Vectorize.queryById",
199
+ spanOptions(definition.binding, "queryById"),
200
+ )((vectorId: string, options?: VectorizeQueryOptions) =>
169
201
  runtime.queryById !== undefined
170
202
  ? tryVectorizePromise(definition.binding, "queryById", () =>
171
203
  runtime.queryById!(vectorId, options),
@@ -177,15 +209,28 @@ export const makeClient =
177
209
  new TypeError("Vectorize binding does not expose queryById()"),
178
210
  ),
179
211
  ),
180
- insert: (vectors) =>
212
+ ),
213
+ insert: Effect.fn(
214
+ "Vectorize.insert",
215
+ spanOptions(definition.binding, "insert"),
216
+ )((vectors: ReadonlyArray<VectorizeVector>) =>
181
217
  tryVectorizePromise(definition.binding, "insert", () => runtime.insert([...vectors])),
182
- upsert: (vectors) =>
218
+ ),
219
+ upsert: Effect.fn(
220
+ "Vectorize.upsert",
221
+ spanOptions(definition.binding, "upsert"),
222
+ )((vectors: ReadonlyArray<VectorizeVector>) =>
183
223
  tryVectorizePromise(definition.binding, "upsert", () => runtime.upsert([...vectors])),
224
+ ),
184
225
  deleteByIds,
185
226
  delete: deleteByIds,
186
- getByIds: (ids) =>
227
+ getByIds: Effect.fn(
228
+ "Vectorize.getByIds",
229
+ spanOptions(definition.binding, "getByIds"),
230
+ )((ids: ReadonlyArray<string>) =>
187
231
  tryVectorizePromise(definition.binding, "getByIds", () => runtime.getByIds([...ids])),
188
- unsafeRaw: Effect.succeed(index),
232
+ ),
233
+ rawUnsafe: Effect.succeed(index),
189
234
  };
190
235
  };
191
236