effect-cf 0.20.0 → 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.
- package/CHANGELOG.md +56 -0
- package/README.md +2 -2
- package/dist/{Hyperdrive-RTjgirMV.d.mts → Hyperdrive-COyg7R26.d.mts} +40 -13
- package/dist/HyperdrivePg.d.mts +13 -5
- package/dist/HyperdrivePg.mjs +12 -7
- package/dist/index.d.mts +708 -549
- package/dist/index.mjs +946 -589
- package/package.json +10 -5
- package/src/AiGateway.ts +82 -47
- package/src/AnalyticsEngine.ts +74 -58
- package/src/Binding.ts +66 -13
- package/src/BrowserRendering.ts +30 -7
- package/src/Cache.ts +32 -8
- package/src/CloudflareOtlp.ts +32 -9
- package/src/ContainerNamespace.ts +87 -55
- package/src/D1.ts +13 -3
- package/src/DurableObject.ts +27 -164
- package/src/DurableObjectAlarm.ts +30 -9
- package/src/DurableObjectDefinition.ts +58 -54
- package/src/DurableObjectNamespace.ts +99 -96
- package/src/DurableObjectRpcWebSocket.ts +14 -6
- package/src/DurableObjectSqlite.ts +6 -3
- package/src/DurableObjectState.ts +6 -9
- package/src/DurableObjectStorage.ts +7 -1
- package/src/DurableObjectWebSocket.ts +51 -41
- package/src/Email.ts +40 -13
- package/src/Environment.ts +26 -6
- package/src/Hyperdrive.ts +2 -2
- package/src/HyperdrivePg.ts +25 -13
- package/src/Images.ts +77 -82
- package/src/Kv.ts +37 -27
- package/src/Queue.ts +6 -1
- package/src/QueueBinding.ts +18 -21
- package/src/QueueDefinition.ts +15 -14
- package/src/R2.ts +107 -29
- package/src/Rpc.ts +3 -1
- package/src/RpcDefinition.ts +177 -133
- package/src/ServiceBinding.ts +112 -108
- package/src/Vectorize.ts +59 -14
- package/src/Worker.ts +205 -198
- package/src/WorkerDefinition.ts +5 -10
- package/src/WorkersAi.ts +27 -17
- package/src/Workflow.ts +54 -49
- package/src/WorkflowBinding.ts +19 -11
- package/src/WorkflowDefinition.ts +24 -27
- package/src/index.ts +4 -3
- package/src/internal/Entrypoint.ts +3 -1
- package/src/internal/ErrorMessage.ts +24 -0
- package/src/internal/RpcInvocation.ts +11 -8
- package/src/internal/Runtime.ts +52 -0
- package/src/internal/WorkerContext.ts +14 -2
- package/src/Entry.ts +0 -259
- package/src/internal/Clock.ts +0 -37
package/src/QueueDefinition.ts
CHANGED
|
@@ -44,7 +44,11 @@ export interface TagClass<
|
|
|
44
44
|
Self,
|
|
45
45
|
Id extends string,
|
|
46
46
|
Message extends RpcDefinition.ServiceFreeSchema,
|
|
47
|
-
> extends Context.ServiceClass<
|
|
47
|
+
> extends Context.ServiceClass<
|
|
48
|
+
Self,
|
|
49
|
+
`effect-cf/Queue/${Id}`,
|
|
50
|
+
QueueBinding.QueueBindingClient<Message>
|
|
51
|
+
> {
|
|
48
52
|
readonly id: Id;
|
|
49
53
|
readonly message: Message;
|
|
50
54
|
readonly make: <ROut, LayerError>(
|
|
@@ -71,7 +75,7 @@ export interface TagClass<
|
|
|
71
75
|
QueueBinding.QueueOperationError,
|
|
72
76
|
Self
|
|
73
77
|
>;
|
|
74
|
-
readonly
|
|
78
|
+
readonly rawUnsafe: Effect.Effect<globalThis.Queue<S.Codec.Encoded<Message>>, never, Self>;
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
const makeDefinition = <Id extends string, Message extends RpcDefinition.ServiceFreeSchema>(
|
|
@@ -108,7 +112,9 @@ export const Tag =
|
|
|
108
112
|
definition: { readonly message: Message },
|
|
109
113
|
) => {
|
|
110
114
|
const queueDefinition = makeDefinition(id, definition);
|
|
111
|
-
const tag = Context.Service<Self, QueueBinding.QueueBindingClient<Message>>()(
|
|
115
|
+
const tag = Context.Service<Self, QueueBinding.QueueBindingClient<Message>>()(
|
|
116
|
+
`effect-cf/Queue/${id}` as const,
|
|
117
|
+
);
|
|
112
118
|
|
|
113
119
|
const layer = (binding: LayerOptions) =>
|
|
114
120
|
QueueBinding.layer(tag, {
|
|
@@ -140,11 +146,7 @@ export const Tag =
|
|
|
140
146
|
return yield* queue.metrics();
|
|
141
147
|
});
|
|
142
148
|
|
|
143
|
-
const
|
|
144
|
-
const queue = yield* tag;
|
|
145
|
-
|
|
146
|
-
return yield* queue.unsafeRaw;
|
|
147
|
-
});
|
|
149
|
+
const rawUnsafe = Effect.flatMap(tag, (queue) => queue.rawUnsafe);
|
|
148
150
|
|
|
149
151
|
return Object.assign(tag, {
|
|
150
152
|
id: queueDefinition.id,
|
|
@@ -154,7 +156,7 @@ export const Tag =
|
|
|
154
156
|
send,
|
|
155
157
|
sendBatch,
|
|
156
158
|
metrics,
|
|
157
|
-
|
|
159
|
+
rawUnsafe,
|
|
158
160
|
}) as TagClass<Self, Id, Message>;
|
|
159
161
|
};
|
|
160
162
|
|
|
@@ -166,12 +168,11 @@ const wrapHandler = <ROut, const Self extends Definition.Any>(
|
|
|
166
168
|
): QueueEntrypoint.QueueHandler<ROut> => {
|
|
167
169
|
const decodeBody = S.decodeUnknownEffect(definition.message);
|
|
168
170
|
|
|
169
|
-
return (batch)
|
|
170
|
-
|
|
171
|
-
const decoded = yield* QueueEntrypoint.decodeBatch(batch.raw, decodeBody);
|
|
171
|
+
return Effect.fnUntraced(function* (batch: QueueEntrypoint.QueueBatch<unknown>) {
|
|
172
|
+
const decoded = yield* QueueEntrypoint.decodeBatch(batch.raw, decodeBody);
|
|
172
173
|
|
|
173
|
-
|
|
174
|
-
|
|
174
|
+
yield* handler(decoded);
|
|
175
|
+
});
|
|
175
176
|
};
|
|
176
177
|
|
|
177
178
|
export const implement = <ROut, const Self extends Definition.Any>(
|
package/src/R2.ts
CHANGED
|
@@ -16,16 +16,39 @@ import { Context, Data, Effect, Option, type Layer } from "effect";
|
|
|
16
16
|
|
|
17
17
|
import * as Binding from "./Binding";
|
|
18
18
|
import type { WorkerEnvironment } from "./Environment";
|
|
19
|
+
import * as ErrorMessage from "./internal/ErrorMessage";
|
|
19
20
|
|
|
20
21
|
const expectedR2Bucket =
|
|
21
22
|
"R2 bucket binding with head(), get(), put(), createMultipartUpload(), resumeMultipartUpload(), delete(), and list()";
|
|
22
23
|
|
|
24
|
+
/** R2 operation represented by {@link R2OperationError}. */
|
|
25
|
+
export type R2Operation =
|
|
26
|
+
| "head"
|
|
27
|
+
| "get"
|
|
28
|
+
| "put"
|
|
29
|
+
| "delete"
|
|
30
|
+
| "list"
|
|
31
|
+
| "createMultipartUpload"
|
|
32
|
+
| "resumeMultipartUpload"
|
|
33
|
+
| "uploadPart"
|
|
34
|
+
| "abortMultipartUpload"
|
|
35
|
+
| "completeMultipartUpload"
|
|
36
|
+
| "arrayBuffer"
|
|
37
|
+
| "bytes"
|
|
38
|
+
| "text"
|
|
39
|
+
| "json"
|
|
40
|
+
| "blob";
|
|
41
|
+
|
|
23
42
|
/** Error raised when an R2 operation fails. */
|
|
24
43
|
export class R2OperationError extends Data.TaggedError("R2OperationError")<{
|
|
25
44
|
readonly binding: string;
|
|
26
|
-
readonly operation:
|
|
45
|
+
readonly operation: R2Operation;
|
|
27
46
|
readonly cause: unknown;
|
|
28
|
-
}> {
|
|
47
|
+
}> {
|
|
48
|
+
override get message(): string {
|
|
49
|
+
return `R2 ${this.operation} failed for binding "${this.binding}": ${ErrorMessage.causeMessage(this.cause)}`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
29
52
|
|
|
30
53
|
/** Typed R2 bucket binding definition. */
|
|
31
54
|
export interface R2Definition {
|
|
@@ -104,7 +127,7 @@ export interface R2Client {
|
|
|
104
127
|
) => Effect.Effect<R2MultipartUploadClient, R2OperationError>;
|
|
105
128
|
readonly delete: (keys: string | ReadonlyArray<string>) => Effect.Effect<void, R2OperationError>;
|
|
106
129
|
readonly list: (options?: R2ListOptions) => Effect.Effect<CloudflareR2Objects, R2OperationError>;
|
|
107
|
-
readonly
|
|
130
|
+
readonly rawUnsafe: Effect.Effect<CloudflareR2Bucket>;
|
|
108
131
|
readonly definition: R2Definition;
|
|
109
132
|
}
|
|
110
133
|
|
|
@@ -136,12 +159,12 @@ export interface TagClass<Self, Id extends string> extends Context.ServiceClass<
|
|
|
136
159
|
>;
|
|
137
160
|
}
|
|
138
161
|
|
|
139
|
-
const r2Error = (binding: string, operation:
|
|
162
|
+
const r2Error = (binding: string, operation: R2Operation, cause: unknown) =>
|
|
140
163
|
new R2OperationError({ binding, operation, cause });
|
|
141
164
|
|
|
142
165
|
const tryR2Promise = <A>(
|
|
143
166
|
binding: string,
|
|
144
|
-
operation:
|
|
167
|
+
operation: R2Operation,
|
|
145
168
|
evaluate: () => Promise<A>,
|
|
146
169
|
): Effect.Effect<A, R2OperationError> =>
|
|
147
170
|
Effect.tryPromise({
|
|
@@ -151,7 +174,7 @@ const tryR2Promise = <A>(
|
|
|
151
174
|
|
|
152
175
|
const tryR2Sync = <A>(
|
|
153
176
|
binding: string,
|
|
154
|
-
operation:
|
|
177
|
+
operation: R2Operation,
|
|
155
178
|
evaluate: () => A,
|
|
156
179
|
): Effect.Effect<A, R2OperationError> =>
|
|
157
180
|
Effect.try({
|
|
@@ -159,8 +182,9 @@ const tryR2Sync = <A>(
|
|
|
159
182
|
catch: (cause) => r2Error(binding, operation, cause),
|
|
160
183
|
});
|
|
161
184
|
|
|
162
|
-
const
|
|
163
|
-
|
|
185
|
+
const spanOptions = (binding: string, operation: R2Operation) => ({
|
|
186
|
+
attributes: { binding, operation },
|
|
187
|
+
});
|
|
164
188
|
|
|
165
189
|
const isR2ObjectBody = (
|
|
166
190
|
value: CloudflareR2ObjectBody | CloudflareR2Object,
|
|
@@ -191,11 +215,22 @@ const wrapObjectBody = (binding: string, object: CloudflareR2ObjectBody): R2Obje
|
|
|
191
215
|
get bodyUsed() {
|
|
192
216
|
return object.bodyUsed;
|
|
193
217
|
},
|
|
194
|
-
arrayBuffer: tryR2Promise(binding, "arrayBuffer", () => object.arrayBuffer())
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
218
|
+
arrayBuffer: tryR2Promise(binding, "arrayBuffer", () => object.arrayBuffer()).pipe(
|
|
219
|
+
Effect.withSpan("R2.arrayBuffer", spanOptions(binding, "arrayBuffer")),
|
|
220
|
+
),
|
|
221
|
+
bytes: tryR2Promise(binding, "bytes", () => object.bytes()).pipe(
|
|
222
|
+
Effect.withSpan("R2.bytes", spanOptions(binding, "bytes")),
|
|
223
|
+
),
|
|
224
|
+
text: tryR2Promise(binding, "text", () => object.text()).pipe(
|
|
225
|
+
Effect.withSpan("R2.text", spanOptions(binding, "text")),
|
|
226
|
+
),
|
|
227
|
+
json: <T = unknown>() =>
|
|
228
|
+
tryR2Promise(binding, "json", () => object.json<T>()).pipe(
|
|
229
|
+
Effect.withSpan("R2.json", spanOptions(binding, "json")),
|
|
230
|
+
),
|
|
231
|
+
blob: tryR2Promise(binding, "blob", () => object.blob()).pipe(
|
|
232
|
+
Effect.withSpan("R2.blob", spanOptions(binding, "blob")),
|
|
233
|
+
),
|
|
199
234
|
});
|
|
200
235
|
|
|
201
236
|
const wrapGetResult = (
|
|
@@ -234,29 +269,55 @@ export const makeClient = (
|
|
|
234
269
|
raw: upload,
|
|
235
270
|
key: upload.key,
|
|
236
271
|
uploadId: upload.uploadId,
|
|
237
|
-
uploadPart: (
|
|
272
|
+
uploadPart: Effect.fn(
|
|
273
|
+
"R2.uploadPart",
|
|
274
|
+
spanOptions(definition.binding, "uploadPart"),
|
|
275
|
+
)((partNumber: number, value: R2UploadPartValue, options?: R2UploadPartOptions) =>
|
|
238
276
|
tryR2Promise(definition.binding, "uploadPart", () =>
|
|
239
277
|
upload.uploadPart(partNumber, value, options),
|
|
240
278
|
),
|
|
241
|
-
|
|
242
|
-
|
|
279
|
+
),
|
|
280
|
+
abort: tryR2Promise(definition.binding, "abortMultipartUpload", () => upload.abort()).pipe(
|
|
281
|
+
Effect.withSpan(
|
|
282
|
+
"R2.abortMultipartUpload",
|
|
283
|
+
spanOptions(definition.binding, "abortMultipartUpload"),
|
|
284
|
+
),
|
|
285
|
+
),
|
|
286
|
+
complete: Effect.fn(
|
|
287
|
+
"R2.completeMultipartUpload",
|
|
288
|
+
spanOptions(definition.binding, "completeMultipartUpload"),
|
|
289
|
+
)((uploadedParts: ReadonlyArray<CloudflareR2UploadedPart>) =>
|
|
243
290
|
tryR2Promise(definition.binding, "completeMultipartUpload", () =>
|
|
244
291
|
upload.complete([...uploadedParts]),
|
|
245
292
|
),
|
|
293
|
+
),
|
|
246
294
|
});
|
|
247
295
|
|
|
248
296
|
return (bucket) => {
|
|
249
|
-
const get = (
|
|
297
|
+
const get = Effect.fn(
|
|
298
|
+
"R2.get",
|
|
299
|
+
spanOptions(definition.binding, "get"),
|
|
300
|
+
)((key: string, options?: R2GetOptions) =>
|
|
250
301
|
tryR2Promise(definition.binding, "get", () => bucket.get(key, options)).pipe(
|
|
251
|
-
Effect.map((object) =>
|
|
252
|
-
)
|
|
302
|
+
Effect.map((object) => Option.fromNullOr(wrapGetResult(definition.binding, object))),
|
|
303
|
+
),
|
|
304
|
+
) as R2Client["get"];
|
|
253
305
|
|
|
254
306
|
return {
|
|
255
307
|
definition,
|
|
256
|
-
head: (
|
|
257
|
-
|
|
308
|
+
head: Effect.fn(
|
|
309
|
+
"R2.head",
|
|
310
|
+
spanOptions(definition.binding, "head"),
|
|
311
|
+
)((key: string) =>
|
|
312
|
+
tryR2Promise(definition.binding, "head", () => bucket.head(key)).pipe(
|
|
313
|
+
Effect.map(Option.fromNullOr),
|
|
314
|
+
),
|
|
315
|
+
),
|
|
258
316
|
get,
|
|
259
|
-
put: (
|
|
317
|
+
put: Effect.fn(
|
|
318
|
+
"R2.put",
|
|
319
|
+
spanOptions(definition.binding, "put"),
|
|
320
|
+
)((key: string, value: R2PutValue, options?: R2PutOptions) =>
|
|
260
321
|
tryR2Promise(definition.binding, "put", () => bucket.put(key, value, options)).pipe(
|
|
261
322
|
Effect.map((object) => {
|
|
262
323
|
if (object === null) {
|
|
@@ -269,22 +330,39 @@ export const makeClient = (
|
|
|
269
330
|
|
|
270
331
|
return object;
|
|
271
332
|
}),
|
|
272
|
-
)
|
|
273
|
-
|
|
333
|
+
),
|
|
334
|
+
) as R2Client["put"],
|
|
335
|
+
createMultipartUpload: Effect.fn(
|
|
336
|
+
"R2.createMultipartUpload",
|
|
337
|
+
spanOptions(definition.binding, "createMultipartUpload"),
|
|
338
|
+
)((key: string, options?: R2MultipartOptions) =>
|
|
274
339
|
tryR2Promise(definition.binding, "createMultipartUpload", () =>
|
|
275
340
|
bucket.createMultipartUpload(key, options),
|
|
276
341
|
).pipe(Effect.map(wrapUpload)),
|
|
277
|
-
|
|
342
|
+
),
|
|
343
|
+
resumeMultipartUpload: Effect.fn(
|
|
344
|
+
"R2.resumeMultipartUpload",
|
|
345
|
+
spanOptions(definition.binding, "resumeMultipartUpload"),
|
|
346
|
+
)((key: string, uploadId: string) =>
|
|
278
347
|
tryR2Sync(definition.binding, "resumeMultipartUpload", () =>
|
|
279
348
|
wrapUpload(bucket.resumeMultipartUpload(key, uploadId)),
|
|
280
349
|
),
|
|
281
|
-
|
|
350
|
+
),
|
|
351
|
+
delete: Effect.fn(
|
|
352
|
+
"R2.delete",
|
|
353
|
+
spanOptions(definition.binding, "delete"),
|
|
354
|
+
)((keys: string | ReadonlyArray<string>) => {
|
|
282
355
|
const nativeKeys = typeof keys === "string" ? keys : [...keys];
|
|
283
356
|
|
|
284
357
|
return tryR2Promise(definition.binding, "delete", () => bucket.delete(nativeKeys));
|
|
285
|
-
},
|
|
286
|
-
list:
|
|
287
|
-
|
|
358
|
+
}),
|
|
359
|
+
list: Effect.fn(
|
|
360
|
+
"R2.list",
|
|
361
|
+
spanOptions(definition.binding, "list"),
|
|
362
|
+
)((options?: R2ListOptions) =>
|
|
363
|
+
tryR2Promise(definition.binding, "list", () => bucket.list(options)),
|
|
364
|
+
),
|
|
365
|
+
rawUnsafe: Effect.succeed(bucket),
|
|
288
366
|
};
|
|
289
367
|
};
|
|
290
368
|
};
|
package/src/Rpc.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { RpcStub, RpcTarget } from "cloudflare:workers";
|
|
2
2
|
import { Effect, type Scope } from "effect";
|
|
3
3
|
|
|
4
|
+
import { decodeWireError } from "./RpcDefinition";
|
|
5
|
+
|
|
4
6
|
export { RpcStub, RpcTarget };
|
|
5
7
|
|
|
6
8
|
export type Stubable = Rpc.Stubable;
|
|
@@ -113,7 +115,7 @@ export const resolve = <A>(value: A): Effect.Effect<Awaited<A>, unknown> =>
|
|
|
113
115
|
isPromiseLike(value)
|
|
114
116
|
? Effect.tryPromise({
|
|
115
117
|
try: () => value,
|
|
116
|
-
catch: (cause) => cause,
|
|
118
|
+
catch: (cause) => decodeWireError(cause),
|
|
117
119
|
})
|
|
118
120
|
: Effect.sync(() => value as Awaited<A>);
|
|
119
121
|
|