effect-cf 0.0.4 → 0.2.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 +21 -0
- package/LICENSE +21 -0
- package/README.md +163 -46
- package/dist/index.d.mts +1234 -309
- package/dist/index.mjs +944 -126
- package/package.json +3 -2
- package/src/DurableObject.ts +26 -2
- package/src/DurableObjectAlarm.ts +832 -0
- package/src/DurableObjectRpcWebSocket.ts +21 -17
- package/src/DurableObjectState.ts +12 -10
- package/src/DurableObjectWebSocket.ts +215 -6
- package/src/Queue.ts +116 -0
- package/src/QueueBinding.ts +131 -0
- package/src/QueueDefinition.ts +129 -0
- package/src/Worker.ts +57 -68
- package/src/WorkerDefinition.ts +6 -0
- package/src/Workflow.ts +279 -0
- package/src/WorkflowBinding.ts +254 -0
- package/src/WorkflowDefinition.ts +167 -0
- package/src/index.ts +7 -0
- package/src/internal/WorkerContext.ts +83 -0
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-CfYAbeIz.mjs";
|
|
2
|
-
import { Cause, Config, ConfigProvider, Context, Data, Effect, Exit, Layer, ManagedRuntime, Option, Queue, Schema } from "effect";
|
|
3
|
-
import { DurableObject, RpcStub, RpcTarget, WorkerEntrypoint } from "cloudflare:workers";
|
|
2
|
+
import { Cause, Clock, Config, ConfigProvider, Context, Data, DateTime, Duration, Effect, Exit, Layer, ManagedRuntime, Option, Queue, Schema } from "effect";
|
|
3
|
+
import { DurableObject, RpcStub, RpcTarget, WorkerEntrypoint, WorkflowEntrypoint } from "cloudflare:workers";
|
|
4
4
|
import { HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
|
|
5
5
|
import * as RpcMessage from "effect/unstable/rpc/RpcMessage";
|
|
6
6
|
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
|
|
@@ -28,11 +28,11 @@ let WorkerConfig;
|
|
|
28
28
|
var Binding_exports = /* @__PURE__ */ __exportAll({
|
|
29
29
|
BindingNotFoundError: () => BindingNotFoundError,
|
|
30
30
|
BindingValidationError: () => BindingValidationError,
|
|
31
|
-
Service: () => Service$
|
|
32
|
-
TypeId: () => TypeId$
|
|
31
|
+
Service: () => Service$5,
|
|
32
|
+
TypeId: () => TypeId$5
|
|
33
33
|
});
|
|
34
34
|
/** Internal type id marker used by binding helper services. */
|
|
35
|
-
const TypeId$
|
|
35
|
+
const TypeId$5 = "effect-cf/Binding";
|
|
36
36
|
/** Error raised when a configured binding does not exist on `env`. */
|
|
37
37
|
var BindingNotFoundError = class extends Data.TaggedError("BindingNotFoundError") {};
|
|
38
38
|
/** Error raised when a binding exists but does not match the expected shape. */
|
|
@@ -48,18 +48,167 @@ const getBinding = (env, binding, isResource) => Effect.gen(function* () {
|
|
|
48
48
|
/**
|
|
49
49
|
* Creates a Context tag + layer for reading and validating a Cloudflare binding.
|
|
50
50
|
*/
|
|
51
|
-
const Service$
|
|
51
|
+
const Service$5 = () => (id, binding, isResource) => {
|
|
52
52
|
const tag = Context.Service()(id);
|
|
53
53
|
const layer = Layer.effect(tag, Effect.gen(function* () {
|
|
54
54
|
return yield* getBinding(yield* WorkerEnvironment, binding, isResource);
|
|
55
55
|
}));
|
|
56
56
|
return Object.assign(tag, {
|
|
57
|
-
[TypeId$
|
|
57
|
+
[TypeId$5]: TypeId$5,
|
|
58
58
|
binding,
|
|
59
59
|
layer
|
|
60
60
|
});
|
|
61
61
|
};
|
|
62
62
|
//#endregion
|
|
63
|
+
//#region src/QueueBinding.ts
|
|
64
|
+
var QueueBinding_exports = /* @__PURE__ */ __exportAll({
|
|
65
|
+
QueueOperationError: () => QueueOperationError,
|
|
66
|
+
Service: () => Service$4,
|
|
67
|
+
make: () => make$10
|
|
68
|
+
});
|
|
69
|
+
const TypeId$4 = "effect-cf/QueueBinding";
|
|
70
|
+
var QueueOperationError = class extends Data.TaggedError("QueueOperationError") {};
|
|
71
|
+
const queueError = (binding, operation, cause) => new QueueOperationError({
|
|
72
|
+
binding,
|
|
73
|
+
operation,
|
|
74
|
+
cause
|
|
75
|
+
});
|
|
76
|
+
const tryQueuePromise = (binding, operation, evaluate) => Effect.tryPromise({
|
|
77
|
+
try: evaluate,
|
|
78
|
+
catch: (cause) => queueError(binding, operation, cause)
|
|
79
|
+
});
|
|
80
|
+
const isQueue = (value) => {
|
|
81
|
+
if (typeof value !== "object" || value === null) return false;
|
|
82
|
+
const resource = value;
|
|
83
|
+
return typeof resource.send === "function" && typeof resource.sendBatch === "function" && typeof resource.metrics === "function";
|
|
84
|
+
};
|
|
85
|
+
/** Creates a typed Queue binding service tag plus Effect helpers. */
|
|
86
|
+
const make$10 = (id, definition) => Service$4()(id, definition);
|
|
87
|
+
/**
|
|
88
|
+
* Builds an Effect service around a Cloudflare Queue producer binding.
|
|
89
|
+
*/
|
|
90
|
+
const Service$4 = () => (id, definition) => {
|
|
91
|
+
const tag = Service$5()(id, definition.binding, (value) => isQueue(value));
|
|
92
|
+
const encodeMessage = Schema.encodeEffect(definition.message);
|
|
93
|
+
const send = Effect.fnUntraced(function* (message, options) {
|
|
94
|
+
const queue = yield* tag;
|
|
95
|
+
const encoded = yield* encodeMessage(message);
|
|
96
|
+
return yield* tryQueuePromise(definition.binding, "send", () => queue.send(encoded, options));
|
|
97
|
+
});
|
|
98
|
+
const sendBatch = Effect.fnUntraced(function* (messages, options) {
|
|
99
|
+
const queue = yield* tag;
|
|
100
|
+
const encodedMessages = [];
|
|
101
|
+
for (const message of messages) encodedMessages.push({
|
|
102
|
+
...message,
|
|
103
|
+
body: yield* encodeMessage(message.body)
|
|
104
|
+
});
|
|
105
|
+
return yield* tryQueuePromise(definition.binding, "sendBatch", () => queue.sendBatch(encodedMessages, options));
|
|
106
|
+
});
|
|
107
|
+
const metrics = Effect.fnUntraced(function* () {
|
|
108
|
+
const queue = yield* tag;
|
|
109
|
+
return yield* tryQueuePromise(definition.binding, "metrics", () => queue.metrics());
|
|
110
|
+
});
|
|
111
|
+
return Object.assign(tag, {
|
|
112
|
+
[TypeId$4]: TypeId$4,
|
|
113
|
+
binding: definition.binding,
|
|
114
|
+
send,
|
|
115
|
+
sendBatch,
|
|
116
|
+
metrics
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
//#endregion
|
|
120
|
+
//#region src/QueueDefinition.ts
|
|
121
|
+
var QueueDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
122
|
+
Queue: () => Queue$1,
|
|
123
|
+
Tag: () => Tag$7,
|
|
124
|
+
implement: () => implement$7,
|
|
125
|
+
make: () => make$9
|
|
126
|
+
});
|
|
127
|
+
const makeDefinition$3 = (id, definition) => {
|
|
128
|
+
const queueDefinition = {
|
|
129
|
+
id,
|
|
130
|
+
message: definition.message
|
|
131
|
+
};
|
|
132
|
+
return Object.assign(queueDefinition, {
|
|
133
|
+
make: (layer, options) => make$6(layer, {
|
|
134
|
+
...options,
|
|
135
|
+
queue: wrapHandler$1(queueDefinition, options.queue)
|
|
136
|
+
}),
|
|
137
|
+
Binding: () => (bindingId, binding) => Service$4()(bindingId, {
|
|
138
|
+
...binding,
|
|
139
|
+
message: definition.message
|
|
140
|
+
}),
|
|
141
|
+
binding: (bindingId, binding) => Service$4()(bindingId, {
|
|
142
|
+
...binding,
|
|
143
|
+
message: definition.message
|
|
144
|
+
})
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
const make$9 = makeDefinition$3;
|
|
148
|
+
const Tag$7 = () => (id, definition) => {
|
|
149
|
+
const queueDefinition = makeDefinition$3(id, definition);
|
|
150
|
+
class QueueDefinitionClass {
|
|
151
|
+
static id = queueDefinition.id;
|
|
152
|
+
static message = queueDefinition.message;
|
|
153
|
+
static make = queueDefinition.make;
|
|
154
|
+
static Binding = queueDefinition.Binding;
|
|
155
|
+
static binding = queueDefinition.binding;
|
|
156
|
+
}
|
|
157
|
+
return QueueDefinitionClass;
|
|
158
|
+
};
|
|
159
|
+
const Queue$1 = Tag$7;
|
|
160
|
+
const wrapHandler$1 = (definition, handler) => {
|
|
161
|
+
const decodeBody = Schema.decodeUnknownEffect(definition.message);
|
|
162
|
+
return (batch) => Effect.gen(function* () {
|
|
163
|
+
yield* handler(yield* decodeBatch(batch.raw, decodeBody));
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
const implement$7 = (_definition, handler) => handler;
|
|
167
|
+
//#endregion
|
|
168
|
+
//#region src/Queue.ts
|
|
169
|
+
var Queue_exports = /* @__PURE__ */ __exportAll({
|
|
170
|
+
QueueMessageDecodeError: () => QueueMessageDecodeError,
|
|
171
|
+
Tag: () => Tag$6,
|
|
172
|
+
decodeBatch: () => decodeBatch,
|
|
173
|
+
fromMessage: () => fromMessage,
|
|
174
|
+
fromMessageBatch: () => fromMessageBatch,
|
|
175
|
+
implement: () => implement$6
|
|
176
|
+
});
|
|
177
|
+
var QueueMessageDecodeError = class extends Data.TaggedError("QueueMessageDecodeError") {};
|
|
178
|
+
const fromMessage = (message, body) => ({
|
|
179
|
+
raw: message,
|
|
180
|
+
id: message.id,
|
|
181
|
+
timestamp: message.timestamp,
|
|
182
|
+
body,
|
|
183
|
+
attempts: message.attempts,
|
|
184
|
+
ack: Effect.sync(() => message.ack()),
|
|
185
|
+
retry: (options) => Effect.sync(() => message.retry(options))
|
|
186
|
+
});
|
|
187
|
+
const fromMessageBatch = (batch, messages) => ({
|
|
188
|
+
raw: batch,
|
|
189
|
+
messages,
|
|
190
|
+
queue: batch.queue,
|
|
191
|
+
metadata: batch.metadata,
|
|
192
|
+
ackAll: Effect.sync(() => batch.ackAll()),
|
|
193
|
+
retryAll: (options) => Effect.sync(() => batch.retryAll(options))
|
|
194
|
+
});
|
|
195
|
+
const decodeBatch = (batch, decodeBody) => Effect.gen(function* () {
|
|
196
|
+
const messages = [];
|
|
197
|
+
for (let index = 0; index < batch.messages.length; index++) {
|
|
198
|
+
const message = batch.messages[index];
|
|
199
|
+
const body = yield* decodeBody(message.body).pipe(Effect.mapError((cause) => new QueueMessageDecodeError({
|
|
200
|
+
queue: batch.queue,
|
|
201
|
+
messageId: message.id,
|
|
202
|
+
index,
|
|
203
|
+
cause
|
|
204
|
+
})));
|
|
205
|
+
messages.push(fromMessage(message, body));
|
|
206
|
+
}
|
|
207
|
+
return fromMessageBatch(batch, messages);
|
|
208
|
+
});
|
|
209
|
+
const Tag$6 = Tag$7;
|
|
210
|
+
const implement$6 = implement$7;
|
|
211
|
+
//#endregion
|
|
63
212
|
//#region src/RpcDefinition.ts
|
|
64
213
|
var RpcDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
65
214
|
ReservedMethodNameError: () => ReservedMethodNameError,
|
|
@@ -75,7 +224,7 @@ var RpcDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
|
75
224
|
decodeSuccess: () => decodeSuccess,
|
|
76
225
|
encodeArgs: () => encodeArgs,
|
|
77
226
|
encodeSuccess: () => encodeSuccess,
|
|
78
|
-
make: () => make$
|
|
227
|
+
make: () => make$8,
|
|
79
228
|
method: () => method$4,
|
|
80
229
|
reservedMethodNames: () => reservedMethodNames$4
|
|
81
230
|
});
|
|
@@ -178,7 +327,7 @@ const decodeSuccess = (definition, methodName, value) => {
|
|
|
178
327
|
cause
|
|
179
328
|
})));
|
|
180
329
|
};
|
|
181
|
-
const make$
|
|
330
|
+
const make$8 = (id, methods) => {
|
|
182
331
|
const definition = {
|
|
183
332
|
id,
|
|
184
333
|
methods
|
|
@@ -232,11 +381,11 @@ const invokeRpcMethod = (target, method, args, makeError) => Effect.gen(function
|
|
|
232
381
|
//#endregion
|
|
233
382
|
//#region src/ServiceBinding.ts
|
|
234
383
|
var ServiceBinding_exports = /* @__PURE__ */ __exportAll({
|
|
235
|
-
Service: () => Service$
|
|
384
|
+
Service: () => Service$3,
|
|
236
385
|
ServiceBindingFetchError: () => ServiceBindingFetchError,
|
|
237
386
|
ServiceBindingRpcError: () => ServiceBindingRpcError
|
|
238
387
|
});
|
|
239
|
-
const TypeId$
|
|
388
|
+
const TypeId$3 = "effect-cf/ServiceBinding";
|
|
240
389
|
/**
|
|
241
390
|
* Failure raised when calling `fetch` on a service binding.
|
|
242
391
|
*/
|
|
@@ -271,8 +420,8 @@ var ServiceBindingRpcError = class extends Data.TaggedError("ServiceBindingRpcEr
|
|
|
271
420
|
* });
|
|
272
421
|
* ```
|
|
273
422
|
*/
|
|
274
|
-
const Service$
|
|
275
|
-
const tag = Service$
|
|
423
|
+
const Service$3 = () => (id, definition) => {
|
|
424
|
+
const tag = Service$5()(id, definition.binding, (value) => typeof value === "object" && value !== null && "fetch" in value);
|
|
276
425
|
const fetch = (input, init) => Effect.gen(function* () {
|
|
277
426
|
const service = yield* tag;
|
|
278
427
|
return yield* Effect.tryPromise({
|
|
@@ -315,7 +464,7 @@ const Service$2 = () => (id, definition) => {
|
|
|
315
464
|
});
|
|
316
465
|
const directMethods = makeDirectMethods$1(definition.definition, call);
|
|
317
466
|
return Object.assign(tag, directMethods, {
|
|
318
|
-
[TypeId$
|
|
467
|
+
[TypeId$3]: TypeId$3,
|
|
319
468
|
definition,
|
|
320
469
|
fetch,
|
|
321
470
|
rpc,
|
|
@@ -331,10 +480,10 @@ const makeDirectMethods$1 = (rpcDefinition, call) => {
|
|
|
331
480
|
//#endregion
|
|
332
481
|
//#region src/WorkerDefinition.ts
|
|
333
482
|
var WorkerDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
334
|
-
Tag: () => Tag$
|
|
483
|
+
Tag: () => Tag$5,
|
|
335
484
|
Worker: () => Worker,
|
|
336
|
-
implement: () => implement$
|
|
337
|
-
make: () => make$
|
|
485
|
+
implement: () => implement$5,
|
|
486
|
+
make: () => make$7,
|
|
338
487
|
method: () => method$3
|
|
339
488
|
});
|
|
340
489
|
const reservedMethodNames$3 = new Set([
|
|
@@ -342,6 +491,12 @@ const reservedMethodNames$3 = new Set([
|
|
|
342
491
|
"dup",
|
|
343
492
|
"fetch",
|
|
344
493
|
"connect",
|
|
494
|
+
"queue",
|
|
495
|
+
"scheduled",
|
|
496
|
+
"tail",
|
|
497
|
+
"tailStream",
|
|
498
|
+
"test",
|
|
499
|
+
"trace",
|
|
345
500
|
"alarm",
|
|
346
501
|
"webSocketMessage",
|
|
347
502
|
"webSocketClose",
|
|
@@ -364,27 +519,27 @@ const method$3 = method$4;
|
|
|
364
519
|
* });
|
|
365
520
|
* ```
|
|
366
521
|
*/
|
|
367
|
-
const makeDefinition$
|
|
522
|
+
const makeDefinition$2 = (id, methods) => {
|
|
368
523
|
assertNoReservedMethods("Worker", methods, reservedMethodNames$3);
|
|
369
|
-
const definition = make$
|
|
524
|
+
const definition = make$8(id, methods);
|
|
370
525
|
return Object.assign(definition, {
|
|
371
|
-
make: (layer, options) => make$
|
|
526
|
+
make: (layer, options) => make$6(layer, {
|
|
372
527
|
...options,
|
|
373
528
|
rpc: wrapHandlers$1(definition, options.rpc)
|
|
374
529
|
}),
|
|
375
|
-
Binding: () => (bindingId, binding) => Service$
|
|
530
|
+
Binding: () => (bindingId, binding) => Service$3()(bindingId, {
|
|
376
531
|
...binding,
|
|
377
532
|
definition
|
|
378
533
|
}),
|
|
379
|
-
binding: (bindingId, binding) => Service$
|
|
534
|
+
binding: (bindingId, binding) => Service$3()(bindingId, {
|
|
380
535
|
...binding,
|
|
381
536
|
definition
|
|
382
537
|
})
|
|
383
538
|
});
|
|
384
539
|
};
|
|
385
|
-
const make$
|
|
386
|
-
const Tag$
|
|
387
|
-
const definition = makeDefinition$
|
|
540
|
+
const make$7 = makeDefinition$2;
|
|
541
|
+
const Tag$5 = () => (id, methods) => {
|
|
542
|
+
const definition = makeDefinition$2(id, methods);
|
|
388
543
|
class WorkerDefinitionClass {
|
|
389
544
|
static id = definition.id;
|
|
390
545
|
static methods = definition.methods;
|
|
@@ -394,7 +549,7 @@ const Tag$3 = () => (id, methods) => {
|
|
|
394
549
|
}
|
|
395
550
|
return WorkerDefinitionClass;
|
|
396
551
|
};
|
|
397
|
-
const Worker = Tag$
|
|
552
|
+
const Worker = Tag$5;
|
|
398
553
|
const wrapHandlers$1 = (definition, handlers) => {
|
|
399
554
|
const wrapped = {};
|
|
400
555
|
for (const key of Object.keys(definition.methods)) {
|
|
@@ -408,7 +563,7 @@ const wrapHandlers$1 = (definition, handlers) => {
|
|
|
408
563
|
/**
|
|
409
564
|
* Helper for implementing handlers with the exact method shape of a definition.
|
|
410
565
|
*/
|
|
411
|
-
const implement$
|
|
566
|
+
const implement$5 = (_definition, handlers) => handlers;
|
|
412
567
|
//#endregion
|
|
413
568
|
//#region src/internal/Entrypoint.ts
|
|
414
569
|
const provideEntrypointServices = (layer, services) => layer.pipe(Layer.provideMerge(services));
|
|
@@ -424,34 +579,43 @@ const defineEntrypointRpcMethods = (target, prototype, rpc, reservedMethodNames,
|
|
|
424
579
|
};
|
|
425
580
|
const assumeEntrypointClass = (entrypoint) => entrypoint;
|
|
426
581
|
//#endregion
|
|
582
|
+
//#region src/internal/WorkerContext.ts
|
|
583
|
+
const causeError = (cause) => new Error(Cause.pretty(cause));
|
|
584
|
+
const failureHandler = (cause, options) => (options?.onFailure?.(cause) ?? Effect.logError("WorkerContext.waitUntil failed", Cause.pretty(cause))).pipe(Effect.catchCause((handlerCause) => Effect.logError("WorkerContext.waitUntil failure handler failed", Cause.pretty(cause), Cause.pretty(handlerCause))));
|
|
585
|
+
const fromExecutionContext = (ctx, runPromiseExit) => {
|
|
586
|
+
const schedule = (effect, options, mode) => Effect.context().pipe(Effect.flatMap((context) => Effect.sync(() => {
|
|
587
|
+
const runHandler = (cause) => runPromiseExit(Effect.scoped(Effect.provideContext(failureHandler(cause, options), context))).then((exit) => {
|
|
588
|
+
if (Exit.isFailure(exit)) console.error("WorkerContext.waitUntil failure handler failed", Cause.pretty(exit.cause));
|
|
589
|
+
});
|
|
590
|
+
ctx.waitUntil(runPromiseExit(Effect.scoped(Effect.provideContext(effect, context))).then(async (exit) => {
|
|
591
|
+
if (Exit.isSuccess(exit)) return;
|
|
592
|
+
await runHandler(exit.cause);
|
|
593
|
+
if (mode === "propagate") throw causeError(exit.cause);
|
|
594
|
+
}));
|
|
595
|
+
})));
|
|
596
|
+
return {
|
|
597
|
+
raw: ctx,
|
|
598
|
+
waitUntil: (effect, options) => schedule(effect, options, options?.mode ?? "observe"),
|
|
599
|
+
waitUntilPropagating: (effect, options) => schedule(effect, options, "propagate"),
|
|
600
|
+
passThroughOnException: Effect.sync(() => ctx.passThroughOnException())
|
|
601
|
+
};
|
|
602
|
+
};
|
|
603
|
+
//#endregion
|
|
427
604
|
//#region src/Worker.ts
|
|
428
605
|
var Worker_exports = /* @__PURE__ */ __exportAll({
|
|
429
606
|
ExecutionContext: () => ExecutionContext,
|
|
430
607
|
NativeRequest: () => NativeRequest,
|
|
431
|
-
Tag: () => Tag$
|
|
608
|
+
Tag: () => Tag$4,
|
|
432
609
|
WorkerContext: () => WorkerContext,
|
|
433
|
-
implement: () => implement$
|
|
610
|
+
implement: () => implement$4,
|
|
434
611
|
isWebSocketUpgrade: () => isWebSocketUpgrade,
|
|
435
|
-
make: () => make$
|
|
612
|
+
make: () => make$6,
|
|
436
613
|
makeFetchHandler: () => makeFetchHandler,
|
|
437
614
|
method: () => method$2,
|
|
438
615
|
renderHttpResponse: () => renderHttpResponse
|
|
439
616
|
});
|
|
440
617
|
var ExecutionContext = class extends Context.Service()("effect-cf/ExecutionContext") {};
|
|
441
618
|
var WorkerContext = class extends Context.Service()("effect-cf/WorkerContext") {};
|
|
442
|
-
const fromExecutionContext = (ctx, runPromiseExit) => ({
|
|
443
|
-
raw: ctx,
|
|
444
|
-
waitUntil: (effect, options) => Effect.context().pipe(Effect.flatMap((context) => Effect.sync(() => {
|
|
445
|
-
const observed = Effect.exit(effect).pipe(Effect.flatMap((exit) => {
|
|
446
|
-
if (Exit.isSuccess(exit)) return Effect.void;
|
|
447
|
-
return (options?.onFailure?.(exit.cause) ?? Effect.logError("WorkerContext.waitUntil failed", Cause.pretty(exit.cause))).pipe(Effect.catchCause((handlerCause) => Effect.logError("WorkerContext.waitUntil failure handler failed", Cause.pretty(exit.cause), Cause.pretty(handlerCause))));
|
|
448
|
-
}));
|
|
449
|
-
ctx.waitUntil(runPromiseExit(Effect.scoped(Effect.provideContext(observed, context))).then((exit) => {
|
|
450
|
-
if (Exit.isFailure(exit)) console.error("WorkerContext.waitUntil failure handler failed", Cause.pretty(exit.cause));
|
|
451
|
-
}));
|
|
452
|
-
}))),
|
|
453
|
-
passThroughOnException: Effect.sync(() => ctx.passThroughOnException())
|
|
454
|
-
});
|
|
455
619
|
var NativeRequest = class extends Context.Service()("effect-cf/NativeRequest") {};
|
|
456
620
|
const isWebSocketUpgrade = (request) => request.headers.get("Upgrade")?.toLowerCase() === "websocket";
|
|
457
621
|
const reservedMethodNames$2 = new Set([
|
|
@@ -459,6 +623,12 @@ const reservedMethodNames$2 = new Set([
|
|
|
459
623
|
"dup",
|
|
460
624
|
"fetch",
|
|
461
625
|
"connect",
|
|
626
|
+
"queue",
|
|
627
|
+
"scheduled",
|
|
628
|
+
"tail",
|
|
629
|
+
"tailStream",
|
|
630
|
+
"test",
|
|
631
|
+
"trace",
|
|
462
632
|
"alarm",
|
|
463
633
|
"webSocketMessage",
|
|
464
634
|
"webSocketClose",
|
|
@@ -467,12 +637,14 @@ const reservedMethodNames$2 = new Set([
|
|
|
467
637
|
const RunSymbol$1 = Symbol.for("effect-cf/Worker/run");
|
|
468
638
|
const renderHttpResponse = (effect) => Effect.flatMap(effect, (response) => Effect.map(Effect.context(), (context) => HttpServerResponse.toWeb(response, { context })));
|
|
469
639
|
const renderFetchSuccess = (effect) => Effect.flatMap(effect, (response) => response instanceof Response ? Effect.succeed(response) : Effect.map(Effect.context(), (context) => HttpServerResponse.toWeb(response, { context })));
|
|
470
|
-
const
|
|
640
|
+
const isWorkerOptions = (options) => typeof options === "object" && options !== null && ("fetch" in options || "queue" in options || "rpc" in options);
|
|
641
|
+
function make$6(layer, optionsOrFetch) {
|
|
642
|
+
const options = isWorkerOptions(optionsOrFetch) ? optionsOrFetch : { fetch: optionsOrFetch };
|
|
471
643
|
class EffectWorker extends WorkerEntrypoint {
|
|
472
644
|
runtime;
|
|
473
645
|
constructor(ctx, env) {
|
|
474
646
|
super(ctx, env);
|
|
475
|
-
let runWaitUntilEffect = () => Promise.
|
|
647
|
+
let runWaitUntilEffect = () => Promise.reject(/* @__PURE__ */ new Error("WorkerContext runtime is not initialized"));
|
|
476
648
|
const runtimeLayer = provideEntrypointServices(layer, Layer.mergeAll(Layer.succeed(ExecutionContext, ctx), ConfigProvider.layer(Effect.succeed(WorkerConfig.providerFromEnv(env))), Layer.succeed(WorkerContext, fromExecutionContext(ctx, (effect) => runWaitUntilEffect(effect))), Layer.succeed(WorkerEnvironment, env)));
|
|
477
649
|
this.runtime = ManagedRuntime.make(runtimeLayer);
|
|
478
650
|
runWaitUntilEffect = (effect) => this.runtime.runPromiseExit(effect);
|
|
@@ -486,17 +658,23 @@ const make$3 = (layer, options) => {
|
|
|
486
658
|
const requestServices = Layer.mergeAll(Layer.succeed(NativeRequest, request), Layer.succeed(HttpServerRequest.HttpServerRequest, HttpServerRequest.fromWeb(request)));
|
|
487
659
|
return this[RunSymbol$1](renderFetchSuccess(fetchHandler).pipe(Effect.provide(requestServices)));
|
|
488
660
|
}
|
|
661
|
+
queue(batch) {
|
|
662
|
+
const queueHandler = options.queue;
|
|
663
|
+
if (queueHandler === void 0) return Promise.resolve();
|
|
664
|
+
const messages = batch.messages.map((message) => fromMessage(message, message.body));
|
|
665
|
+
return this[RunSymbol$1](queueHandler(fromMessageBatch(batch, messages)));
|
|
666
|
+
}
|
|
489
667
|
}
|
|
490
668
|
defineEntrypointRpcMethods("Worker", EffectWorker.prototype, options.rpc, reservedMethodNames$2, (self, effect) => self[RunSymbol$1](effect));
|
|
491
669
|
return assumeEntrypointClass(EffectWorker);
|
|
492
|
-
}
|
|
670
|
+
}
|
|
493
671
|
const makeFetchHandler = (layer, options) => {
|
|
494
|
-
const WorkerClass = make$
|
|
672
|
+
const WorkerClass = make$6(layer, options);
|
|
495
673
|
return { fetch: (request, env, ctx) => Promise.resolve(new WorkerClass(ctx, env).fetch(request)) };
|
|
496
674
|
};
|
|
497
|
-
const Tag$
|
|
675
|
+
const Tag$4 = Tag$5;
|
|
498
676
|
const method$2 = method$3;
|
|
499
|
-
const implement$
|
|
677
|
+
const implement$4 = implement$5;
|
|
500
678
|
//#endregion
|
|
501
679
|
//#region src/DurableObjectStorage.ts
|
|
502
680
|
var DurableObjectStorage_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -620,6 +798,138 @@ const fromDurableObjectStorage = (storage) => ({
|
|
|
620
798
|
kv: fromSyncKvStorage(storage.kv)
|
|
621
799
|
});
|
|
622
800
|
//#endregion
|
|
801
|
+
//#region src/DurableObjectWebSocket.ts
|
|
802
|
+
var DurableObjectWebSocket_exports = /* @__PURE__ */ __exportAll({
|
|
803
|
+
DurableWebSocketAttachmentError: () => DurableWebSocketAttachmentError,
|
|
804
|
+
DurableWebSocketCloseError: () => DurableWebSocketCloseError,
|
|
805
|
+
DurableWebSocketSendError: () => DurableWebSocketSendError,
|
|
806
|
+
acceptUpgrade: () => acceptUpgrade,
|
|
807
|
+
attachment: () => attachment,
|
|
808
|
+
fromWebSocket: () => fromWebSocket,
|
|
809
|
+
handlers: () => handlers
|
|
810
|
+
});
|
|
811
|
+
/** Error raised when sending on a Durable Object websocket fails. */
|
|
812
|
+
var DurableWebSocketSendError = class extends Data.TaggedError("DurableWebSocketSendError") {};
|
|
813
|
+
/** Error raised when closing a Durable Object websocket fails. */
|
|
814
|
+
var DurableWebSocketCloseError = class extends Data.TaggedError("DurableWebSocketCloseError") {};
|
|
815
|
+
/** Error raised when serializing or deserializing a websocket attachment fails. */
|
|
816
|
+
var DurableWebSocketAttachmentError = class extends Data.TaggedError("DurableWebSocketAttachmentError") {};
|
|
817
|
+
const wrappers = /* @__PURE__ */ new WeakMap();
|
|
818
|
+
/** Wraps a native Cloudflare websocket in the Effect-native Durable Object API. */
|
|
819
|
+
const fromWebSocket = (raw) => {
|
|
820
|
+
const existing = wrappers.get(raw);
|
|
821
|
+
if (existing !== void 0) return existing;
|
|
822
|
+
const socket = {
|
|
823
|
+
raw,
|
|
824
|
+
send: (data) => Effect.try({
|
|
825
|
+
try: () => raw.send(data),
|
|
826
|
+
catch: (cause) => new DurableWebSocketSendError({ cause })
|
|
827
|
+
}),
|
|
828
|
+
close: (code, reason) => Effect.try({
|
|
829
|
+
try: () => raw.close(code, reason),
|
|
830
|
+
catch: (cause) => new DurableWebSocketCloseError({ cause })
|
|
831
|
+
}),
|
|
832
|
+
serializeAttachment: (value) => Effect.try({
|
|
833
|
+
try: () => raw.serializeAttachment(value),
|
|
834
|
+
catch: (cause) => new DurableWebSocketAttachmentError({
|
|
835
|
+
operation: "serialize",
|
|
836
|
+
cause
|
|
837
|
+
})
|
|
838
|
+
}),
|
|
839
|
+
deserializeAttachment: Effect.try({
|
|
840
|
+
try: () => raw.deserializeAttachment(),
|
|
841
|
+
catch: (cause) => new DurableWebSocketAttachmentError({
|
|
842
|
+
operation: "deserialize",
|
|
843
|
+
cause
|
|
844
|
+
})
|
|
845
|
+
})
|
|
846
|
+
};
|
|
847
|
+
wrappers.set(raw, socket);
|
|
848
|
+
return socket;
|
|
849
|
+
};
|
|
850
|
+
/**
|
|
851
|
+
* Accepts a websocket upgrade and registers the server socket on `DurableObjectState`.
|
|
852
|
+
*
|
|
853
|
+
* @example
|
|
854
|
+
* ```ts
|
|
855
|
+
* const response = yield* DurableObjectWebSocket.acceptUpgrade({
|
|
856
|
+
* tags: ["room:general"],
|
|
857
|
+
* });
|
|
858
|
+
*
|
|
859
|
+
* return response.response;
|
|
860
|
+
* ```
|
|
861
|
+
*/
|
|
862
|
+
const acceptUpgrade = (options = {}) => Effect.gen(function* () {
|
|
863
|
+
const state = yield* DurableObjectState;
|
|
864
|
+
const pair = new WebSocketPair();
|
|
865
|
+
const client = pair[0];
|
|
866
|
+
const server = fromWebSocket(pair[1]);
|
|
867
|
+
if (options.attachment !== void 0) server.raw.serializeAttachment(options.attachment);
|
|
868
|
+
yield* state.acceptWebSocket(server, options.tags === void 0 ? void 0 : [...options.tags]);
|
|
869
|
+
return {
|
|
870
|
+
client,
|
|
871
|
+
server,
|
|
872
|
+
response: new Response(null, {
|
|
873
|
+
status: 101,
|
|
874
|
+
webSocket: client
|
|
875
|
+
})
|
|
876
|
+
};
|
|
877
|
+
});
|
|
878
|
+
/** Creates typed attachment helpers for accepted and rehydrated sockets. */
|
|
879
|
+
const attachment = (schema) => {
|
|
880
|
+
const serialize = (socket, value) => Schema.encodeEffect(schema)(value).pipe(Effect.mapError((cause) => new DurableWebSocketAttachmentError({
|
|
881
|
+
operation: "serialize",
|
|
882
|
+
cause
|
|
883
|
+
})), Effect.flatMap((encoded) => socket.serializeAttachment(encoded)));
|
|
884
|
+
const deserialize = (socket) => Effect.gen(function* () {
|
|
885
|
+
const value = yield* socket.deserializeAttachment;
|
|
886
|
+
if (value == null) return Option.none();
|
|
887
|
+
return Option.some(yield* Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError((cause) => new DurableWebSocketAttachmentError({
|
|
888
|
+
operation: "deserialize",
|
|
889
|
+
cause
|
|
890
|
+
}))));
|
|
891
|
+
});
|
|
892
|
+
const rehydrate = (options = {}) => Effect.gen(function* () {
|
|
893
|
+
const sockets = yield* (yield* DurableObjectState).getWebSockets(options.tag);
|
|
894
|
+
const restored = [];
|
|
895
|
+
const onInvalid = options.onInvalid ?? "ignore";
|
|
896
|
+
for (const socket of sockets) {
|
|
897
|
+
const decoded = yield* deserialize(socket).pipe(Effect.match({
|
|
898
|
+
onFailure: (error) => ({
|
|
899
|
+
_tag: "Failure",
|
|
900
|
+
error
|
|
901
|
+
}),
|
|
902
|
+
onSuccess: (value) => ({
|
|
903
|
+
_tag: "Success",
|
|
904
|
+
value
|
|
905
|
+
})
|
|
906
|
+
}));
|
|
907
|
+
if (decoded._tag === "Success" && Option.isSome(decoded.value)) {
|
|
908
|
+
restored.push({
|
|
909
|
+
socket,
|
|
910
|
+
attachment: decoded.value.value
|
|
911
|
+
});
|
|
912
|
+
continue;
|
|
913
|
+
}
|
|
914
|
+
if (decoded._tag === "Failure" && onInvalid === "fail") return yield* Effect.fail(decoded.error);
|
|
915
|
+
if (decoded._tag === "Failure" && onInvalid === "ignore-and-close") yield* socket.close(1008, "invalid websocket attachment").pipe(Effect.ignore);
|
|
916
|
+
}
|
|
917
|
+
return restored;
|
|
918
|
+
});
|
|
919
|
+
return {
|
|
920
|
+
serialize,
|
|
921
|
+
deserialize,
|
|
922
|
+
rehydrate,
|
|
923
|
+
schema
|
|
924
|
+
};
|
|
925
|
+
};
|
|
926
|
+
/** Adapts wrapped websocket lifecycle handlers to `DurableObject.make` raw callbacks. */
|
|
927
|
+
const handlers = (options) => ({
|
|
928
|
+
webSocketMessage: options.message === void 0 ? void 0 : (socket, message) => options.message?.(fromWebSocket(socket), message) ?? Effect.void,
|
|
929
|
+
webSocketClose: options.close === void 0 ? void 0 : (socket, code, reason, wasClean) => options.close?.(fromWebSocket(socket), code, reason, wasClean) ?? Effect.void,
|
|
930
|
+
webSocketError: options.error === void 0 ? void 0 : (socket, error) => options.error?.(fromWebSocket(socket), error) ?? Effect.void
|
|
931
|
+
});
|
|
932
|
+
//#endregion
|
|
623
933
|
//#region src/DurableObjectState.ts
|
|
624
934
|
var DurableObjectState_exports = /* @__PURE__ */ __exportAll({
|
|
625
935
|
DurableObjectState: () => DurableObjectState,
|
|
@@ -639,14 +949,14 @@ const fromDurableObjectState = (state) => ({
|
|
|
639
949
|
waitUntil: (promise) => Effect.sync(() => state.waitUntil(promise)),
|
|
640
950
|
blockConcurrencyWhile: (effect) => Effect.context().pipe(Effect.flatMap((context) => Effect.promise(() => state.blockConcurrencyWhile(() => runPromiseExitPreservingTypedFailures(Effect.provideContext(effect, context))))), Effect.flatten),
|
|
641
951
|
blockConcurrencyWhileOrReset: (effect) => Effect.context().pipe(Effect.flatMap((context) => Effect.promise(() => state.blockConcurrencyWhile(() => Effect.runPromise(Effect.provideContext(effect, context)))))),
|
|
642
|
-
acceptWebSocket: (ws, tags) => Effect.sync(() => state.acceptWebSocket(ws, tags)),
|
|
643
|
-
getWebSockets: (tag) => Effect.sync(() => state.getWebSockets(tag)),
|
|
952
|
+
acceptWebSocket: (ws, tags) => Effect.sync(() => state.acceptWebSocket(ws.raw, tags)),
|
|
953
|
+
getWebSockets: (tag) => Effect.sync(() => state.getWebSockets(tag).map((socket) => fromWebSocket(socket))),
|
|
644
954
|
setWebSocketAutoResponse: (pair) => Effect.sync(() => state.setWebSocketAutoResponse(pair)),
|
|
645
955
|
getWebSocketAutoResponse: Effect.sync(() => state.getWebSocketAutoResponse()),
|
|
646
|
-
getWebSocketAutoResponseTimestamp: (ws) => Effect.sync(() => state.getWebSocketAutoResponseTimestamp(ws)),
|
|
956
|
+
getWebSocketAutoResponseTimestamp: (ws) => Effect.sync(() => state.getWebSocketAutoResponseTimestamp(ws.raw)),
|
|
647
957
|
setHibernatableWebSocketEventTimeout: (timeoutMs) => Effect.sync(() => state.setHibernatableWebSocketEventTimeout(timeoutMs)),
|
|
648
958
|
getHibernatableWebSocketEventTimeout: Effect.sync(() => state.getHibernatableWebSocketEventTimeout()),
|
|
649
|
-
getTags: (ws) => Effect.sync(() => state.getTags(ws)),
|
|
959
|
+
getTags: (ws) => Effect.sync(() => state.getTags(ws.raw)),
|
|
650
960
|
abort: (reason) => Effect.sync(() => state.abort(reason))
|
|
651
961
|
});
|
|
652
962
|
const runPromiseExitPreservingTypedFailures = async (effect) => {
|
|
@@ -659,9 +969,9 @@ const runPromiseExitPreservingTypedFailures = async (effect) => {
|
|
|
659
969
|
var DurableObjectNamespace_exports = /* @__PURE__ */ __exportAll({
|
|
660
970
|
DurableObjectFetchError: () => DurableObjectFetchError,
|
|
661
971
|
DurableObjectRpcError: () => DurableObjectRpcError,
|
|
662
|
-
Service: () => Service$
|
|
972
|
+
Service: () => Service$2
|
|
663
973
|
});
|
|
664
|
-
const TypeId$
|
|
974
|
+
const TypeId$2 = "effect-cf/DurableObjectNamespace";
|
|
665
975
|
/**
|
|
666
976
|
* Failure raised when invoking an RPC method on a Durable Object stub.
|
|
667
977
|
*/
|
|
@@ -693,10 +1003,10 @@ var DurableObjectFetchError = class extends Data.TaggedError("DurableObjectFetch
|
|
|
693
1003
|
* });
|
|
694
1004
|
* ```
|
|
695
1005
|
*/
|
|
696
|
-
const Service$
|
|
1006
|
+
const Service$2 = () => (id, definition) => {
|
|
697
1007
|
const hasFunction = (value, key) => typeof Reflect.get(value, key) === "function";
|
|
698
1008
|
const isDurableObjectNamespaceClient = (value) => typeof value === "object" && value !== null && hasFunction(value, "getByName") && hasFunction(value, "get") && hasFunction(value, "idFromName") && hasFunction(value, "idFromString") && hasFunction(value, "newUniqueId") && hasFunction(value, "jurisdiction");
|
|
699
|
-
const tag = Service$
|
|
1009
|
+
const tag = Service$5()(id, definition.binding, (value) => isDurableObjectNamespaceClient(value));
|
|
700
1010
|
const newUniqueId = Effect.fnUntraced(function* (options) {
|
|
701
1011
|
return (yield* tag).newUniqueId(options);
|
|
702
1012
|
});
|
|
@@ -758,7 +1068,7 @@ const Service$1 = () => (id, definition) => {
|
|
|
758
1068
|
getByName
|
|
759
1069
|
});
|
|
760
1070
|
return Object.assign(tag, directMethods, {
|
|
761
|
-
[TypeId$
|
|
1071
|
+
[TypeId$2]: TypeId$2,
|
|
762
1072
|
definition,
|
|
763
1073
|
newUniqueId,
|
|
764
1074
|
idFromName,
|
|
@@ -796,9 +1106,9 @@ const makeDirectMethods = (rpcDefinition, helpers) => {
|
|
|
796
1106
|
//#region src/DurableObjectDefinition.ts
|
|
797
1107
|
var DurableObjectDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
798
1108
|
DurableObject: () => DurableObject$1,
|
|
799
|
-
Tag: () => Tag$
|
|
800
|
-
implement: () => implement$
|
|
801
|
-
make: () => make$
|
|
1109
|
+
Tag: () => Tag$3,
|
|
1110
|
+
implement: () => implement$3,
|
|
1111
|
+
make: () => make$5,
|
|
802
1112
|
method: () => method$1
|
|
803
1113
|
});
|
|
804
1114
|
const reservedMethodNames$1 = new Set([
|
|
@@ -827,27 +1137,27 @@ const method$1 = method$4;
|
|
|
827
1137
|
* });
|
|
828
1138
|
* ```
|
|
829
1139
|
*/
|
|
830
|
-
const makeDefinition = (id, methods) => {
|
|
1140
|
+
const makeDefinition$1 = (id, methods) => {
|
|
831
1141
|
assertNoReservedMethods("Durable Object", methods, reservedMethodNames$1);
|
|
832
|
-
const definition = make$
|
|
1142
|
+
const definition = make$8(id, methods);
|
|
833
1143
|
return Object.assign(definition, {
|
|
834
|
-
make: (layer, options) => make$
|
|
1144
|
+
make: (layer, options) => make$4(layer, {
|
|
835
1145
|
...options,
|
|
836
1146
|
rpc: wrapHandlers(definition, options.rpc)
|
|
837
1147
|
}),
|
|
838
|
-
Namespace: () => (bindingId, binding) => Service$
|
|
1148
|
+
Namespace: () => (bindingId, binding) => Service$2()(bindingId, {
|
|
839
1149
|
...binding,
|
|
840
1150
|
definition
|
|
841
1151
|
}),
|
|
842
|
-
namespace: (bindingId, binding) => Service$
|
|
1152
|
+
namespace: (bindingId, binding) => Service$2()(bindingId, {
|
|
843
1153
|
...binding,
|
|
844
1154
|
definition
|
|
845
1155
|
})
|
|
846
1156
|
});
|
|
847
1157
|
};
|
|
848
|
-
const make$
|
|
849
|
-
const Tag$
|
|
850
|
-
const definition = makeDefinition(id, methods);
|
|
1158
|
+
const make$5 = makeDefinition$1;
|
|
1159
|
+
const Tag$3 = () => (id, methods) => {
|
|
1160
|
+
const definition = makeDefinition$1(id, methods);
|
|
851
1161
|
class DurableObjectDefinitionClass {
|
|
852
1162
|
static id = definition.id;
|
|
853
1163
|
static methods = definition.methods;
|
|
@@ -857,7 +1167,7 @@ const Tag$1 = () => (id, methods) => {
|
|
|
857
1167
|
}
|
|
858
1168
|
return DurableObjectDefinitionClass;
|
|
859
1169
|
};
|
|
860
|
-
const DurableObject$1 = Tag$
|
|
1170
|
+
const DurableObject$1 = Tag$3;
|
|
861
1171
|
const wrapHandlers = (definition, handlers) => {
|
|
862
1172
|
const wrapped = {};
|
|
863
1173
|
for (const key of Object.keys(definition.methods)) {
|
|
@@ -871,13 +1181,13 @@ const wrapHandlers = (definition, handlers) => {
|
|
|
871
1181
|
/**
|
|
872
1182
|
* Helper for implementing handlers with the exact method shape of a definition.
|
|
873
1183
|
*/
|
|
874
|
-
const implement$
|
|
1184
|
+
const implement$3 = (_definition, handlers) => handlers;
|
|
875
1185
|
//#endregion
|
|
876
1186
|
//#region src/DurableObject.ts
|
|
877
1187
|
var DurableObject_exports = /* @__PURE__ */ __exportAll({
|
|
878
|
-
Tag: () => Tag,
|
|
879
|
-
implement: () => implement,
|
|
880
|
-
make: () => make$
|
|
1188
|
+
Tag: () => Tag$2,
|
|
1189
|
+
implement: () => implement$2,
|
|
1190
|
+
make: () => make$4,
|
|
881
1191
|
method: () => method
|
|
882
1192
|
});
|
|
883
1193
|
const reservedMethodNames = new Set([
|
|
@@ -893,7 +1203,7 @@ const RunSymbol = Symbol.for("effect-cf/DurableObject/run");
|
|
|
893
1203
|
/**
|
|
894
1204
|
* Creates a Durable Object class backed by a single managed Effect runtime.
|
|
895
1205
|
*/
|
|
896
|
-
const make$
|
|
1206
|
+
const make$4 = (layer, options = {}) => {
|
|
897
1207
|
class EffectDurableObject extends DurableObject {
|
|
898
1208
|
runtime;
|
|
899
1209
|
constructor(state, env) {
|
|
@@ -910,7 +1220,14 @@ const make$1 = (layer, options = {}) => {
|
|
|
910
1220
|
return this[RunSymbol](Effect.provideService(fetchHandler, NativeRequest, request));
|
|
911
1221
|
}
|
|
912
1222
|
alarm(alarmInfo) {
|
|
913
|
-
|
|
1223
|
+
const logicalAlarms = options.alarms?.pipe(Effect.asVoid);
|
|
1224
|
+
const rawAlarm = options.alarm?.(alarmInfo);
|
|
1225
|
+
if (logicalAlarms !== void 0 && rawAlarm !== void 0) return this[RunSymbol](Effect.gen(function* () {
|
|
1226
|
+
yield* logicalAlarms;
|
|
1227
|
+
yield* rawAlarm;
|
|
1228
|
+
}));
|
|
1229
|
+
if (logicalAlarms !== void 0) return this[RunSymbol](logicalAlarms);
|
|
1230
|
+
if (rawAlarm !== void 0) return this[RunSymbol](rawAlarm);
|
|
914
1231
|
}
|
|
915
1232
|
webSocketMessage(socket, message) {
|
|
916
1233
|
if (options.webSocketMessage !== void 0) return this[RunSymbol](options.webSocketMessage(socket, message));
|
|
@@ -925,9 +1242,331 @@ const make$1 = (layer, options = {}) => {
|
|
|
925
1242
|
defineEntrypointRpcMethods("Durable Object", EffectDurableObject.prototype, options.rpc, reservedMethodNames, (self, effect) => self[RunSymbol](effect));
|
|
926
1243
|
return assumeEntrypointClass(EffectDurableObject);
|
|
927
1244
|
};
|
|
928
|
-
const Tag = Tag$
|
|
1245
|
+
const Tag$2 = Tag$3;
|
|
929
1246
|
const method = method$1;
|
|
930
|
-
const implement = implement$
|
|
1247
|
+
const implement$2 = implement$3;
|
|
1248
|
+
//#endregion
|
|
1249
|
+
//#region src/DurableObjectAlarm.ts
|
|
1250
|
+
var DurableObjectAlarm_exports = /* @__PURE__ */ __exportAll({
|
|
1251
|
+
DurableObjectAlarm: () => DurableObjectAlarm,
|
|
1252
|
+
DurableObjectAlarmEvent: () => DurableObjectAlarmEvent,
|
|
1253
|
+
InvalidAlarmPayloadError: () => InvalidAlarmPayloadError,
|
|
1254
|
+
InvalidAlarmRefError: () => InvalidAlarmRefError,
|
|
1255
|
+
InvalidProcessDueAlarmsOptionsError: () => InvalidProcessDueAlarmsOptionsError,
|
|
1256
|
+
InvalidRepeatEveryError: () => InvalidRepeatEveryError,
|
|
1257
|
+
StoredAlarmDecodeError: () => StoredAlarmDecodeError,
|
|
1258
|
+
define: () => define,
|
|
1259
|
+
process: () => process,
|
|
1260
|
+
processDue: () => processDue
|
|
1261
|
+
});
|
|
1262
|
+
const INIT_TABLE_SQL = `
|
|
1263
|
+
CREATE TABLE IF NOT EXISTS effect_cf_scheduled_alarms (
|
|
1264
|
+
storage_id TEXT PRIMARY KEY,
|
|
1265
|
+
alarm_id TEXT NOT NULL,
|
|
1266
|
+
tag TEXT NOT NULL,
|
|
1267
|
+
run_at INTEGER NOT NULL,
|
|
1268
|
+
repeat_every_ms INTEGER,
|
|
1269
|
+
payload TEXT NOT NULL
|
|
1270
|
+
);
|
|
1271
|
+
CREATE INDEX IF NOT EXISTS idx_effect_cf_scheduled_alarms_run_at_storage_id
|
|
1272
|
+
ON effect_cf_scheduled_alarms (run_at, storage_id);
|
|
1273
|
+
`;
|
|
1274
|
+
const DEFAULT_PROCESS_DUE_ALARMS_LIMIT = 100;
|
|
1275
|
+
const DEFAULT_PROCESS_DUE_ALARMS_FAILURE_RESCHEDULE_AFTER = "30 seconds";
|
|
1276
|
+
const getScheduledEventId = (input) => `effect-cf-alarm:${encodeURIComponent(input.tag)}:${encodeURIComponent(input.id)}`;
|
|
1277
|
+
var InvalidAlarmRefError = class extends Data.TaggedError("InvalidAlarmRefError") {};
|
|
1278
|
+
var InvalidAlarmPayloadError = class extends Data.TaggedError("InvalidAlarmPayloadError") {};
|
|
1279
|
+
var InvalidRepeatEveryError = class extends Data.TaggedError("InvalidRepeatEveryError") {};
|
|
1280
|
+
var InvalidProcessDueAlarmsOptionsError = class extends Data.TaggedError("InvalidProcessDueAlarmsOptionsError") {};
|
|
1281
|
+
var StoredAlarmDecodeError = class extends Data.TaggedError("StoredAlarmDecodeError") {};
|
|
1282
|
+
/**
|
|
1283
|
+
* Events handled by `processDueAlarms`.
|
|
1284
|
+
*
|
|
1285
|
+
* `AlarmDue` represents one durable alarm whose scheduled time is now due. The
|
|
1286
|
+
* `tag` is the consumer-owned routing key, while `id` is the stable alarm id
|
|
1287
|
+
* within that tag.
|
|
1288
|
+
*
|
|
1289
|
+
* `scheduledAt` is the logical due-after timestamp from durable storage. It is
|
|
1290
|
+
* not expected to match the current Durable Object alarm invocation time,
|
|
1291
|
+
* especially during retries. Retries re-scan durable rows with `run_at <= now`
|
|
1292
|
+
* and identify logical events by `{ tag, id }`.
|
|
1293
|
+
*
|
|
1294
|
+
* @example Handling events by tag
|
|
1295
|
+
* ```ts
|
|
1296
|
+
* yield* durableObjectAlarm.processDueAlarms((event) =>
|
|
1297
|
+
* event.tag === "heartbeat"
|
|
1298
|
+
* ? heartbeatManager.handleAlarmEvent(event).pipe(Effect.asVoid)
|
|
1299
|
+
* : Effect.void
|
|
1300
|
+
* );
|
|
1301
|
+
* ```
|
|
1302
|
+
*/
|
|
1303
|
+
const DurableObjectAlarmEvent = Schema.TaggedUnion({ AlarmDue: {
|
|
1304
|
+
id: Schema.NonEmptyString,
|
|
1305
|
+
payload: Schema.Json,
|
|
1306
|
+
scheduledAt: Schema.DateTimeUtc,
|
|
1307
|
+
tag: Schema.NonEmptyString
|
|
1308
|
+
} });
|
|
1309
|
+
const AlarmRefSchema = Schema.Struct({
|
|
1310
|
+
id: Schema.NonEmptyString,
|
|
1311
|
+
tag: Schema.NonEmptyString
|
|
1312
|
+
});
|
|
1313
|
+
const decodeAlarmRef = (input) => Schema.decodeUnknownEffect(AlarmRefSchema)(input).pipe(Effect.mapError((cause) => new InvalidAlarmRefError({ cause })));
|
|
1314
|
+
const StoredPayloadString = Schema.fromJsonString(Schema.Json);
|
|
1315
|
+
const decodeStoredPayload = (row) => Schema.decodeUnknownEffect(StoredPayloadString)(row.payload).pipe(Effect.mapError((cause) => new StoredAlarmDecodeError({
|
|
1316
|
+
cause,
|
|
1317
|
+
storageId: row.storage_id
|
|
1318
|
+
})));
|
|
1319
|
+
const encodeStoredPayload = (payload) => Schema.encodeEffect(StoredPayloadString)(payload).pipe(Effect.mapError((cause) => new InvalidAlarmPayloadError({ cause })));
|
|
1320
|
+
const ensureTable = (state) => state.storage.sql.exec(INIT_TABLE_SQL).pipe(Effect.asVoid);
|
|
1321
|
+
const toRepeatEveryMillis = (input) => {
|
|
1322
|
+
if (input === void 0) return Effect.succeed(null);
|
|
1323
|
+
return Effect.try({
|
|
1324
|
+
try: () => {
|
|
1325
|
+
const millis = Duration.toMillis(Duration.fromInputUnsafe(input));
|
|
1326
|
+
if (!Number.isFinite(millis) || millis <= 0) throw new Error("Alarm repeatEvery must be a positive finite duration");
|
|
1327
|
+
return Math.ceil(millis);
|
|
1328
|
+
},
|
|
1329
|
+
catch: (cause) => new InvalidRepeatEveryError({ cause })
|
|
1330
|
+
});
|
|
1331
|
+
};
|
|
1332
|
+
const toAlarmDue = (row) => Effect.gen(function* () {
|
|
1333
|
+
if (!Number.isFinite(row.run_at)) return yield* Effect.fail(new StoredAlarmDecodeError({
|
|
1334
|
+
cause: /* @__PURE__ */ new Error("Stored alarm run_at must be a finite number"),
|
|
1335
|
+
storageId: row.storage_id
|
|
1336
|
+
}));
|
|
1337
|
+
return DurableObjectAlarmEvent.make({
|
|
1338
|
+
_tag: "AlarmDue",
|
|
1339
|
+
id: row.alarm_id,
|
|
1340
|
+
payload: yield* decodeStoredPayload(row),
|
|
1341
|
+
scheduledAt: DateTime.toUtc(DateTime.makeUnsafe(row.run_at)),
|
|
1342
|
+
tag: row.tag
|
|
1343
|
+
});
|
|
1344
|
+
});
|
|
1345
|
+
const getProcessLimit = (options) => {
|
|
1346
|
+
const limit = options?.limit ?? DEFAULT_PROCESS_DUE_ALARMS_LIMIT;
|
|
1347
|
+
if (!Number.isSafeInteger(limit) || limit <= 0) return Effect.fail(new InvalidProcessDueAlarmsOptionsError({ cause: /* @__PURE__ */ new Error("processDueAlarms limit must be a positive safe integer") }));
|
|
1348
|
+
return Effect.succeed(limit);
|
|
1349
|
+
};
|
|
1350
|
+
const toFailureRescheduleMillis = (input) => Effect.try({
|
|
1351
|
+
try: () => {
|
|
1352
|
+
const millis = Duration.toMillis(Duration.fromInputUnsafe(input));
|
|
1353
|
+
if (!Number.isFinite(millis) || millis <= 0) throw new Error("Alarm failure rescheduleAfter must be a positive finite duration");
|
|
1354
|
+
return Math.ceil(millis);
|
|
1355
|
+
},
|
|
1356
|
+
catch: (cause) => new InvalidProcessDueAlarmsOptionsError({ cause })
|
|
1357
|
+
});
|
|
1358
|
+
const getFailureRetryDelay = (options) => toFailureRescheduleMillis(options?.retryFailedAfter ?? DEFAULT_PROCESS_DUE_ALARMS_FAILURE_RESCHEDULE_AFTER);
|
|
1359
|
+
const getFailureActionMode = (action) => typeof action === "string" ? action : action.mode;
|
|
1360
|
+
const getFailureActionRetryDelay = (action) => typeof action === "string" || action.mode !== "retry" ? void 0 : action.retryFailedAfter;
|
|
1361
|
+
const processDue = (handle, options = {}) => Effect.gen(function* () {
|
|
1362
|
+
return yield* (yield* DurableObjectAlarm).processDueAlarms(handle, options);
|
|
1363
|
+
});
|
|
1364
|
+
const process = processDue;
|
|
1365
|
+
const isAlarmDefinitionConfig = (definition) => typeof definition === "object" && definition !== null && "payload" in definition;
|
|
1366
|
+
const getAlarmDefinitionSchema = (definition) => isAlarmDefinitionConfig(definition) ? definition.payload : definition;
|
|
1367
|
+
const getAlarmDefinitionFailureAction = (definition) => {
|
|
1368
|
+
if (definition === void 0 || !isAlarmDefinitionConfig(definition)) return;
|
|
1369
|
+
if (definition.failure === void 0) return;
|
|
1370
|
+
return definition.failure === "retry" ? {
|
|
1371
|
+
mode: "retry",
|
|
1372
|
+
retryFailedAfter: definition.retry?.initialDelay
|
|
1373
|
+
} : { mode: definition.failure };
|
|
1374
|
+
};
|
|
1375
|
+
const define = (definitions) => ({ handlers: (handlers, options) => processDue((event) => Effect.gen(function* () {
|
|
1376
|
+
const definition = definitions[event.tag];
|
|
1377
|
+
if (definition === void 0) return;
|
|
1378
|
+
const schema = getAlarmDefinitionSchema(definition);
|
|
1379
|
+
const payload = yield* Schema.decodeUnknownEffect(schema)(event.payload).pipe(Effect.mapError((cause) => new StoredAlarmDecodeError({
|
|
1380
|
+
cause,
|
|
1381
|
+
storageId: getScheduledEventId(event)
|
|
1382
|
+
})));
|
|
1383
|
+
const handler = handlers[event.tag];
|
|
1384
|
+
yield* handler({
|
|
1385
|
+
...event,
|
|
1386
|
+
payload
|
|
1387
|
+
});
|
|
1388
|
+
}), {
|
|
1389
|
+
...options,
|
|
1390
|
+
onFailure: (failure) => Effect.gen(function* () {
|
|
1391
|
+
const action = getAlarmDefinitionFailureAction(definitions[failure.tag]);
|
|
1392
|
+
const optionAction = options?.onFailure === void 0 ? void 0 : yield* options.onFailure(failure);
|
|
1393
|
+
return action ?? optionAction;
|
|
1394
|
+
})
|
|
1395
|
+
}) });
|
|
1396
|
+
/**
|
|
1397
|
+
* SQLite-backed Durable Object alarm scheduler.
|
|
1398
|
+
*
|
|
1399
|
+
* `DurableObjectAlarm` stores alarms in the current Durable Object's SQLite storage
|
|
1400
|
+
* and keeps the platform alarm set to the earliest pending scheduled alarm. The
|
|
1401
|
+
* platform alarm timestamp is only a wake-up hint; logical event identity comes
|
|
1402
|
+
* from persisted `{ tag, id }` rows.
|
|
1403
|
+
*
|
|
1404
|
+
* Retry safety depends on acknowledgement ordering. `processDueAlarms` runs the
|
|
1405
|
+
* caller's handler first and only then conditionally deletes or advances the
|
|
1406
|
+
* same selected row. By default, handler failures are isolated: the failed row
|
|
1407
|
+
* is retried after a delay, later due rows continue, and the platform alarm is
|
|
1408
|
+
* reconciled once at the end. Use `mode: "ordered"` for strict workflows where
|
|
1409
|
+
* one failed logical alarm should block later due alarms.
|
|
1410
|
+
*
|
|
1411
|
+
* Provide `DurableObjectAlarm.layer` anywhere `DurableObjectState` is available.
|
|
1412
|
+
*
|
|
1413
|
+
* @example Providing the service
|
|
1414
|
+
* ```ts
|
|
1415
|
+
* const program = Effect.gen(function* () {
|
|
1416
|
+
* const durableObjectAlarm = yield* DurableObjectAlarm;
|
|
1417
|
+
* const now = yield* DateTime.now;
|
|
1418
|
+
*
|
|
1419
|
+
* yield* durableObjectAlarm.scheduleAlarm({
|
|
1420
|
+
* tag: "heartbeat",
|
|
1421
|
+
* id: "heartbeat-check",
|
|
1422
|
+
* runAt: DateTime.add(now, { seconds: 5 }),
|
|
1423
|
+
* repeatEvery: Duration.seconds(5),
|
|
1424
|
+
* payload: null,
|
|
1425
|
+
* });
|
|
1426
|
+
* }).pipe(Effect.provide(DurableObjectAlarm.layer));
|
|
1427
|
+
* ```
|
|
1428
|
+
*
|
|
1429
|
+
* @example Processing due alarms
|
|
1430
|
+
* ```ts
|
|
1431
|
+
* const handledEvents = yield* durableObjectAlarm.processDueAlarms((event) =>
|
|
1432
|
+
* Effect.gen(function* () {
|
|
1433
|
+
* if (event.tag === "heartbeat") {
|
|
1434
|
+
* yield* heartbeatManager.handleAlarmEvent(event);
|
|
1435
|
+
* }
|
|
1436
|
+
* })
|
|
1437
|
+
* );
|
|
1438
|
+
* ```
|
|
1439
|
+
*/
|
|
1440
|
+
var DurableObjectAlarm = class DurableObjectAlarm extends Context.Service()("effect-cf/DurableObjectAlarm") {
|
|
1441
|
+
static layer = Layer.effect(DurableObjectAlarm, Effect.gen(function* () {
|
|
1442
|
+
const state = yield* DurableObjectState;
|
|
1443
|
+
const reconcileAlarm = Effect.fn("DurableObjectAlarm.reconcileAlarm")(function* () {
|
|
1444
|
+
const next = (yield* (yield* state.storage.sql.exec(`SELECT run_at FROM effect_cf_scheduled_alarms ORDER BY run_at ASC, storage_id ASC LIMIT 1`)).toArray())[0];
|
|
1445
|
+
if (next === void 0) {
|
|
1446
|
+
yield* state.storage.deleteAlarm();
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
yield* state.storage.setAlarm(next.run_at);
|
|
1450
|
+
});
|
|
1451
|
+
const rescheduleFailedAlarm = Effect.fn("DurableObjectAlarm.rescheduleFailedAlarm")(function* (row, retryDelayMillis) {
|
|
1452
|
+
const retryAt = (yield* Clock.currentTimeMillis) + retryDelayMillis;
|
|
1453
|
+
if (row.repeat_every_ms === null) {
|
|
1454
|
+
yield* (yield* state.storage.sql.exec(`UPDATE effect_cf_scheduled_alarms
|
|
1455
|
+
SET run_at = ?
|
|
1456
|
+
WHERE storage_id = ?
|
|
1457
|
+
AND run_at = ?
|
|
1458
|
+
AND repeat_every_ms IS NULL
|
|
1459
|
+
AND payload = ?`, retryAt, row.storage_id, row.run_at, row.payload)).rowsWritten;
|
|
1460
|
+
return;
|
|
1461
|
+
}
|
|
1462
|
+
yield* (yield* state.storage.sql.exec(`UPDATE effect_cf_scheduled_alarms
|
|
1463
|
+
SET run_at = ?
|
|
1464
|
+
WHERE storage_id = ?
|
|
1465
|
+
AND run_at = ?
|
|
1466
|
+
AND repeat_every_ms = ?
|
|
1467
|
+
AND payload = ?`, retryAt, row.storage_id, row.run_at, row.repeat_every_ms, row.payload)).rowsWritten;
|
|
1468
|
+
});
|
|
1469
|
+
const acknowledgeAlarm = Effect.fn("DurableObjectAlarm.acknowledgeAlarm")(function* (row) {
|
|
1470
|
+
if (row.repeat_every_ms === null) {
|
|
1471
|
+
yield* (yield* state.storage.sql.exec(`DELETE FROM effect_cf_scheduled_alarms
|
|
1472
|
+
WHERE storage_id = ?
|
|
1473
|
+
AND run_at = ?
|
|
1474
|
+
AND repeat_every_ms IS NULL
|
|
1475
|
+
AND payload = ?`, row.storage_id, row.run_at, row.payload)).rowsWritten;
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1478
|
+
const acknowledgedAt = yield* Clock.currentTimeMillis;
|
|
1479
|
+
yield* (yield* state.storage.sql.exec(`UPDATE effect_cf_scheduled_alarms
|
|
1480
|
+
SET run_at = ?
|
|
1481
|
+
WHERE storage_id = ?
|
|
1482
|
+
AND run_at = ?
|
|
1483
|
+
AND repeat_every_ms = ?
|
|
1484
|
+
AND payload = ?`, acknowledgedAt + row.repeat_every_ms, row.storage_id, row.run_at, row.repeat_every_ms, row.payload)).rowsWritten;
|
|
1485
|
+
});
|
|
1486
|
+
const cancelAlarm = Effect.fn("DurableObjectAlarm.cancelAlarm")(function* (input) {
|
|
1487
|
+
const ref = yield* decodeAlarmRef(input);
|
|
1488
|
+
yield* state.storage.transaction(() => Effect.gen(function* () {
|
|
1489
|
+
yield* ensureTable(state);
|
|
1490
|
+
yield* state.storage.sql.exec(`DELETE FROM effect_cf_scheduled_alarms WHERE storage_id = ?`, getScheduledEventId(ref)).pipe(Effect.asVoid);
|
|
1491
|
+
yield* reconcileAlarm();
|
|
1492
|
+
}));
|
|
1493
|
+
});
|
|
1494
|
+
const scheduleAlarm = Effect.fn("DurableObjectAlarm.scheduleAlarm")(function* (input) {
|
|
1495
|
+
const ref = yield* decodeAlarmRef(input);
|
|
1496
|
+
const repeatEveryMillis = yield* toRepeatEveryMillis(input.repeatEvery);
|
|
1497
|
+
const payload = yield* encodeStoredPayload(input.payload);
|
|
1498
|
+
const runAt = DateTime.toEpochMillis(input.runAt);
|
|
1499
|
+
yield* state.storage.transaction(() => Effect.gen(function* () {
|
|
1500
|
+
yield* ensureTable(state);
|
|
1501
|
+
yield* state.storage.sql.exec(`INSERT OR REPLACE INTO effect_cf_scheduled_alarms
|
|
1502
|
+
(storage_id, alarm_id, tag, run_at, repeat_every_ms, payload)
|
|
1503
|
+
VALUES (?, ?, ?, ?, ?, ?)`, getScheduledEventId(ref), ref.id, ref.tag, runAt, repeatEveryMillis, payload).pipe(Effect.asVoid);
|
|
1504
|
+
yield* reconcileAlarm();
|
|
1505
|
+
}));
|
|
1506
|
+
});
|
|
1507
|
+
const processDueAlarms = Effect.fn("DurableObjectAlarm.processDueAlarms")(function* (handle, options) {
|
|
1508
|
+
yield* ensureTable(state);
|
|
1509
|
+
const mode = options?.mode ?? "isolated";
|
|
1510
|
+
const limit = yield* getProcessLimit(options);
|
|
1511
|
+
const now = yield* Clock.currentTimeMillis;
|
|
1512
|
+
const dueRows = yield* (yield* state.storage.sql.exec(`SELECT storage_id, alarm_id, tag, run_at, repeat_every_ms, payload
|
|
1513
|
+
FROM effect_cf_scheduled_alarms
|
|
1514
|
+
WHERE run_at <= ?
|
|
1515
|
+
ORDER BY run_at ASC, storage_id ASC
|
|
1516
|
+
LIMIT ?`, now, limit)).toArray();
|
|
1517
|
+
const handled = [];
|
|
1518
|
+
const failed = [];
|
|
1519
|
+
const handleFailure = function* (row, event, cause) {
|
|
1520
|
+
const failure = {
|
|
1521
|
+
cause,
|
|
1522
|
+
event,
|
|
1523
|
+
id: row.alarm_id,
|
|
1524
|
+
storageId: row.storage_id,
|
|
1525
|
+
tag: row.tag
|
|
1526
|
+
};
|
|
1527
|
+
failed.push(failure);
|
|
1528
|
+
const failureAction = options?.onFailure === void 0 ? void 0 : yield* options.onFailure(failure);
|
|
1529
|
+
const actionMode = failureAction === void 0 ? mode : getFailureActionMode(failureAction);
|
|
1530
|
+
if (actionMode === "retry" || actionMode === "isolated") {
|
|
1531
|
+
const actionRetryDelay = failureAction === void 0 ? void 0 : getFailureActionRetryDelay(failureAction);
|
|
1532
|
+
yield* rescheduleFailedAlarm(row, actionRetryDelay === void 0 ? yield* getFailureRetryDelay(options) : yield* toFailureRescheduleMillis(actionRetryDelay));
|
|
1533
|
+
return "continue";
|
|
1534
|
+
}
|
|
1535
|
+
if (actionMode === "skip-and-advance-repeat") {
|
|
1536
|
+
yield* acknowledgeAlarm(row);
|
|
1537
|
+
return "continue";
|
|
1538
|
+
}
|
|
1539
|
+
yield* reconcileAlarm();
|
|
1540
|
+
return "stop";
|
|
1541
|
+
};
|
|
1542
|
+
for (const row of dueRows) {
|
|
1543
|
+
const eventExit = yield* Effect.exit(toAlarmDue(row));
|
|
1544
|
+
if (Exit.isFailure(eventExit)) {
|
|
1545
|
+
if ((yield* handleFailure(row, void 0, eventExit.cause)) === "stop") return yield* Effect.failCause(eventExit.cause);
|
|
1546
|
+
continue;
|
|
1547
|
+
}
|
|
1548
|
+
const event = eventExit.value;
|
|
1549
|
+
const handleExit = yield* Effect.exit(handle(event));
|
|
1550
|
+
if (Exit.isFailure(handleExit)) {
|
|
1551
|
+
if ((yield* handleFailure(row, event, handleExit.cause)) === "stop") return yield* Effect.failCause(handleExit.cause);
|
|
1552
|
+
continue;
|
|
1553
|
+
}
|
|
1554
|
+
yield* acknowledgeAlarm(row);
|
|
1555
|
+
handled.push(event);
|
|
1556
|
+
}
|
|
1557
|
+
yield* reconcileAlarm();
|
|
1558
|
+
return {
|
|
1559
|
+
failed,
|
|
1560
|
+
handled
|
|
1561
|
+
};
|
|
1562
|
+
});
|
|
1563
|
+
return DurableObjectAlarm.of({
|
|
1564
|
+
cancelAlarm,
|
|
1565
|
+
processDueAlarms,
|
|
1566
|
+
scheduleAlarm
|
|
1567
|
+
});
|
|
1568
|
+
}).pipe(Effect.withSpan("DurableObjectAlarm.layer")));
|
|
1569
|
+
};
|
|
931
1570
|
//#endregion
|
|
932
1571
|
//#region src/DurableObjectRpcWebSocket.ts
|
|
933
1572
|
var DurableObjectRpcWebSocket_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -955,32 +1594,32 @@ const layer = (options = {}) => Layer.effectContext(Effect.gen(function* () {
|
|
|
955
1594
|
let nextClientId = 0;
|
|
956
1595
|
let writeRequest;
|
|
957
1596
|
const reserveClientId = (socket) => {
|
|
958
|
-
const attachment = readAttachment(socket, attachmentKey);
|
|
1597
|
+
const attachment = readAttachment(socket.raw, attachmentKey);
|
|
959
1598
|
if (attachment !== void 0) {
|
|
960
1599
|
nextClientId = Math.max(nextClientId, attachment + 1);
|
|
961
1600
|
return attachment;
|
|
962
1601
|
}
|
|
963
1602
|
const id = nextClientId++;
|
|
964
|
-
writeAttachment(socket, attachmentKey, id);
|
|
1603
|
+
writeAttachment(socket.raw, attachmentKey, id);
|
|
965
1604
|
return id;
|
|
966
1605
|
};
|
|
967
1606
|
const register = (socket) => {
|
|
968
|
-
const existing = connectionsBySocket.get(socket);
|
|
1607
|
+
const existing = connectionsBySocket.get(socket.raw);
|
|
969
1608
|
if (existing !== void 0) return existing;
|
|
970
1609
|
const connection = {
|
|
971
1610
|
id: reserveClientId(socket),
|
|
972
1611
|
socket,
|
|
973
1612
|
parser: serialization.makeUnsafe()
|
|
974
1613
|
};
|
|
975
|
-
connectionsBySocket.set(socket, connection);
|
|
1614
|
+
connectionsBySocket.set(socket.raw, connection);
|
|
976
1615
|
connectionsById.set(connection.id, connection);
|
|
977
1616
|
clientIds.add(connection.id);
|
|
978
1617
|
return connection;
|
|
979
1618
|
};
|
|
980
1619
|
const unregister = (socket) => Effect.sync(() => {
|
|
981
|
-
const connection = connectionsBySocket.get(socket);
|
|
1620
|
+
const connection = connectionsBySocket.get(socket.raw);
|
|
982
1621
|
if (connection === void 0) return;
|
|
983
|
-
connectionsBySocket.delete(socket);
|
|
1622
|
+
connectionsBySocket.delete(socket.raw);
|
|
984
1623
|
connectionsById.delete(connection.id);
|
|
985
1624
|
clientIds.delete(connection.id);
|
|
986
1625
|
Queue.offerUnsafe(disconnects, connection.id);
|
|
@@ -989,10 +1628,10 @@ const layer = (options = {}) => Layer.effectContext(Effect.gen(function* () {
|
|
|
989
1628
|
const send = (connection, response) => Effect.sync(() => {
|
|
990
1629
|
try {
|
|
991
1630
|
const encoded = connection.parser.encode(response);
|
|
992
|
-
if (encoded !== void 0) connection.socket.send(encoded);
|
|
1631
|
+
if (encoded !== void 0) connection.socket.raw.send(encoded);
|
|
993
1632
|
} catch (cause) {
|
|
994
1633
|
const encoded = connection.parser.encode(RpcMessage.ResponseDefectEncoded(cause));
|
|
995
|
-
if (encoded !== void 0) connection.socket.send(encoded);
|
|
1634
|
+
if (encoded !== void 0) connection.socket.raw.send(encoded);
|
|
996
1635
|
}
|
|
997
1636
|
});
|
|
998
1637
|
const protocol = yield* RpcServer.Protocol.make((writeRequest_) => {
|
|
@@ -1004,7 +1643,7 @@ const layer = (options = {}) => Layer.effectContext(Effect.gen(function* () {
|
|
|
1004
1643
|
return connection === void 0 ? Effect.void : send(connection, response);
|
|
1005
1644
|
},
|
|
1006
1645
|
end: (clientId) => Effect.sync(() => {
|
|
1007
|
-
connectionsById.get(clientId)?.socket.close();
|
|
1646
|
+
connectionsById.get(clientId)?.socket.raw.close();
|
|
1008
1647
|
}),
|
|
1009
1648
|
clientIds: Effect.sync(() => clientIds),
|
|
1010
1649
|
initialMessage: Effect.succeed(Option.none()),
|
|
@@ -1055,44 +1694,13 @@ const writeAttachment = (socket, key, clientId) => {
|
|
|
1055
1694
|
});
|
|
1056
1695
|
};
|
|
1057
1696
|
//#endregion
|
|
1058
|
-
//#region src/DurableObjectWebSocket.ts
|
|
1059
|
-
var DurableObjectWebSocket_exports = /* @__PURE__ */ __exportAll({ acceptUpgrade: () => acceptUpgrade });
|
|
1060
|
-
/**
|
|
1061
|
-
* Accepts a websocket upgrade and registers the server socket on `DurableObjectState`.
|
|
1062
|
-
*
|
|
1063
|
-
* @example
|
|
1064
|
-
* ```ts
|
|
1065
|
-
* const response = yield* DurableObjectWebSocket.acceptUpgrade({
|
|
1066
|
-
* tags: ["room:general"],
|
|
1067
|
-
* });
|
|
1068
|
-
*
|
|
1069
|
-
* return response.response;
|
|
1070
|
-
* ```
|
|
1071
|
-
*/
|
|
1072
|
-
const acceptUpgrade = (options = {}) => Effect.gen(function* () {
|
|
1073
|
-
const state = yield* DurableObjectState;
|
|
1074
|
-
const pair = new WebSocketPair();
|
|
1075
|
-
const client = pair[0];
|
|
1076
|
-
const server = pair[1];
|
|
1077
|
-
if (options.attachment !== void 0) server.serializeAttachment(options.attachment);
|
|
1078
|
-
yield* state.acceptWebSocket(server, options.tags === void 0 ? void 0 : [...options.tags]);
|
|
1079
|
-
return {
|
|
1080
|
-
client,
|
|
1081
|
-
server,
|
|
1082
|
-
response: new Response(null, {
|
|
1083
|
-
status: 101,
|
|
1084
|
-
webSocket: client
|
|
1085
|
-
})
|
|
1086
|
-
};
|
|
1087
|
-
});
|
|
1088
|
-
//#endregion
|
|
1089
1697
|
//#region src/Kv.ts
|
|
1090
1698
|
var Kv_exports = /* @__PURE__ */ __exportAll({
|
|
1091
1699
|
KvOperationError: () => KvOperationError,
|
|
1092
|
-
Service: () => Service,
|
|
1093
|
-
make: () => make
|
|
1700
|
+
Service: () => Service$1,
|
|
1701
|
+
make: () => make$3
|
|
1094
1702
|
});
|
|
1095
|
-
const TypeId = "effect-cf/Kv";
|
|
1703
|
+
const TypeId$1 = "effect-cf/Kv";
|
|
1096
1704
|
/** Error raised when a KV operation fails. */
|
|
1097
1705
|
var KvOperationError = class extends Data.TaggedError("KvOperationError") {};
|
|
1098
1706
|
const maybeString = (value) => value == null ? Option.none() : Option.some(value);
|
|
@@ -1109,7 +1717,7 @@ const tryKvPromise = (binding, operation, evaluate) => Effect.tryPromise({
|
|
|
1109
1717
|
/**
|
|
1110
1718
|
* Creates a typed KV service tag plus Effect helpers.
|
|
1111
1719
|
*/
|
|
1112
|
-
const make = (id, definition) => Service()(id, definition);
|
|
1720
|
+
const make$3 = (id, definition) => Service$1()(id, definition);
|
|
1113
1721
|
/**
|
|
1114
1722
|
* Builds a KV service around a Cloudflare KV namespace binding.
|
|
1115
1723
|
*
|
|
@@ -1130,8 +1738,8 @@ const make = (id, definition) => Service()(id, definition);
|
|
|
1130
1738
|
* });
|
|
1131
1739
|
* ```
|
|
1132
1740
|
*/
|
|
1133
|
-
const Service = () => (id, definition) => {
|
|
1134
|
-
const tag = Service$
|
|
1741
|
+
const Service$1 = () => (id, definition) => {
|
|
1742
|
+
const tag = Service$5()(id, definition.binding, (value) => {
|
|
1135
1743
|
if (typeof value !== "object" || value === null) return false;
|
|
1136
1744
|
const resource = value;
|
|
1137
1745
|
return typeof resource.get === "function" && typeof resource.put === "function" && typeof resource.delete === "function" && typeof resource.getWithMetadata === "function" && typeof resource.list === "function";
|
|
@@ -1196,7 +1804,7 @@ const Service = () => (id, definition) => {
|
|
|
1196
1804
|
return yield* tag;
|
|
1197
1805
|
});
|
|
1198
1806
|
return Object.assign(tag, {
|
|
1199
|
-
[TypeId]: TypeId,
|
|
1807
|
+
[TypeId$1]: TypeId$1,
|
|
1200
1808
|
definition,
|
|
1201
1809
|
put,
|
|
1202
1810
|
get,
|
|
@@ -1207,4 +1815,214 @@ const Service = () => (id, definition) => {
|
|
|
1207
1815
|
});
|
|
1208
1816
|
};
|
|
1209
1817
|
//#endregion
|
|
1210
|
-
|
|
1818
|
+
//#region src/WorkflowBinding.ts
|
|
1819
|
+
var WorkflowBinding_exports = /* @__PURE__ */ __exportAll({
|
|
1820
|
+
Service: () => Service,
|
|
1821
|
+
WorkflowOperationError: () => WorkflowOperationError,
|
|
1822
|
+
WorkflowResultDecodeError: () => WorkflowResultDecodeError,
|
|
1823
|
+
make: () => make$2
|
|
1824
|
+
});
|
|
1825
|
+
const TypeId = "effect-cf/WorkflowBinding";
|
|
1826
|
+
var WorkflowOperationError = class extends Data.TaggedError("WorkflowOperationError") {};
|
|
1827
|
+
var WorkflowResultDecodeError = class extends Data.TaggedError("WorkflowResultDecodeError") {};
|
|
1828
|
+
const workflowError = (binding, operation, cause) => new WorkflowOperationError({
|
|
1829
|
+
binding,
|
|
1830
|
+
operation,
|
|
1831
|
+
cause
|
|
1832
|
+
});
|
|
1833
|
+
const tryWorkflowPromise = (binding, operation, evaluate) => Effect.tryPromise({
|
|
1834
|
+
try: evaluate,
|
|
1835
|
+
catch: (cause) => workflowError(binding, operation, cause)
|
|
1836
|
+
});
|
|
1837
|
+
const isWorkflow = (value) => {
|
|
1838
|
+
if (typeof value !== "object" || value === null) return false;
|
|
1839
|
+
const resource = value;
|
|
1840
|
+
return typeof resource.create === "function" && typeof resource.createBatch === "function" && typeof resource.get === "function";
|
|
1841
|
+
};
|
|
1842
|
+
const make$2 = (id, definition) => Service()(id, definition);
|
|
1843
|
+
const Service = () => (id, definition) => {
|
|
1844
|
+
const tag = Service$5()(id, definition.binding, (value) => isWorkflow(value));
|
|
1845
|
+
const encodePayload = Schema.encodeEffect(definition.payload);
|
|
1846
|
+
const decodeResult = Schema.decodeUnknownEffect(definition.result);
|
|
1847
|
+
const wrapInstance = (raw) => {
|
|
1848
|
+
const operation = (name, evaluate) => tryWorkflowPromise(definition.binding, name, evaluate);
|
|
1849
|
+
return {
|
|
1850
|
+
raw,
|
|
1851
|
+
id: raw.id,
|
|
1852
|
+
pause: operation("pause", () => raw.pause()),
|
|
1853
|
+
resume: operation("resume", () => raw.resume()),
|
|
1854
|
+
terminate: operation("terminate", () => raw.terminate()),
|
|
1855
|
+
restart: (options) => operation("restart", () => raw.restart(options)),
|
|
1856
|
+
status: operation("status", () => raw.status()).pipe(Effect.flatMap((status) => Effect.gen(function* () {
|
|
1857
|
+
const output = status.output === void 0 ? Option.none() : Option.some(yield* decodeResult(status.output).pipe(Effect.mapError((cause) => new WorkflowResultDecodeError({
|
|
1858
|
+
binding: definition.binding,
|
|
1859
|
+
instanceId: raw.id,
|
|
1860
|
+
cause
|
|
1861
|
+
}))));
|
|
1862
|
+
return {
|
|
1863
|
+
status: status.status,
|
|
1864
|
+
output,
|
|
1865
|
+
error: status.error === void 0 ? Option.none() : Option.some(status.error)
|
|
1866
|
+
};
|
|
1867
|
+
}))),
|
|
1868
|
+
sendEvent: (event) => operation("sendEvent", () => raw.sendEvent(event))
|
|
1869
|
+
};
|
|
1870
|
+
};
|
|
1871
|
+
const create = Effect.fnUntraced(function* (payload, options) {
|
|
1872
|
+
const workflow = yield* tag;
|
|
1873
|
+
const encoded = yield* encodePayload(payload);
|
|
1874
|
+
return wrapInstance(yield* tryWorkflowPromise(definition.binding, "create", () => workflow.create({
|
|
1875
|
+
...options,
|
|
1876
|
+
params: encoded
|
|
1877
|
+
})));
|
|
1878
|
+
});
|
|
1879
|
+
const createBatch = Effect.fnUntraced(function* (batch) {
|
|
1880
|
+
const workflow = yield* tag;
|
|
1881
|
+
const encodedBatch = [];
|
|
1882
|
+
for (const item of batch) {
|
|
1883
|
+
const { payload, ...options } = item;
|
|
1884
|
+
encodedBatch.push({
|
|
1885
|
+
...options,
|
|
1886
|
+
params: yield* encodePayload(payload)
|
|
1887
|
+
});
|
|
1888
|
+
}
|
|
1889
|
+
return (yield* tryWorkflowPromise(definition.binding, "createBatch", () => workflow.createBatch(encodedBatch))).map(wrapInstance);
|
|
1890
|
+
});
|
|
1891
|
+
const get = Effect.fnUntraced(function* (instanceId) {
|
|
1892
|
+
const workflow = yield* tag;
|
|
1893
|
+
return wrapInstance(yield* tryWorkflowPromise(definition.binding, "get", () => workflow.get(instanceId)));
|
|
1894
|
+
});
|
|
1895
|
+
return Object.assign(tag, {
|
|
1896
|
+
[TypeId]: TypeId,
|
|
1897
|
+
binding: definition.binding,
|
|
1898
|
+
create,
|
|
1899
|
+
createBatch,
|
|
1900
|
+
get
|
|
1901
|
+
});
|
|
1902
|
+
};
|
|
1903
|
+
//#endregion
|
|
1904
|
+
//#region src/WorkflowDefinition.ts
|
|
1905
|
+
var WorkflowDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
1906
|
+
Tag: () => Tag$1,
|
|
1907
|
+
Workflow: () => Workflow,
|
|
1908
|
+
implement: () => implement$1,
|
|
1909
|
+
make: () => make$1
|
|
1910
|
+
});
|
|
1911
|
+
const makeDefinition = (id, definition) => {
|
|
1912
|
+
const workflowDefinition = {
|
|
1913
|
+
id,
|
|
1914
|
+
payload: definition.payload,
|
|
1915
|
+
result: definition.result
|
|
1916
|
+
};
|
|
1917
|
+
return Object.assign(workflowDefinition, {
|
|
1918
|
+
make: (layer, options) => make(layer, { run: wrapHandler(workflowDefinition, options.run) }),
|
|
1919
|
+
Binding: () => (bindingId, binding) => Service()(bindingId, {
|
|
1920
|
+
...binding,
|
|
1921
|
+
payload: definition.payload,
|
|
1922
|
+
result: definition.result
|
|
1923
|
+
}),
|
|
1924
|
+
binding: (bindingId, binding) => Service()(bindingId, {
|
|
1925
|
+
...binding,
|
|
1926
|
+
payload: definition.payload,
|
|
1927
|
+
result: definition.result
|
|
1928
|
+
})
|
|
1929
|
+
});
|
|
1930
|
+
};
|
|
1931
|
+
const make$1 = makeDefinition;
|
|
1932
|
+
const Tag$1 = () => (id, definition) => {
|
|
1933
|
+
const workflowDefinition = makeDefinition(id, definition);
|
|
1934
|
+
class WorkflowDefinitionClass {
|
|
1935
|
+
static id = workflowDefinition.id;
|
|
1936
|
+
static payload = workflowDefinition.payload;
|
|
1937
|
+
static result = workflowDefinition.result;
|
|
1938
|
+
static make = workflowDefinition.make;
|
|
1939
|
+
static Binding = workflowDefinition.Binding;
|
|
1940
|
+
static binding = workflowDefinition.binding;
|
|
1941
|
+
}
|
|
1942
|
+
return WorkflowDefinitionClass;
|
|
1943
|
+
};
|
|
1944
|
+
const Workflow = Tag$1;
|
|
1945
|
+
const wrapHandler = (definition, handler) => {
|
|
1946
|
+
const decodePayload = Schema.decodeUnknownEffect(definition.payload);
|
|
1947
|
+
const encodeResult = Schema.encodeEffect(definition.result);
|
|
1948
|
+
return (payload) => Effect.gen(function* () {
|
|
1949
|
+
const decodedPayload = yield* decodePayload(payload);
|
|
1950
|
+
const decodedEvent = {
|
|
1951
|
+
...yield* WorkflowEvent$1,
|
|
1952
|
+
payload: decodedPayload
|
|
1953
|
+
};
|
|
1954
|
+
return yield* encodeResult(yield* handler(decodedPayload).pipe(Effect.provideService(WorkflowEvent$1, decodedEvent)));
|
|
1955
|
+
});
|
|
1956
|
+
};
|
|
1957
|
+
const implement$1 = (_definition, handler) => handler;
|
|
1958
|
+
//#endregion
|
|
1959
|
+
//#region src/Workflow.ts
|
|
1960
|
+
var Workflow_exports = /* @__PURE__ */ __exportAll({
|
|
1961
|
+
Tag: () => Tag,
|
|
1962
|
+
WorkflowEvent: () => WorkflowEvent$1,
|
|
1963
|
+
WorkflowStep: () => WorkflowStep$1,
|
|
1964
|
+
WorkflowStepContext: () => WorkflowStepContext$1,
|
|
1965
|
+
implement: () => implement,
|
|
1966
|
+
make: () => make,
|
|
1967
|
+
sleep: () => sleep,
|
|
1968
|
+
sleepUntil: () => sleepUntil,
|
|
1969
|
+
step: () => step,
|
|
1970
|
+
waitForEvent: () => waitForEvent
|
|
1971
|
+
});
|
|
1972
|
+
var WorkflowEvent$1 = class extends Context.Service()("effect-cf/WorkflowEvent") {};
|
|
1973
|
+
var WorkflowStep$1 = class extends Context.Service()("effect-cf/WorkflowStep") {};
|
|
1974
|
+
var WorkflowStepContext$1 = class extends Context.Service()("effect-cf/WorkflowStepContext") {};
|
|
1975
|
+
const fromWorkflowEvent = (event) => ({
|
|
1976
|
+
raw: event,
|
|
1977
|
+
payload: event.payload,
|
|
1978
|
+
timestamp: event.timestamp,
|
|
1979
|
+
instanceId: event.instanceId
|
|
1980
|
+
});
|
|
1981
|
+
const fromWorkflowStep = (step, runPromise) => ({
|
|
1982
|
+
raw: step,
|
|
1983
|
+
do: (name, effect, config) => Effect.context().pipe(Effect.flatMap((context) => Effect.tryPromise({
|
|
1984
|
+
try: () => {
|
|
1985
|
+
const run = (stepContext) => runPromise(Effect.scoped(Effect.provideService(Effect.provideContext(effect, context), WorkflowStepContext$1, stepContext)));
|
|
1986
|
+
const rawStep = step;
|
|
1987
|
+
return config === void 0 ? rawStep.do(name, run) : rawStep.do(name, config, run);
|
|
1988
|
+
},
|
|
1989
|
+
catch: (cause) => cause
|
|
1990
|
+
}))),
|
|
1991
|
+
sleep: (name, duration) => Effect.tryPromise({
|
|
1992
|
+
try: () => step.sleep(name, duration),
|
|
1993
|
+
catch: (cause) => cause
|
|
1994
|
+
}),
|
|
1995
|
+
sleepUntil: (name, timestamp) => Effect.tryPromise({
|
|
1996
|
+
try: () => step.sleepUntil(name, timestamp),
|
|
1997
|
+
catch: (cause) => cause
|
|
1998
|
+
}),
|
|
1999
|
+
waitForEvent: (name, options) => Effect.tryPromise({
|
|
2000
|
+
try: () => step.waitForEvent(name, options),
|
|
2001
|
+
catch: (cause) => cause
|
|
2002
|
+
})
|
|
2003
|
+
});
|
|
2004
|
+
const make = (layer, options) => {
|
|
2005
|
+
class EffectWorkflow extends WorkflowEntrypoint {
|
|
2006
|
+
runtime;
|
|
2007
|
+
constructor(ctx, env) {
|
|
2008
|
+
super(ctx, env);
|
|
2009
|
+
let runWaitUntilEffect = () => Promise.reject(/* @__PURE__ */ new Error("WorkerContext runtime is not initialized"));
|
|
2010
|
+
const runtimeLayer = provideEntrypointServices(layer, Layer.mergeAll(Layer.succeed(ExecutionContext, ctx), ConfigProvider.layer(Effect.succeed(WorkerConfig.providerFromEnv(env))), Layer.succeed(WorkerContext, fromExecutionContext(ctx, (effect) => runWaitUntilEffect(effect))), Layer.succeed(WorkerEnvironment, env)));
|
|
2011
|
+
this.runtime = ManagedRuntime.make(runtimeLayer);
|
|
2012
|
+
runWaitUntilEffect = (effect) => this.runtime.runPromiseExit(effect);
|
|
2013
|
+
}
|
|
2014
|
+
run(event, step) {
|
|
2015
|
+
const workflowServices = Layer.mergeAll(Layer.succeed(WorkflowEvent$1, fromWorkflowEvent(event)), Layer.succeed(WorkflowStep$1, fromWorkflowStep(step, (effect) => this.runtime.runPromise(effect))));
|
|
2016
|
+
return this.runtime.runPromise(Effect.scoped(options.run(event.payload).pipe(Effect.provide(workflowServices))));
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
return assumeEntrypointClass(EffectWorkflow);
|
|
2020
|
+
};
|
|
2021
|
+
const step = (name, effect, config) => Effect.flatMap(WorkflowStep$1.asEffect(), (workflowStep) => workflowStep.do(name, effect, config));
|
|
2022
|
+
const sleep = (name, duration) => Effect.flatMap(WorkflowStep$1.asEffect(), (workflowStep) => workflowStep.sleep(name, duration));
|
|
2023
|
+
const sleepUntil = (name, timestamp) => Effect.flatMap(WorkflowStep$1.asEffect(), (workflowStep) => workflowStep.sleepUntil(name, timestamp));
|
|
2024
|
+
const waitForEvent = (name, options) => Effect.flatMap(WorkflowStep$1.asEffect(), (workflowStep) => workflowStep.waitForEvent(name, options));
|
|
2025
|
+
const Tag = Tag$1;
|
|
2026
|
+
const implement = implement$1;
|
|
2027
|
+
//#endregion
|
|
2028
|
+
export { Binding_exports as Binding, DurableObject_exports as DurableObject, DurableObjectAlarm_exports as DurableObjectAlarm, DurableObjectDefinition_exports as DurableObjectDefinition, DurableObjectNamespace_exports as DurableObjectNamespace, DurableObjectRpcWebSocket_exports as DurableObjectRpcWebSocket, DurableObjectState_exports as DurableObjectState, DurableObjectStorage_exports as DurableObjectStorage, DurableObjectWebSocket_exports as DurableObjectWebSocket, Kv_exports as Kv, Queue_exports as Queue, QueueBinding_exports as QueueBinding, QueueDefinition_exports as QueueDefinition, Rpc_exports as Rpc, RpcDefinition_exports as RpcDefinition, ServiceBinding_exports as ServiceBinding, Worker_exports as Worker, WorkerConfig, WorkerDefinition_exports as WorkerDefinition, WorkerEnvironment, Workflow_exports as Workflow, WorkflowBinding_exports as WorkflowBinding, WorkflowDefinition_exports as WorkflowDefinition };
|