effect-cf 0.27.0 → 0.28.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 (65) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/{Artifacts-DcoXcRP5.d.mts → Artifacts-DnHQA-Ax.d.mts} +42 -25
  3. package/dist/{Artifacts-BhWrdyqX.mjs → Artifacts-rq3hUKQE.mjs} +46 -30
  4. package/dist/{Binding-COCtoJXa.d.mts → Binding-xJJJPmiD.d.mts} +6 -5
  5. package/dist/ComputerArtifacts.d.mts +1 -1
  6. package/dist/ComputerArtifacts.mjs +9 -9
  7. package/dist/ComputerWorkspace.d.mts +5 -5
  8. package/dist/ComputerWorkspace.mjs +107 -75
  9. package/dist/ComputerWorkspaceHost.d.mts +1 -1
  10. package/dist/ComputerWorkspaceHost.mjs +18 -16
  11. package/dist/{DurableObjectState-biHrHwrh.d.mts → DurableObjectState-B3uFY1eM.d.mts} +85 -62
  12. package/dist/{DurableObjectState-Dux8KfjG.mjs → DurableObjectState-BjkK2kwH.mjs} +3 -3
  13. package/dist/{ErrorMessage-_lg53p3W.mjs → ErrorMessage-BM0K-Nik.mjs} +1 -4
  14. package/dist/{Hyperdrive-6p59yyVk.d.mts → Hyperdrive-z-9fFz15.d.mts} +2 -2
  15. package/dist/HyperdrivePg.d.mts +2 -2
  16. package/dist/Vitest.d.mts +6 -5
  17. package/dist/Vitest.mjs +2 -2
  18. package/dist/{WorkflowBinding-zlRPCXVf.d.mts → WorkflowBinding-wZ-yGHow.d.mts} +5 -10
  19. package/dist/index.d.mts +82 -60
  20. package/dist/index.mjs +268 -170
  21. package/package.json +1 -1
  22. package/src/AiGateway.ts +62 -7
  23. package/src/AnalyticsEngine.ts +17 -13
  24. package/src/Artifacts.ts +111 -47
  25. package/src/Binding.ts +34 -23
  26. package/src/BrowserRendering.ts +72 -33
  27. package/src/CloudflareOtlp.ts +8 -5
  28. package/src/ComputerArtifacts.ts +17 -9
  29. package/src/ComputerWorkspace.ts +202 -98
  30. package/src/ComputerWorkspaceHost.ts +55 -27
  31. package/src/ContainerNamespace.ts +8 -9
  32. package/src/D1.ts +8 -14
  33. package/src/DurableObject.ts +27 -11
  34. package/src/DurableObjectAlarm.ts +17 -5
  35. package/src/DurableObjectDefinition.ts +89 -72
  36. package/src/DurableObjectNamespace.ts +26 -12
  37. package/src/DurableObjectRpcWebSocket.ts +9 -10
  38. package/src/DurableObjectState.ts +1 -0
  39. package/src/DurableObjectStorage.ts +5 -2
  40. package/src/DurableObjectWebSocket.ts +4 -1
  41. package/src/Email.ts +26 -25
  42. package/src/Hyperdrive.ts +4 -10
  43. package/src/Images.ts +12 -14
  44. package/src/Kv.ts +15 -17
  45. package/src/Queue.ts +2 -1
  46. package/src/QueueBinding.ts +7 -12
  47. package/src/QueueDefinition.ts +7 -2
  48. package/src/R2.ts +33 -24
  49. package/src/Rpc.ts +15 -21
  50. package/src/RpcDefinition.ts +33 -38
  51. package/src/ServiceBinding.ts +26 -8
  52. package/src/Vectorize.ts +45 -18
  53. package/src/Vitest.ts +9 -3
  54. package/src/WebTransport.ts +11 -5
  55. package/src/Worker.ts +91 -21
  56. package/src/WorkerDefinition.ts +143 -63
  57. package/src/WorkersAi.ts +50 -28
  58. package/src/Workflow.ts +66 -13
  59. package/src/WorkflowBinding.ts +18 -25
  60. package/src/WorkflowDefinition.ts +4 -2
  61. package/src/internal/Entrypoint.ts +29 -13
  62. package/src/internal/ErrorMessage.ts +7 -6
  63. package/src/internal/RpcInvocation.ts +34 -11
  64. package/src/internal/Runtime.ts +33 -22
  65. package/src/internal/WorkerContext.ts +3 -3
