effect-cf 0.1.0 → 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/README.md +128 -1
- package/dist/index.d.mts +901 -308
- package/dist/index.mjs +613 -124
- package/package.json +3 -2
- 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 +6 -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
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 } from "cloudflare:workers";
|
|
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) {
|
|
@@ -932,9 +1242,9 @@ const make$1 = (layer, options = {}) => {
|
|
|
932
1242
|
defineEntrypointRpcMethods("Durable Object", EffectDurableObject.prototype, options.rpc, reservedMethodNames, (self, effect) => self[RunSymbol](effect));
|
|
933
1243
|
return assumeEntrypointClass(EffectDurableObject);
|
|
934
1244
|
};
|
|
935
|
-
const Tag = Tag$
|
|
1245
|
+
const Tag$2 = Tag$3;
|
|
936
1246
|
const method = method$1;
|
|
937
|
-
const implement = implement$
|
|
1247
|
+
const implement$2 = implement$3;
|
|
938
1248
|
//#endregion
|
|
939
1249
|
//#region src/DurableObjectAlarm.ts
|
|
940
1250
|
var DurableObjectAlarm_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -1284,32 +1594,32 @@ const layer = (options = {}) => Layer.effectContext(Effect.gen(function* () {
|
|
|
1284
1594
|
let nextClientId = 0;
|
|
1285
1595
|
let writeRequest;
|
|
1286
1596
|
const reserveClientId = (socket) => {
|
|
1287
|
-
const attachment = readAttachment(socket, attachmentKey);
|
|
1597
|
+
const attachment = readAttachment(socket.raw, attachmentKey);
|
|
1288
1598
|
if (attachment !== void 0) {
|
|
1289
1599
|
nextClientId = Math.max(nextClientId, attachment + 1);
|
|
1290
1600
|
return attachment;
|
|
1291
1601
|
}
|
|
1292
1602
|
const id = nextClientId++;
|
|
1293
|
-
writeAttachment(socket, attachmentKey, id);
|
|
1603
|
+
writeAttachment(socket.raw, attachmentKey, id);
|
|
1294
1604
|
return id;
|
|
1295
1605
|
};
|
|
1296
1606
|
const register = (socket) => {
|
|
1297
|
-
const existing = connectionsBySocket.get(socket);
|
|
1607
|
+
const existing = connectionsBySocket.get(socket.raw);
|
|
1298
1608
|
if (existing !== void 0) return existing;
|
|
1299
1609
|
const connection = {
|
|
1300
1610
|
id: reserveClientId(socket),
|
|
1301
1611
|
socket,
|
|
1302
1612
|
parser: serialization.makeUnsafe()
|
|
1303
1613
|
};
|
|
1304
|
-
connectionsBySocket.set(socket, connection);
|
|
1614
|
+
connectionsBySocket.set(socket.raw, connection);
|
|
1305
1615
|
connectionsById.set(connection.id, connection);
|
|
1306
1616
|
clientIds.add(connection.id);
|
|
1307
1617
|
return connection;
|
|
1308
1618
|
};
|
|
1309
1619
|
const unregister = (socket) => Effect.sync(() => {
|
|
1310
|
-
const connection = connectionsBySocket.get(socket);
|
|
1620
|
+
const connection = connectionsBySocket.get(socket.raw);
|
|
1311
1621
|
if (connection === void 0) return;
|
|
1312
|
-
connectionsBySocket.delete(socket);
|
|
1622
|
+
connectionsBySocket.delete(socket.raw);
|
|
1313
1623
|
connectionsById.delete(connection.id);
|
|
1314
1624
|
clientIds.delete(connection.id);
|
|
1315
1625
|
Queue.offerUnsafe(disconnects, connection.id);
|
|
@@ -1318,10 +1628,10 @@ const layer = (options = {}) => Layer.effectContext(Effect.gen(function* () {
|
|
|
1318
1628
|
const send = (connection, response) => Effect.sync(() => {
|
|
1319
1629
|
try {
|
|
1320
1630
|
const encoded = connection.parser.encode(response);
|
|
1321
|
-
if (encoded !== void 0) connection.socket.send(encoded);
|
|
1631
|
+
if (encoded !== void 0) connection.socket.raw.send(encoded);
|
|
1322
1632
|
} catch (cause) {
|
|
1323
1633
|
const encoded = connection.parser.encode(RpcMessage.ResponseDefectEncoded(cause));
|
|
1324
|
-
if (encoded !== void 0) connection.socket.send(encoded);
|
|
1634
|
+
if (encoded !== void 0) connection.socket.raw.send(encoded);
|
|
1325
1635
|
}
|
|
1326
1636
|
});
|
|
1327
1637
|
const protocol = yield* RpcServer.Protocol.make((writeRequest_) => {
|
|
@@ -1333,7 +1643,7 @@ const layer = (options = {}) => Layer.effectContext(Effect.gen(function* () {
|
|
|
1333
1643
|
return connection === void 0 ? Effect.void : send(connection, response);
|
|
1334
1644
|
},
|
|
1335
1645
|
end: (clientId) => Effect.sync(() => {
|
|
1336
|
-
connectionsById.get(clientId)?.socket.close();
|
|
1646
|
+
connectionsById.get(clientId)?.socket.raw.close();
|
|
1337
1647
|
}),
|
|
1338
1648
|
clientIds: Effect.sync(() => clientIds),
|
|
1339
1649
|
initialMessage: Effect.succeed(Option.none()),
|
|
@@ -1384,44 +1694,13 @@ const writeAttachment = (socket, key, clientId) => {
|
|
|
1384
1694
|
});
|
|
1385
1695
|
};
|
|
1386
1696
|
//#endregion
|
|
1387
|
-
//#region src/DurableObjectWebSocket.ts
|
|
1388
|
-
var DurableObjectWebSocket_exports = /* @__PURE__ */ __exportAll({ acceptUpgrade: () => acceptUpgrade });
|
|
1389
|
-
/**
|
|
1390
|
-
* Accepts a websocket upgrade and registers the server socket on `DurableObjectState`.
|
|
1391
|
-
*
|
|
1392
|
-
* @example
|
|
1393
|
-
* ```ts
|
|
1394
|
-
* const response = yield* DurableObjectWebSocket.acceptUpgrade({
|
|
1395
|
-
* tags: ["room:general"],
|
|
1396
|
-
* });
|
|
1397
|
-
*
|
|
1398
|
-
* return response.response;
|
|
1399
|
-
* ```
|
|
1400
|
-
*/
|
|
1401
|
-
const acceptUpgrade = (options = {}) => Effect.gen(function* () {
|
|
1402
|
-
const state = yield* DurableObjectState;
|
|
1403
|
-
const pair = new WebSocketPair();
|
|
1404
|
-
const client = pair[0];
|
|
1405
|
-
const server = pair[1];
|
|
1406
|
-
if (options.attachment !== void 0) server.serializeAttachment(options.attachment);
|
|
1407
|
-
yield* state.acceptWebSocket(server, options.tags === void 0 ? void 0 : [...options.tags]);
|
|
1408
|
-
return {
|
|
1409
|
-
client,
|
|
1410
|
-
server,
|
|
1411
|
-
response: new Response(null, {
|
|
1412
|
-
status: 101,
|
|
1413
|
-
webSocket: client
|
|
1414
|
-
})
|
|
1415
|
-
};
|
|
1416
|
-
});
|
|
1417
|
-
//#endregion
|
|
1418
1697
|
//#region src/Kv.ts
|
|
1419
1698
|
var Kv_exports = /* @__PURE__ */ __exportAll({
|
|
1420
1699
|
KvOperationError: () => KvOperationError,
|
|
1421
|
-
Service: () => Service,
|
|
1422
|
-
make: () => make
|
|
1700
|
+
Service: () => Service$1,
|
|
1701
|
+
make: () => make$3
|
|
1423
1702
|
});
|
|
1424
|
-
const TypeId = "effect-cf/Kv";
|
|
1703
|
+
const TypeId$1 = "effect-cf/Kv";
|
|
1425
1704
|
/** Error raised when a KV operation fails. */
|
|
1426
1705
|
var KvOperationError = class extends Data.TaggedError("KvOperationError") {};
|
|
1427
1706
|
const maybeString = (value) => value == null ? Option.none() : Option.some(value);
|
|
@@ -1438,7 +1717,7 @@ const tryKvPromise = (binding, operation, evaluate) => Effect.tryPromise({
|
|
|
1438
1717
|
/**
|
|
1439
1718
|
* Creates a typed KV service tag plus Effect helpers.
|
|
1440
1719
|
*/
|
|
1441
|
-
const make = (id, definition) => Service()(id, definition);
|
|
1720
|
+
const make$3 = (id, definition) => Service$1()(id, definition);
|
|
1442
1721
|
/**
|
|
1443
1722
|
* Builds a KV service around a Cloudflare KV namespace binding.
|
|
1444
1723
|
*
|
|
@@ -1459,8 +1738,8 @@ const make = (id, definition) => Service()(id, definition);
|
|
|
1459
1738
|
* });
|
|
1460
1739
|
* ```
|
|
1461
1740
|
*/
|
|
1462
|
-
const Service = () => (id, definition) => {
|
|
1463
|
-
const tag = Service$
|
|
1741
|
+
const Service$1 = () => (id, definition) => {
|
|
1742
|
+
const tag = Service$5()(id, definition.binding, (value) => {
|
|
1464
1743
|
if (typeof value !== "object" || value === null) return false;
|
|
1465
1744
|
const resource = value;
|
|
1466
1745
|
return typeof resource.get === "function" && typeof resource.put === "function" && typeof resource.delete === "function" && typeof resource.getWithMetadata === "function" && typeof resource.list === "function";
|
|
@@ -1525,7 +1804,7 @@ const Service = () => (id, definition) => {
|
|
|
1525
1804
|
return yield* tag;
|
|
1526
1805
|
});
|
|
1527
1806
|
return Object.assign(tag, {
|
|
1528
|
-
[TypeId]: TypeId,
|
|
1807
|
+
[TypeId$1]: TypeId$1,
|
|
1529
1808
|
definition,
|
|
1530
1809
|
put,
|
|
1531
1810
|
get,
|
|
@@ -1536,4 +1815,214 @@ const Service = () => (id, definition) => {
|
|
|
1536
1815
|
});
|
|
1537
1816
|
};
|
|
1538
1817
|
//#endregion
|
|
1539
|
-
|
|
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 };
|