@@ -1,4 +1,4 @@
1
- import { Context, Data, Effect, type Layer } from "effect";
1
+ import { Context, Data, Effect, type Layer, Predicate } from "effect";
2
2
 
3
3
  import * as Binding from "./Binding";
4
4
  import type { WorkerEnvironment } from "./Environment";
@@ -26,6 +26,9 @@ export interface BrowserRenderingDefinition {
26
26
  }
27
27
 
28
28
  export type BrowserRenderingBinding = object;
29
+ export interface BrowserRenderingMethodOptions {}
30
+ export type BrowserRenderingExternalResult = Awaited<ReturnType<Response["json"]>>;
31
+ export type BrowserRenderingPageFunction = string | Function;
29
32
  export type BrowserRenderingLaunch<RawBinding, Browser, LaunchOptions = unknown> = (
30
33
  binding: RawBinding,
31
34
  options?: LaunchOptions,
@@ -43,13 +46,19 @@ export interface BrowserRenderingBrowserLike<Page = BrowserRenderingPageLike> {
43
46
  }
44
47
 
45
48
  export interface BrowserRenderingPageLike {
46
- readonly goto?: (url: string, options?: unknown) => Promise<unknown>;
47
- readonly setContent?: (html: string, options?: unknown) => Promise<void>;
49
+ readonly goto?: (
50
+ url: string,
51
+ options?: BrowserRenderingMethodOptions,
52
+ ) => Promise<BrowserRenderingExternalResult>;
53
+ readonly setContent?: (html: string, options?: BrowserRenderingMethodOptions) => Promise<void>;
48
54
  readonly content?: () => Promise<string>;
49
- readonly screenshot?: (options?: unknown) => Promise<Uint8Array | string>;
50
- readonly pdf?: (options?: unknown) => Promise<Uint8Array>;
51
- readonly evaluate?: (pageFunction: unknown, ...args: ReadonlyArray<unknown>) => Promise<unknown>;
52
- readonly close?: (options?: unknown) => Promise<void>;
55
+ readonly screenshot?: (options?: BrowserRenderingMethodOptions) => Promise<Uint8Array | string>;
56
+ readonly pdf?: (options?: BrowserRenderingMethodOptions) => Promise<Uint8Array>;
57
+ readonly evaluate?: (
58
+ pageFunction: BrowserRenderingPageFunction,
59
+ ...args: ReadonlyArray<unknown>
60
+ ) => Promise<BrowserRenderingExternalResult>;
61
+ readonly close?: (options?: BrowserRenderingMethodOptions) => Promise<void>;
53
62
  }
54
63
 
55
64
  export interface BrowserRenderingPageClient<Page extends BrowserRenderingPageLike> {
@@ -66,16 +75,22 @@ export interface BrowserRenderingPageClient<Page extends BrowserRenderingPageLik
66
75
  options?: Parameters<NonNullable<Page["setContent"]>>[1],
67
76
  ) => Effect.Effect<void, BrowserRenderingOperationError>;
68
77
  readonly content: Effect.Effect<string, BrowserRenderingOperationError>;
69
- readonly screenshot: <A = Uint8Array | string>(
78
+ readonly screenshot: (
70
79
  options?: Parameters<NonNullable<Page["screenshot"]>>[0],
71
- ) => Effect.Effect<A, BrowserRenderingOperationError>;
72
- readonly pdf: <A = Uint8Array>(
80
+ ) => Effect.Effect<
81
+ Awaited<ReturnType<NonNullable<Page["screenshot"]>>>,
82
+ BrowserRenderingOperationError
83
+ >;
84
+ readonly pdf: (
73
85
  options?: Parameters<NonNullable<Page["pdf"]>>[0],
74
- ) => Effect.Effect<A, BrowserRenderingOperationError>;
75
- readonly evaluate: <A = unknown>(
86
+ ) => Effect.Effect<Awaited<ReturnType<NonNullable<Page["pdf"]>>>, BrowserRenderingOperationError>;
87
+ readonly evaluate: (
76
88
  pageFunction: Parameters<NonNullable<Page["evaluate"]>>[0],
77
89
  ...args: ReadonlyArray<unknown>
78
- ) => Effect.Effect<A, BrowserRenderingOperationError>;
90
+ ) => Effect.Effect<
91
+ Awaited<ReturnType<NonNullable<Page["evaluate"]>>>,
92
+ BrowserRenderingOperationError
93
+ >;
79
94
  readonly close: (
80
95
  options?: Parameters<NonNullable<Page["close"]>>[0],
81
96
  ) => Effect.Effect<void, BrowserRenderingOperationError>;
@@ -181,6 +196,7 @@ const wrapPage = <Page extends BrowserRenderingPageLike>(
181
196
  ): BrowserRenderingPageClient<Page> => ({
182
197
  raw: page,
183
198
  goto: (url, options) =>
199
+ // SAFETY: the success branch preserves Page.goto's exact awaited return type.
184
200
  (page.goto === undefined
185
201
  ? missingMethod(binding, "goto")
186
202
  : tryBrowserRenderingPromise(binding, "goto", () =>
@@ -197,25 +213,45 @@ const wrapPage = <Page extends BrowserRenderingPageLike>(
197
213
  page.content === undefined
198
214
  ? missingMethod(binding, "content")
199
215
  : tryBrowserRenderingPromise(binding, "content", () => page.content!()),
200
- screenshot: (options) =>
201
- (page.screenshot === undefined
202
- ? missingMethod(binding, "screenshot")
203
- : tryBrowserRenderingPromise(binding, "screenshot", () =>
204
- page.screenshot!(options),
205
- )) as Effect.Effect<never, BrowserRenderingOperationError>,
206
- pdf: (options) =>
207
- (page.pdf === undefined
208
- ? missingMethod(binding, "pdf")
209
- : tryBrowserRenderingPromise(binding, "pdf", () => page.pdf!(options))) as Effect.Effect<
210
- never,
216
+ screenshot: (options) => {
217
+ const screenshot = page.screenshot?.bind(page);
218
+ const effect =
219
+ screenshot === undefined
220
+ ? missingMethod(binding, "screenshot")
221
+ : tryBrowserRenderingPromise(binding, "screenshot", () => screenshot(options));
222
+
223
+ // SAFETY: the success value comes directly from this Page's captured screenshot method.
224
+ return effect as Effect.Effect<
225
+ Awaited<ReturnType<NonNullable<Page["screenshot"]>>>,
211
226
  BrowserRenderingOperationError
212
- >,
213
- evaluate: (pageFunction, ...args) =>
214
- (page.evaluate === undefined
215
- ? missingMethod(binding, "evaluate")
216
- : tryBrowserRenderingPromise(binding, "evaluate", () =>
217
- page.evaluate!(pageFunction, ...args),
218
- )) as Effect.Effect<never, BrowserRenderingOperationError>,
227
+ >;
228
+ },
229
+ pdf: (options) => {
230
+ const pdf = page.pdf?.bind(page);
231
+ const effect =
232
+ pdf === undefined
233
+ ? missingMethod(binding, "pdf")
234
+ : tryBrowserRenderingPromise(binding, "pdf", () => pdf(options));
235
+
236
+ // SAFETY: the success value comes directly from this Page's captured pdf method.
237
+ return effect as Effect.Effect<
238
+ Awaited<ReturnType<NonNullable<Page["pdf"]>>>,
239
+ BrowserRenderingOperationError
240
+ >;
241
+ },
242
+ evaluate: (pageFunction, ...args) => {
243
+ const evaluate = page.evaluate?.bind(page);
244
+ const effect =
245
+ evaluate === undefined
246
+ ? missingMethod(binding, "evaluate")
247
+ : tryBrowserRenderingPromise(binding, "evaluate", () => evaluate(pageFunction, ...args));
248
+
249
+ // SAFETY: the success value comes directly from this Page's captured evaluate method.
250
+ return effect as Effect.Effect<
251
+ Awaited<ReturnType<NonNullable<Page["evaluate"]>>>,
252
+ BrowserRenderingOperationError
253
+ >;
254
+ },
219
255
  close: (options) =>
220
256
  page.close === undefined
221
257
  ? Effect.void
@@ -247,8 +283,10 @@ const wrapBrowser = <
247
283
  : tryBrowserRenderingSync(binding, "disconnect", () => browser.disconnect!()),
248
284
  });
249
285
 
250
- export const isBrowserRenderingBinding = (value: unknown): value is BrowserRenderingBinding =>
251
- (typeof value === "object" || typeof value === "function") && value !== null;
286
+ export const isBrowserRenderingBinding = <Candidate>(
287
+ value: Candidate,
288
+ ): value is Candidate & BrowserRenderingBinding =>
289
+ Predicate.isObjectOrArray(value) || Predicate.isFunction(value);
252
290
 
253
291
  export const makeClient =
254
292
  <RawBinding extends BrowserRenderingBinding = BrowserRenderingBinding>(
@@ -302,6 +340,7 @@ export const Tag =
302
340
 
303
341
  const makeLayer = (definition: LayerOptions) => layer(tag, definition);
304
342
 
343
+ // SAFETY: these are exactly the members required by TagClass, attached to the matching service tag.
305
344
  return Object.assign(tag, {
306
345
  id,
307
346
  layer: makeLayer,
@@ -24,6 +24,7 @@ import {
24
24
  OtlpExporter,
25
25
  OtlpLogger,
26
26
  OtlpMetrics,
27
+ OtlpResource,
27
28
  OtlpSerialization,
28
29
  OtlpTracer,
29
30
  } from "effect/unstable/observability";
@@ -31,6 +32,8 @@ import {
31
32
  import { DurableObjectState } from "./DurableObjectState";
32
33
  import { WorkerConfig, WorkerEnvironment } from "./Environment";
33
34
 
35
+ type ResourceAttributes = NonNullable<Parameters<typeof OtlpResource.make>[0]["attributes"]>;
36
+
34
37
  /** Telemetry signal groups supported by the Cloudflare OTLP layers. */
35
38
  export type Signal = "logs" | "traces" | "metrics";
36
39
 
@@ -52,7 +55,7 @@ export interface ResourceOptions {
52
55
  /** Explicit service version. Takes precedence over OTEL environment variables. */
53
56
  readonly serviceVersion?: string;
54
57
  /** Additional resource attributes attached to exported telemetry. */
55
- readonly attributes?: Record<string, unknown>;
58
+ readonly attributes?: ResourceAttributes;
56
59
  }
57
60
 
58
61
  /** Options shared by all Cloudflare OTLP telemetry layers. */
@@ -115,8 +118,8 @@ const cloudflareConfigProviderLayer = ConfigProvider.layerAdd(
115
118
  const selectedSignals = (signals: ReadonlyArray<Signal> | undefined): ReadonlySet<Signal> =>
116
119
  new Set(signals ?? allSignals);
117
120
 
118
- const withDefinedAttributes = (attributes: Record<string, unknown>): Record<string, unknown> => {
119
- const out: Record<string, unknown> = {};
121
+ const withDefinedAttributes = (attributes: ResourceAttributes): ResourceAttributes => {
122
+ const out: ResourceAttributes = {};
120
123
 
121
124
  for (const [key, value] of Object.entries(attributes)) {
122
125
  if (value !== undefined) {
@@ -129,7 +132,7 @@ const withDefinedAttributes = (attributes: Record<string, unknown>): Record<stri
129
132
 
130
133
  const makeResource = (
131
134
  options: LayerOptions,
132
- runtimeAttributes: Record<string, unknown>,
135
+ runtimeAttributes: ResourceAttributes,
133
136
  ): ResourceOptions => ({
134
137
  serviceName: options.resource?.serviceName,
135
138
  serviceVersion: options.resource?.serviceVersion,
@@ -157,7 +160,7 @@ const mergeSignalLayers = (layers: ReadonlyArray<SignalLayer>): SignalLayer => {
157
160
 
158
161
  const makeLayer = (
159
162
  options: LayerOptions = {},
160
- runtimeAttributes: Record<string, unknown> = {},
163
+ runtimeAttributes: ResourceAttributes = {},
161
164
  ): Layer.Layer<OtlpExporter.Flusher> => {
162
165
  const signals = selectedSignals(options.signals);
163
166
  const resource = makeResource(options, runtimeAttributes);
@@ -8,7 +8,7 @@ import type {
8
8
  ArtifactsCLIResult as CloudflareComputerArtifactsCliResult,
9
9
  RemoteAddFn as CloudflareComputerRemoteAdd,
10
10
  } from "@cloudflare/computer/artifacts";
11
- import { Effect } from "effect";
11
+ import { Effect, Predicate } from "effect";
12
12
 
13
13
  import * as Artifacts from "./Artifacts";
14
14
 
@@ -39,6 +39,11 @@ export interface ComputerArtifactsClientOptions {
39
39
  readonly binding?: string;
40
40
  }
41
41
 
42
+ interface MutableArtifactsErrorDetails {
43
+ code?: Artifacts.ArtifactsOperationError["code"];
44
+ numericCode?: number;
45
+ }
46
+
42
47
  /**
43
48
  * Effect-native facade over `@cloudflare/computer/artifacts`.
44
49
  *
@@ -93,17 +98,18 @@ export interface ComputerArtifactsClient {
93
98
  const artifactsErrorDetails = (
94
99
  cause: unknown,
95
100
  ): Pick<Artifacts.ArtifactsOperationError, "code" | "numericCode"> => {
96
- if (typeof cause !== "object" || cause === null) {
101
+ if (!Predicate.isObject(cause)) {
97
102
  return {};
98
103
  }
99
104
 
100
- const code = Reflect.get(cause, "code");
101
- const numericCode = Reflect.get(cause, "numericCode");
105
+ const code = Predicate.hasProperty(cause, "code") ? cause.code : undefined;
106
+ const numericCode = Predicate.hasProperty(cause, "numericCode") ? cause.numericCode : undefined;
107
+ const details: MutableArtifactsErrorDetails = {};
102
108
 
103
- return {
104
- ...(typeof code === "string" ? { code } : {}),
105
- ...(typeof numericCode === "number" ? { numericCode } : {}),
106
- };
109
+ if (Predicate.isString(code)) details.code = code;
110
+ if (Predicate.isNumber(numericCode)) details.numericCode = numericCode;
111
+
112
+ return details;
107
113
  };
108
114
 
109
115
  const operationError = (binding: string, operation: Artifacts.ArtifactsOperation, cause: unknown) =>
@@ -244,8 +250,10 @@ export const makeClient = Effect.fn("ComputerArtifacts.makeClient")(function* (
244
250
  });
245
251
  const client = yield* Effect.try({
246
252
  try: () =>
253
+ // SAFETY: both packages describe the same Cloudflare Artifacts binding runtime object.
247
254
  computerArtifacts.createArtifact(
248
- bindingValue as unknown as Parameters<typeof computerArtifacts.createArtifact>[0],
255
+ bindingValue as Artifacts.ArtifactsBinding &
256
+ Parameters<typeof computerArtifacts.createArtifact>[0],
249
257
  sessionId,
250
258
  ),
251
259
  catch: (cause) => operationError(binding, "createClient", cause),