effect-cf 0.0.1
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/README.md +79 -0
- package/dist/chunk-CfYAbeIz.mjs +13 -0
- package/dist/index.d.mts +1362 -0
- package/dist/index.mjs +1198 -0
- package/package.json +47 -0
- package/src/Binding.ts +70 -0
- package/src/DurableObject.ts +220 -0
- package/src/DurableObjectDefinition.ts +214 -0
- package/src/DurableObjectNamespace.ts +483 -0
- package/src/DurableObjectRpcWebSocket.ts +222 -0
- package/src/DurableObjectState.ts +127 -0
- package/src/DurableObjectStorage.ts +381 -0
- package/src/DurableObjectWebSocket.ts +62 -0
- package/src/Entry.ts +259 -0
- package/src/Environment.ts +86 -0
- package/src/Kv.ts +244 -0
- package/src/Rpc.ts +127 -0
- package/src/RpcDefinition.ts +354 -0
- package/src/ServiceBinding.ts +278 -0
- package/src/Worker.ts +264 -0
- package/src/WorkerDefinition.ts +206 -0
- package/src/index.ts +15 -0
- package/src/internal/Entrypoint.ts +40 -0
- package/src/internal/RpcInvocation.ts +73 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,1198 @@
|
|
|
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";
|
|
4
|
+
import { HttpServerRequest } from "effect/unstable/http";
|
|
5
|
+
import * as RpcMessage from "effect/unstable/rpc/RpcMessage";
|
|
6
|
+
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
|
|
7
|
+
import * as RpcServer from "effect/unstable/rpc/RpcServer";
|
|
8
|
+
//#region src/Environment.ts
|
|
9
|
+
/**
|
|
10
|
+
* Context service for reading worker bindings from the current `env` object.
|
|
11
|
+
*/
|
|
12
|
+
var WorkerEnvironment = class extends Context.Service()("effect-cf/WorkerEnvironment") {};
|
|
13
|
+
let WorkerConfig;
|
|
14
|
+
(function(_WorkerConfig) {
|
|
15
|
+
_WorkerConfig.string = (name) => Config.string(name);
|
|
16
|
+
_WorkerConfig.redacted = (name) => Config.redacted(name);
|
|
17
|
+
_WorkerConfig.number = (name) => Config.number(name);
|
|
18
|
+
_WorkerConfig.integer = (name) => Config.int(name);
|
|
19
|
+
_WorkerConfig.boolean = (name) => Config.boolean(name);
|
|
20
|
+
const provider = _WorkerConfig.provider = Effect.map(WorkerEnvironment.asEffect(), ConfigProvider.fromUnknown);
|
|
21
|
+
_WorkerConfig.layer = _WorkerConfig.providerLayer = ConfigProvider.layer(provider);
|
|
22
|
+
})(WorkerConfig || (WorkerConfig = {}));
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/Binding.ts
|
|
25
|
+
var Binding_exports = /* @__PURE__ */ __exportAll({
|
|
26
|
+
BindingNotFoundError: () => BindingNotFoundError,
|
|
27
|
+
BindingValidationError: () => BindingValidationError,
|
|
28
|
+
Service: () => Service$3,
|
|
29
|
+
TypeId: () => TypeId$3
|
|
30
|
+
});
|
|
31
|
+
/** Internal type id marker used by binding helper services. */
|
|
32
|
+
const TypeId$3 = "effect-cf/Binding";
|
|
33
|
+
/** Error raised when a configured binding does not exist on `env`. */
|
|
34
|
+
var BindingNotFoundError = class extends Data.TaggedError("BindingNotFoundError") {};
|
|
35
|
+
/** Error raised when a binding exists but does not match the expected shape. */
|
|
36
|
+
var BindingValidationError = class extends Data.TaggedError("BindingValidationError") {};
|
|
37
|
+
const isPropertyTarget$1 = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
|
|
38
|
+
const getBinding = (env, binding, isResource) => Effect.gen(function* () {
|
|
39
|
+
if (!isPropertyTarget$1(env)) return yield* Effect.fail(new BindingValidationError({ binding }));
|
|
40
|
+
const resource = Reflect.get(env, binding);
|
|
41
|
+
if (resource === void 0) return yield* Effect.fail(new BindingNotFoundError({ binding }));
|
|
42
|
+
if (!isResource(resource)) return yield* Effect.fail(new BindingValidationError({ binding }));
|
|
43
|
+
return resource;
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* Creates a Context tag + layer for reading and validating a Cloudflare binding.
|
|
47
|
+
*/
|
|
48
|
+
const Service$3 = () => (id, binding, isResource) => {
|
|
49
|
+
const tag = Context.Service()(id);
|
|
50
|
+
const layer = Layer.effect(tag, Effect.gen(function* () {
|
|
51
|
+
return yield* getBinding(yield* WorkerEnvironment, binding, isResource);
|
|
52
|
+
}));
|
|
53
|
+
return Object.assign(tag, {
|
|
54
|
+
[TypeId$3]: TypeId$3,
|
|
55
|
+
binding,
|
|
56
|
+
layer
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/RpcDefinition.ts
|
|
61
|
+
var RpcDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
62
|
+
ReservedMethodNameError: () => ReservedMethodNameError,
|
|
63
|
+
RpcArgumentCountError: () => RpcArgumentCountError,
|
|
64
|
+
RpcArgumentDecodeError: () => RpcArgumentDecodeError,
|
|
65
|
+
RpcArgumentEncodeError: () => RpcArgumentEncodeError,
|
|
66
|
+
RpcReservedMethodNameError: () => RpcReservedMethodNameError,
|
|
67
|
+
RpcSuccessDecodeError: () => RpcSuccessDecodeError,
|
|
68
|
+
RpcSuccessEncodeError: () => RpcSuccessEncodeError,
|
|
69
|
+
assertNoReservedMethodNames: () => assertNoReservedMethodNames,
|
|
70
|
+
assertNoReservedMethods: () => assertNoReservedMethods,
|
|
71
|
+
decodeArgs: () => decodeArgs,
|
|
72
|
+
decodeSuccess: () => decodeSuccess,
|
|
73
|
+
encodeArgs: () => encodeArgs,
|
|
74
|
+
encodeSuccess: () => encodeSuccess,
|
|
75
|
+
make: () => make$5,
|
|
76
|
+
method: () => method$4,
|
|
77
|
+
reservedMethodNames: () => reservedMethodNames$4
|
|
78
|
+
});
|
|
79
|
+
var RpcReservedMethodNameError = class extends Data.TaggedError("RpcReservedMethodNameError") {};
|
|
80
|
+
var RpcArgumentCountError = class extends Data.TaggedError("RpcArgumentCountError") {};
|
|
81
|
+
var RpcArgumentDecodeError = class extends Data.TaggedError("RpcArgumentDecodeError") {};
|
|
82
|
+
var RpcArgumentEncodeError = class extends Data.TaggedError("RpcArgumentEncodeError") {};
|
|
83
|
+
var RpcSuccessDecodeError = class extends Data.TaggedError("RpcSuccessDecodeError") {};
|
|
84
|
+
var RpcSuccessEncodeError = class extends Data.TaggedError("RpcSuccessEncodeError") {};
|
|
85
|
+
const reservedMethodNames$4 = new Set([
|
|
86
|
+
"constructor",
|
|
87
|
+
"fetch",
|
|
88
|
+
"connect",
|
|
89
|
+
"alarm",
|
|
90
|
+
"webSocketMessage",
|
|
91
|
+
"webSocketClose",
|
|
92
|
+
"webSocketError",
|
|
93
|
+
"then",
|
|
94
|
+
"dup",
|
|
95
|
+
"dispose",
|
|
96
|
+
"serialize",
|
|
97
|
+
"deserialize"
|
|
98
|
+
]);
|
|
99
|
+
var ReservedMethodNameError = class extends Error {
|
|
100
|
+
method;
|
|
101
|
+
target;
|
|
102
|
+
constructor(target, method) {
|
|
103
|
+
super(`${target} RPC method "${method}" is reserved by Cloudflare Workers RPC`);
|
|
104
|
+
this.name = "ReservedMethodNameError";
|
|
105
|
+
this.target = target;
|
|
106
|
+
this.method = method;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const assertNoReservedMethods = (target, methods, reserved) => {
|
|
110
|
+
for (const method of Object.keys(methods)) if (reserved.has(method)) throw new ReservedMethodNameError(target, method);
|
|
111
|
+
};
|
|
112
|
+
function method$4(definition) {
|
|
113
|
+
return {
|
|
114
|
+
args: definition.args ?? [],
|
|
115
|
+
success: definition.success
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const assertNoReservedMethodNames = (definition) => Effect.forEach(Object.keys(definition.methods), (method) => reservedMethodNames$4.has(method) ? Effect.fail(new RpcReservedMethodNameError({
|
|
119
|
+
definition: definition.id,
|
|
120
|
+
method
|
|
121
|
+
})) : Effect.void).pipe(Effect.asVoid);
|
|
122
|
+
const decodeArgs = (definition, methodName, args) => Effect.gen(function* () {
|
|
123
|
+
const methodDefinition = definition.methods[methodName];
|
|
124
|
+
if (args.length !== methodDefinition.args.length) return yield* Effect.fail(new RpcArgumentCountError({
|
|
125
|
+
definition: definition.id,
|
|
126
|
+
method: methodName,
|
|
127
|
+
expected: methodDefinition.args.length,
|
|
128
|
+
actual: args.length
|
|
129
|
+
}));
|
|
130
|
+
const decoded = [];
|
|
131
|
+
for (let index = 0; index < methodDefinition.args.length; index++) {
|
|
132
|
+
const schema = methodDefinition.args[index];
|
|
133
|
+
decoded.push(yield* Schema.decodeUnknownEffect(schema)(args[index]).pipe(Effect.mapError((cause) => new RpcArgumentDecodeError({
|
|
134
|
+
definition: definition.id,
|
|
135
|
+
method: methodName,
|
|
136
|
+
index,
|
|
137
|
+
cause
|
|
138
|
+
}))));
|
|
139
|
+
}
|
|
140
|
+
return decoded;
|
|
141
|
+
});
|
|
142
|
+
const encodeArgs = (definition, methodName, args) => Effect.gen(function* () {
|
|
143
|
+
const methodDefinition = definition.methods[methodName];
|
|
144
|
+
if (args.length !== methodDefinition.args.length) return yield* Effect.fail(new RpcArgumentCountError({
|
|
145
|
+
definition: definition.id,
|
|
146
|
+
method: methodName,
|
|
147
|
+
expected: methodDefinition.args.length,
|
|
148
|
+
actual: args.length
|
|
149
|
+
}));
|
|
150
|
+
const encoded = [];
|
|
151
|
+
for (let index = 0; index < methodDefinition.args.length; index++) {
|
|
152
|
+
const schema = methodDefinition.args[index];
|
|
153
|
+
encoded.push(yield* Schema.encodeEffect(schema)(args[index]).pipe(Effect.mapError((cause) => new RpcArgumentEncodeError({
|
|
154
|
+
definition: definition.id,
|
|
155
|
+
method: methodName,
|
|
156
|
+
index,
|
|
157
|
+
cause
|
|
158
|
+
}))));
|
|
159
|
+
}
|
|
160
|
+
return encoded;
|
|
161
|
+
});
|
|
162
|
+
const encodeSuccess = (definition, methodName, value) => {
|
|
163
|
+
const methodDefinition = definition.methods[methodName];
|
|
164
|
+
return Schema.encodeEffect(methodDefinition.success)(value).pipe(Effect.mapError((cause) => new RpcSuccessEncodeError({
|
|
165
|
+
definition: definition.id,
|
|
166
|
+
method: methodName,
|
|
167
|
+
cause
|
|
168
|
+
})));
|
|
169
|
+
};
|
|
170
|
+
const decodeSuccess = (definition, methodName, value) => {
|
|
171
|
+
const methodDefinition = definition.methods[methodName];
|
|
172
|
+
return Schema.decodeUnknownEffect(methodDefinition.success)(value).pipe(Effect.mapError((cause) => new RpcSuccessDecodeError({
|
|
173
|
+
definition: definition.id,
|
|
174
|
+
method: methodName,
|
|
175
|
+
cause
|
|
176
|
+
})));
|
|
177
|
+
};
|
|
178
|
+
const make$5 = (id, methods) => {
|
|
179
|
+
const definition = {
|
|
180
|
+
id,
|
|
181
|
+
methods
|
|
182
|
+
};
|
|
183
|
+
const reserved = Object.keys(definition.methods).find((methodName) => reservedMethodNames$4.has(methodName));
|
|
184
|
+
if (reserved !== void 0) throw new RpcReservedMethodNameError({
|
|
185
|
+
definition: id,
|
|
186
|
+
method: reserved
|
|
187
|
+
});
|
|
188
|
+
return definition;
|
|
189
|
+
};
|
|
190
|
+
//#endregion
|
|
191
|
+
//#region src/Rpc.ts
|
|
192
|
+
var Rpc_exports = /* @__PURE__ */ __exportAll({
|
|
193
|
+
RpcStub: () => RpcStub,
|
|
194
|
+
RpcTarget: () => RpcTarget,
|
|
195
|
+
dispose: () => dispose,
|
|
196
|
+
isDisposable: () => isDisposable,
|
|
197
|
+
resolve: () => resolve,
|
|
198
|
+
scoped: () => scoped
|
|
199
|
+
});
|
|
200
|
+
const isDisposable = (value) => (typeof value === "object" || typeof value === "function") && value !== null && Symbol.dispose in value && typeof value[Symbol.dispose] === "function";
|
|
201
|
+
const dispose = (value) => Effect.sync(() => {
|
|
202
|
+
if (isDisposable(value)) value[Symbol.dispose]();
|
|
203
|
+
});
|
|
204
|
+
const resolve = (value) => isPromiseLike(value) ? Effect.tryPromise({
|
|
205
|
+
try: () => value,
|
|
206
|
+
catch: (cause) => cause
|
|
207
|
+
}) : Effect.sync(() => value);
|
|
208
|
+
const scoped = (value) => Effect.acquireRelease(resolve(value), (resolved) => dispose(resolved));
|
|
209
|
+
const isPromiseLike = (value) => (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region src/internal/RpcInvocation.ts
|
|
212
|
+
const isPropertyTarget = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
|
|
213
|
+
const lookupRpcMethod = (target, method, makeError) => Effect.try({
|
|
214
|
+
try: () => {
|
|
215
|
+
if (!isPropertyTarget(target)) throw new TypeError(`RPC target is not object-like`);
|
|
216
|
+
const value = Reflect.get(target, method);
|
|
217
|
+
if (typeof value !== "function") throw new TypeError(`RPC method "${String(method)}" is not callable`);
|
|
218
|
+
return ((...args) => Reflect.apply(value, target, args));
|
|
219
|
+
},
|
|
220
|
+
catch: makeError
|
|
221
|
+
});
|
|
222
|
+
const invokeRpcMethod = (target, method, args, makeError) => Effect.gen(function* () {
|
|
223
|
+
const fn = yield* lookupRpcMethod(target, method, makeError);
|
|
224
|
+
return yield* Effect.try({
|
|
225
|
+
try: () => fn(...args),
|
|
226
|
+
catch: makeError
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
//#endregion
|
|
230
|
+
//#region src/ServiceBinding.ts
|
|
231
|
+
var ServiceBinding_exports = /* @__PURE__ */ __exportAll({
|
|
232
|
+
Service: () => Service$2,
|
|
233
|
+
ServiceBindingFetchError: () => ServiceBindingFetchError,
|
|
234
|
+
ServiceBindingRpcError: () => ServiceBindingRpcError
|
|
235
|
+
});
|
|
236
|
+
const TypeId$2 = "effect-cf/ServiceBinding";
|
|
237
|
+
/**
|
|
238
|
+
* Failure raised when calling `fetch` on a service binding.
|
|
239
|
+
*/
|
|
240
|
+
var ServiceBindingFetchError = class extends Data.TaggedError("ServiceBindingFetchError") {};
|
|
241
|
+
/**
|
|
242
|
+
* Failure raised when invoking an RPC method on a service binding.
|
|
243
|
+
*/
|
|
244
|
+
var ServiceBindingRpcError = class extends Data.TaggedError("ServiceBindingRpcError") {};
|
|
245
|
+
/**
|
|
246
|
+
* Creates a typed Effect service for a Worker service binding.
|
|
247
|
+
*
|
|
248
|
+
* Returned value includes:
|
|
249
|
+
* - a Context tag for dependency injection
|
|
250
|
+
* - `fetch(...)` for raw HTTP forwarding
|
|
251
|
+
* - `call(...)` for generic RPC invocation
|
|
252
|
+
* - direct RPC methods when `definition` is provided
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```ts
|
|
256
|
+
* const Counter = WorkerDefinition.make("Counter", {
|
|
257
|
+
* increment: WorkerDefinition.method({
|
|
258
|
+
* args: [Schema.Number],
|
|
259
|
+
* success: Schema.Number,
|
|
260
|
+
* }),
|
|
261
|
+
* });
|
|
262
|
+
*
|
|
263
|
+
* const CounterService = Counter.binding("COUNTER", { binding: "COUNTER" });
|
|
264
|
+
*
|
|
265
|
+
* const program = Effect.gen(function* () {
|
|
266
|
+
* const next = yield* CounterService.increment(1);
|
|
267
|
+
* return next;
|
|
268
|
+
* });
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
271
|
+
const Service$2 = () => (id, definition) => {
|
|
272
|
+
const tag = Service$3()(id, definition.binding, (value) => typeof value === "object" && value !== null && "fetch" in value);
|
|
273
|
+
const fetch = (input, init) => Effect.gen(function* () {
|
|
274
|
+
const service = yield* tag;
|
|
275
|
+
return yield* Effect.tryPromise({
|
|
276
|
+
try: () => service.fetch(input, init),
|
|
277
|
+
catch: (cause) => new ServiceBindingFetchError({
|
|
278
|
+
binding: definition.binding,
|
|
279
|
+
cause
|
|
280
|
+
})
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
const rpc = (method, ...args) => Effect.gen(function* () {
|
|
284
|
+
const service = yield* tag;
|
|
285
|
+
const methodName = String(method);
|
|
286
|
+
return yield* invokeRpcMethod(service, method, definition.definition === void 0 ? args : yield* encodeArgs(definition.definition, methodName, args).pipe(Effect.mapError((cause) => new ServiceBindingRpcError({
|
|
287
|
+
binding: definition.binding,
|
|
288
|
+
method: methodName,
|
|
289
|
+
cause
|
|
290
|
+
}))), (cause) => new ServiceBindingRpcError({
|
|
291
|
+
binding: definition.binding,
|
|
292
|
+
method: methodName,
|
|
293
|
+
cause
|
|
294
|
+
}));
|
|
295
|
+
});
|
|
296
|
+
const call = (method, ...args) => Effect.gen(function* () {
|
|
297
|
+
const methodName = String(method);
|
|
298
|
+
const value = yield* resolve(yield* rpc(method, ...args)).pipe(Effect.mapError((cause) => new ServiceBindingRpcError({
|
|
299
|
+
binding: definition.binding,
|
|
300
|
+
method: methodName,
|
|
301
|
+
cause
|
|
302
|
+
})));
|
|
303
|
+
if (definition.definition === void 0) return value;
|
|
304
|
+
return yield* decodeSuccess(definition.definition, methodName, value).pipe(Effect.mapError((cause) => new ServiceBindingRpcError({
|
|
305
|
+
binding: definition.binding,
|
|
306
|
+
method: methodName,
|
|
307
|
+
cause
|
|
308
|
+
})));
|
|
309
|
+
});
|
|
310
|
+
const scopedCall = (method, ...args) => Effect.gen(function* () {
|
|
311
|
+
return yield* scoped(yield* rpc(method, ...args));
|
|
312
|
+
});
|
|
313
|
+
const directMethods = makeDirectMethods$1(definition.definition, call);
|
|
314
|
+
return Object.assign(tag, directMethods, {
|
|
315
|
+
[TypeId$2]: TypeId$2,
|
|
316
|
+
definition,
|
|
317
|
+
fetch,
|
|
318
|
+
rpc,
|
|
319
|
+
call,
|
|
320
|
+
scopedCall
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
const makeDirectMethods$1 = (rpcDefinition, call) => {
|
|
324
|
+
const methods = {};
|
|
325
|
+
if (rpcDefinition !== void 0) for (const methodName of Object.keys(rpcDefinition.methods)) methods[methodName] = (...args) => call(methodName, ...args);
|
|
326
|
+
return methods;
|
|
327
|
+
};
|
|
328
|
+
//#endregion
|
|
329
|
+
//#region src/WorkerDefinition.ts
|
|
330
|
+
var WorkerDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
331
|
+
Tag: () => Tag$3,
|
|
332
|
+
Worker: () => Worker,
|
|
333
|
+
implement: () => implement$3,
|
|
334
|
+
make: () => make$4,
|
|
335
|
+
method: () => method$3
|
|
336
|
+
});
|
|
337
|
+
const reservedMethodNames$3 = new Set([
|
|
338
|
+
"constructor",
|
|
339
|
+
"dup",
|
|
340
|
+
"fetch",
|
|
341
|
+
"connect",
|
|
342
|
+
"alarm",
|
|
343
|
+
"webSocketMessage",
|
|
344
|
+
"webSocketClose",
|
|
345
|
+
"webSocketError"
|
|
346
|
+
]);
|
|
347
|
+
/**
|
|
348
|
+
* Defines a single RPC method schema in a worker definition.
|
|
349
|
+
*/
|
|
350
|
+
const method$3 = method$4;
|
|
351
|
+
/**
|
|
352
|
+
* Creates a typed worker RPC definition plus helpers for implementation and bindings.
|
|
353
|
+
*
|
|
354
|
+
* @example
|
|
355
|
+
* ```ts
|
|
356
|
+
* const CounterWorker = WorkerDefinition.make("CounterWorker", {
|
|
357
|
+
* increment: WorkerDefinition.method({
|
|
358
|
+
* args: [Schema.Number],
|
|
359
|
+
* success: Schema.Number,
|
|
360
|
+
* }),
|
|
361
|
+
* });
|
|
362
|
+
* ```
|
|
363
|
+
*/
|
|
364
|
+
const makeDefinition$1 = (id, methods) => {
|
|
365
|
+
assertNoReservedMethods("Worker", methods, reservedMethodNames$3);
|
|
366
|
+
const definition = make$5(id, methods);
|
|
367
|
+
return Object.assign(definition, {
|
|
368
|
+
make: (layer, options) => make$3(layer, {
|
|
369
|
+
...options,
|
|
370
|
+
rpc: wrapHandlers$1(definition, options.rpc)
|
|
371
|
+
}),
|
|
372
|
+
Binding: () => (bindingId, binding) => Service$2()(bindingId, {
|
|
373
|
+
...binding,
|
|
374
|
+
definition
|
|
375
|
+
}),
|
|
376
|
+
binding: (bindingId, binding) => Service$2()(bindingId, {
|
|
377
|
+
...binding,
|
|
378
|
+
definition
|
|
379
|
+
})
|
|
380
|
+
});
|
|
381
|
+
};
|
|
382
|
+
const make$4 = makeDefinition$1;
|
|
383
|
+
const Tag$3 = () => (id, methods) => {
|
|
384
|
+
const definition = makeDefinition$1(id, methods);
|
|
385
|
+
class WorkerDefinitionClass {
|
|
386
|
+
static id = definition.id;
|
|
387
|
+
static methods = definition.methods;
|
|
388
|
+
static make = definition.make;
|
|
389
|
+
static Binding = definition.Binding;
|
|
390
|
+
static binding = definition.binding;
|
|
391
|
+
}
|
|
392
|
+
return WorkerDefinitionClass;
|
|
393
|
+
};
|
|
394
|
+
const Worker = Tag$3;
|
|
395
|
+
const wrapHandlers$1 = (definition, handlers) => {
|
|
396
|
+
const wrapped = {};
|
|
397
|
+
for (const key of Object.keys(definition.methods)) {
|
|
398
|
+
const handler = handlers[key];
|
|
399
|
+
wrapped[key] = (...args) => Effect.gen(function* () {
|
|
400
|
+
return yield* encodeSuccess(definition, key, yield* handler(...yield* decodeArgs(definition, key, args)));
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
return wrapped;
|
|
404
|
+
};
|
|
405
|
+
/**
|
|
406
|
+
* Helper for implementing handlers with the exact method shape of a definition.
|
|
407
|
+
*/
|
|
408
|
+
const implement$3 = (_definition, handlers) => handlers;
|
|
409
|
+
//#endregion
|
|
410
|
+
//#region src/internal/Entrypoint.ts
|
|
411
|
+
const provideEntrypointServices = (layer, services) => layer.pipe(Layer.provideMerge(services));
|
|
412
|
+
const defineEntrypointRpcMethods = (target, prototype, rpc, reservedMethodNames, run) => {
|
|
413
|
+
const methods = rpc ?? {};
|
|
414
|
+
assertNoReservedMethods(target, methods, reservedMethodNames);
|
|
415
|
+
for (const [key, method] of Object.entries(methods)) Object.defineProperty(prototype, key, {
|
|
416
|
+
enumerable: true,
|
|
417
|
+
value(...args) {
|
|
418
|
+
return run(this, Effect.suspend(() => method(...args)));
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
};
|
|
422
|
+
const assumeEntrypointClass = (entrypoint) => entrypoint;
|
|
423
|
+
//#endregion
|
|
424
|
+
//#region src/Worker.ts
|
|
425
|
+
var Worker_exports = /* @__PURE__ */ __exportAll({
|
|
426
|
+
ExecutionContext: () => ExecutionContext,
|
|
427
|
+
NativeRequest: () => NativeRequest,
|
|
428
|
+
Tag: () => Tag$2,
|
|
429
|
+
WorkerContext: () => WorkerContext,
|
|
430
|
+
implement: () => implement$2,
|
|
431
|
+
isWebSocketUpgrade: () => isWebSocketUpgrade,
|
|
432
|
+
make: () => make$3,
|
|
433
|
+
method: () => method$2
|
|
434
|
+
});
|
|
435
|
+
var ExecutionContext = class extends Context.Service()("effect-cf/ExecutionContext") {};
|
|
436
|
+
var WorkerContext = class extends Context.Service()("effect-cf/WorkerContext") {};
|
|
437
|
+
const fromExecutionContext = (ctx, runPromiseExit) => ({
|
|
438
|
+
raw: ctx,
|
|
439
|
+
waitUntil: (effect, options) => Effect.context().pipe(Effect.flatMap((context) => Effect.sync(() => {
|
|
440
|
+
const observed = Effect.exit(effect).pipe(Effect.flatMap((exit) => {
|
|
441
|
+
if (Exit.isSuccess(exit)) return Effect.void;
|
|
442
|
+
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))));
|
|
443
|
+
}));
|
|
444
|
+
ctx.waitUntil(runPromiseExit(Effect.scoped(Effect.provideContext(observed, context))).then((exit) => {
|
|
445
|
+
if (Exit.isFailure(exit)) console.error("WorkerContext.waitUntil failure handler failed", Cause.pretty(exit.cause));
|
|
446
|
+
}));
|
|
447
|
+
}))),
|
|
448
|
+
passThroughOnException: Effect.sync(() => ctx.passThroughOnException())
|
|
449
|
+
});
|
|
450
|
+
var NativeRequest = class extends Context.Service()("effect-cf/NativeRequest") {};
|
|
451
|
+
const isWebSocketUpgrade = (request) => request.headers.get("Upgrade")?.toLowerCase() === "websocket";
|
|
452
|
+
const reservedMethodNames$2 = new Set([
|
|
453
|
+
"constructor",
|
|
454
|
+
"dup",
|
|
455
|
+
"fetch",
|
|
456
|
+
"connect",
|
|
457
|
+
"alarm",
|
|
458
|
+
"webSocketMessage",
|
|
459
|
+
"webSocketClose",
|
|
460
|
+
"webSocketError"
|
|
461
|
+
]);
|
|
462
|
+
const RunSymbol$1 = Symbol.for("effect-cf/Worker/run");
|
|
463
|
+
const make$3 = (layer, options) => {
|
|
464
|
+
class EffectWorker extends WorkerEntrypoint {
|
|
465
|
+
runtime;
|
|
466
|
+
constructor(ctx, env) {
|
|
467
|
+
super(ctx, env);
|
|
468
|
+
let runWaitUntilEffect = () => Promise.resolve(Exit.die(/* @__PURE__ */ new Error("WorkerContext runtime is not initialized")));
|
|
469
|
+
const runtimeLayer = provideEntrypointServices(layer, Layer.mergeAll(Layer.succeed(ExecutionContext, ctx), Layer.succeed(WorkerContext, fromExecutionContext(ctx, (effect) => runWaitUntilEffect(effect))), Layer.succeed(WorkerEnvironment, env)));
|
|
470
|
+
this.runtime = ManagedRuntime.make(runtimeLayer);
|
|
471
|
+
runWaitUntilEffect = (effect) => this.runtime.runPromiseExit(effect);
|
|
472
|
+
}
|
|
473
|
+
[RunSymbol$1](effect) {
|
|
474
|
+
return this.runtime.runPromise(Effect.scoped(effect));
|
|
475
|
+
}
|
|
476
|
+
fetch(request) {
|
|
477
|
+
const fetchHandler = options.fetch;
|
|
478
|
+
if (fetchHandler === void 0) return Promise.resolve(new Response("Not Found", { status: 404 }));
|
|
479
|
+
return this[RunSymbol$1](fetchHandler.pipe(Effect.provideService(NativeRequest, request), Effect.provideService(HttpServerRequest.HttpServerRequest, HttpServerRequest.fromWeb(request))));
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
defineEntrypointRpcMethods("Worker", EffectWorker.prototype, options.rpc, reservedMethodNames$2, (self, effect) => self[RunSymbol$1](effect));
|
|
483
|
+
return assumeEntrypointClass(EffectWorker);
|
|
484
|
+
};
|
|
485
|
+
const Tag$2 = Tag$3;
|
|
486
|
+
const method$2 = method$3;
|
|
487
|
+
const implement$2 = implement$3;
|
|
488
|
+
//#endregion
|
|
489
|
+
//#region src/DurableObjectStorage.ts
|
|
490
|
+
var DurableObjectStorage_exports = /* @__PURE__ */ __exportAll({
|
|
491
|
+
StorageOperationError: () => StorageOperationError,
|
|
492
|
+
fromDurableObjectStorage: () => fromDurableObjectStorage
|
|
493
|
+
});
|
|
494
|
+
/** Error type used when a storage operation throws or rejects. */
|
|
495
|
+
var StorageOperationError = class extends Data.TaggedError("StorageOperationError") {};
|
|
496
|
+
const storageError = (operation, cause) => new StorageOperationError({
|
|
497
|
+
operation,
|
|
498
|
+
cause
|
|
499
|
+
});
|
|
500
|
+
const tryStorageSync = (operation, evaluate) => Effect.try({
|
|
501
|
+
try: evaluate,
|
|
502
|
+
catch: (cause) => storageError(operation, cause)
|
|
503
|
+
});
|
|
504
|
+
const tryStoragePromise = (operation, evaluate) => Effect.tryPromise({
|
|
505
|
+
try: evaluate,
|
|
506
|
+
catch: (cause) => storageError(operation, cause)
|
|
507
|
+
});
|
|
508
|
+
const fromSqlCursor = (cursor) => ({
|
|
509
|
+
next: () => tryStorageSync("sql.next", () => cursor.next()),
|
|
510
|
+
toArray: () => tryStorageSync("sql.toArray", () => cursor.toArray()),
|
|
511
|
+
one: () => tryStorageSync("sql.one", () => cursor.one()),
|
|
512
|
+
raw: () => tryStorageSync("sql.raw", () => cursor.raw()),
|
|
513
|
+
get columnNames() {
|
|
514
|
+
return cursor.columnNames;
|
|
515
|
+
},
|
|
516
|
+
rowsRead: tryStorageSync("sql.rowsRead", () => cursor.rowsRead),
|
|
517
|
+
rowsWritten: tryStorageSync("sql.rowsWritten", () => cursor.rowsWritten)
|
|
518
|
+
});
|
|
519
|
+
const fromSqlStorage = (sql) => ({
|
|
520
|
+
exec: (query, ...bindings) => tryStorageSync("sql.exec", () => fromSqlCursor(sql.exec(query, ...bindings))),
|
|
521
|
+
get databaseSize() {
|
|
522
|
+
return sql.databaseSize;
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
const schemaBackedSyncKvStorage = (kv, definition) => {
|
|
526
|
+
const encodeKey = Schema.encodeEffect(definition.key);
|
|
527
|
+
const decodeKey = Schema.decodeUnknownEffect(definition.key);
|
|
528
|
+
const encodeValue = Schema.encodeEffect(definition.value);
|
|
529
|
+
const decodeValue = Schema.decodeUnknownEffect(definition.value);
|
|
530
|
+
return {
|
|
531
|
+
get: (key) => Effect.gen(function* () {
|
|
532
|
+
const encodedKey = yield* encodeKey(key);
|
|
533
|
+
const encodedValue = yield* tryStorageSync("kv.get", () => kv.get(encodedKey));
|
|
534
|
+
if (encodedValue === void 0) return Option.none();
|
|
535
|
+
return yield* decodeValue(encodedValue).pipe(Effect.map(Option.some));
|
|
536
|
+
}),
|
|
537
|
+
put: (key, value) => Effect.gen(function* () {
|
|
538
|
+
const encodedKey = yield* encodeKey(key);
|
|
539
|
+
const encodedValue = yield* encodeValue(value);
|
|
540
|
+
yield* tryStorageSync("kv.put", () => kv.put(encodedKey, encodedValue));
|
|
541
|
+
}),
|
|
542
|
+
delete: (key) => Effect.gen(function* () {
|
|
543
|
+
const encodedKey = yield* encodeKey(key);
|
|
544
|
+
return yield* tryStorageSync("kv.delete", () => kv.delete(encodedKey));
|
|
545
|
+
}),
|
|
546
|
+
list: (options) => Effect.gen(function* () {
|
|
547
|
+
const entries = Array.from(yield* tryStorageSync("kv.list", () => kv.list(options)));
|
|
548
|
+
const decoded = [];
|
|
549
|
+
for (const [key, value] of entries) decoded.push([yield* decodeKey(key), yield* decodeValue(value)]);
|
|
550
|
+
return decoded;
|
|
551
|
+
})
|
|
552
|
+
};
|
|
553
|
+
};
|
|
554
|
+
const fromSyncKvStorage = (kv) => ({
|
|
555
|
+
get: (key) => tryStorageSync("kv.get", () => kv.get(key)),
|
|
556
|
+
put: (key, value) => tryStorageSync("kv.put", () => kv.put(key, value)),
|
|
557
|
+
delete: (key) => tryStorageSync("kv.delete", () => kv.delete(key)),
|
|
558
|
+
list: (options) => tryStorageSync("kv.list", () => Array.from(kv.list(options))),
|
|
559
|
+
schema: (definition) => schemaBackedSyncKvStorage(kv, definition)
|
|
560
|
+
});
|
|
561
|
+
const fromDurableObjectTransaction = (txn) => ({
|
|
562
|
+
get: (keyOrKeys, options) => Array.isArray(keyOrKeys) ? tryStoragePromise("transaction.get", () => txn.get(keyOrKeys, options)) : tryStoragePromise("transaction.get", () => txn.get(keyOrKeys, options)),
|
|
563
|
+
list: (options) => tryStoragePromise("transaction.list", () => txn.list(options)),
|
|
564
|
+
put: (keyOrEntries, valueOrOptions, maybeOptions) => tryStoragePromise("transaction.put", () => typeof keyOrEntries === "string" ? txn.put(keyOrEntries, valueOrOptions, maybeOptions) : txn.put(keyOrEntries, valueOrOptions)),
|
|
565
|
+
delete: (keyOrKeys, options) => Array.isArray(keyOrKeys) ? tryStoragePromise("transaction.delete", () => txn.delete(keyOrKeys, options)) : tryStoragePromise("transaction.delete", () => txn.delete(keyOrKeys, options)),
|
|
566
|
+
rollback: () => tryStorageSync("transaction.rollback", () => txn.rollback()),
|
|
567
|
+
getAlarm: (options) => tryStoragePromise("transaction.getAlarm", () => txn.getAlarm(options)),
|
|
568
|
+
setAlarm: (scheduledTime, options) => tryStoragePromise("transaction.setAlarm", () => txn.setAlarm(scheduledTime, options)),
|
|
569
|
+
deleteAlarm: (options) => tryStoragePromise("transaction.deleteAlarm", () => txn.deleteAlarm(options))
|
|
570
|
+
});
|
|
571
|
+
/**
|
|
572
|
+
* Wraps native Cloudflare storage APIs as Effect-returning helpers.
|
|
573
|
+
*/
|
|
574
|
+
const fromDurableObjectStorage = (storage) => ({
|
|
575
|
+
get: (key, options) => tryStoragePromise("get", () => storage.get(key, options)),
|
|
576
|
+
put: (key, value, options) => tryStoragePromise("put", () => storage.put(key, value, options)),
|
|
577
|
+
delete: (key, options) => tryStoragePromise("delete", () => storage.delete(key, options)),
|
|
578
|
+
deleteAll: (options) => tryStoragePromise("deleteAll", () => storage.deleteAll(options)),
|
|
579
|
+
getAlarm: (options) => tryStoragePromise("getAlarm", () => storage.getAlarm(options)),
|
|
580
|
+
setAlarm: (scheduledTime, options) => tryStoragePromise("setAlarm", () => storage.setAlarm(scheduledTime, options)),
|
|
581
|
+
deleteAlarm: (options) => tryStoragePromise("deleteAlarm", () => storage.deleteAlarm(options)),
|
|
582
|
+
transactionSync: (closure) => Effect.context().pipe(Effect.flatMap((context) => Effect.suspend(() => {
|
|
583
|
+
try {
|
|
584
|
+
return Effect.succeed(storage.transactionSync(() => {
|
|
585
|
+
const exit = Effect.runSyncExitWith(context)(closure());
|
|
586
|
+
if (Exit.isSuccess(exit)) return exit.value;
|
|
587
|
+
throw exit;
|
|
588
|
+
}));
|
|
589
|
+
} catch (cause) {
|
|
590
|
+
if (Exit.isExit(cause) && Exit.isFailure(cause)) return Effect.failCause(cause.cause);
|
|
591
|
+
return Effect.fail(storageError("transactionSync", cause));
|
|
592
|
+
}
|
|
593
|
+
}))),
|
|
594
|
+
transaction: (closure) => Effect.context().pipe(Effect.flatMap((context) => Effect.callback((resume) => {
|
|
595
|
+
storage.transaction(async (txn) => {
|
|
596
|
+
const exit = await Effect.runPromiseExitWith(context)(closure(fromDurableObjectTransaction(txn)));
|
|
597
|
+
if (Exit.isSuccess(exit)) return exit.value;
|
|
598
|
+
throw exit;
|
|
599
|
+
}).then((value) => resume(Effect.succeed(value)), (cause) => {
|
|
600
|
+
if (Exit.isExit(cause) && Exit.isFailure(cause)) resume(Effect.failCause(cause.cause));
|
|
601
|
+
else resume(Effect.fail(storageError("transaction", cause)));
|
|
602
|
+
});
|
|
603
|
+
}))),
|
|
604
|
+
sync: () => tryStoragePromise("sync", () => storage.sync()),
|
|
605
|
+
getCurrentBookmark: () => tryStoragePromise("getCurrentBookmark", () => storage.getCurrentBookmark()),
|
|
606
|
+
onNextSessionRestoreBookmark: (bookmark) => tryStoragePromise("onNextSessionRestoreBookmark", () => storage.onNextSessionRestoreBookmark(bookmark)),
|
|
607
|
+
sql: fromSqlStorage(storage.sql),
|
|
608
|
+
kv: fromSyncKvStorage(storage.kv)
|
|
609
|
+
});
|
|
610
|
+
//#endregion
|
|
611
|
+
//#region src/DurableObjectState.ts
|
|
612
|
+
var DurableObjectState_exports = /* @__PURE__ */ __exportAll({
|
|
613
|
+
DurableObjectState: () => DurableObjectState,
|
|
614
|
+
fromDurableObjectState: () => fromDurableObjectState
|
|
615
|
+
});
|
|
616
|
+
/**
|
|
617
|
+
* Context tag for accessing the current Durable Object state service.
|
|
618
|
+
*/
|
|
619
|
+
var DurableObjectState = class extends Context.Service()("effect-cf/DurableObjectState") {};
|
|
620
|
+
/**
|
|
621
|
+
* Wraps a native Cloudflare `DurableObjectState` as a {@link DurableObjectStateService}.
|
|
622
|
+
*/
|
|
623
|
+
const fromDurableObjectState = (state) => ({
|
|
624
|
+
raw: state,
|
|
625
|
+
id: state.id,
|
|
626
|
+
storage: fromDurableObjectStorage(state.storage),
|
|
627
|
+
waitUntil: (promise) => Effect.sync(() => state.waitUntil(promise)),
|
|
628
|
+
blockConcurrencyWhile: (effect) => Effect.context().pipe(Effect.flatMap((context) => Effect.promise(() => state.blockConcurrencyWhile(() => runPromiseExitPreservingTypedFailures(Effect.provideContext(effect, context))))), Effect.flatten),
|
|
629
|
+
blockConcurrencyWhileOrReset: (effect) => Effect.context().pipe(Effect.flatMap((context) => Effect.promise(() => state.blockConcurrencyWhile(() => Effect.runPromise(Effect.provideContext(effect, context)))))),
|
|
630
|
+
acceptWebSocket: (ws, tags) => Effect.sync(() => state.acceptWebSocket(ws, tags)),
|
|
631
|
+
getWebSockets: (tag) => Effect.sync(() => state.getWebSockets(tag)),
|
|
632
|
+
setWebSocketAutoResponse: (pair) => Effect.sync(() => state.setWebSocketAutoResponse(pair)),
|
|
633
|
+
getWebSocketAutoResponse: Effect.sync(() => state.getWebSocketAutoResponse()),
|
|
634
|
+
getWebSocketAutoResponseTimestamp: (ws) => Effect.sync(() => state.getWebSocketAutoResponseTimestamp(ws)),
|
|
635
|
+
setHibernatableWebSocketEventTimeout: (timeoutMs) => Effect.sync(() => state.setHibernatableWebSocketEventTimeout(timeoutMs)),
|
|
636
|
+
getHibernatableWebSocketEventTimeout: Effect.sync(() => state.getHibernatableWebSocketEventTimeout()),
|
|
637
|
+
getTags: (ws) => Effect.sync(() => state.getTags(ws)),
|
|
638
|
+
abort: (reason) => Effect.sync(() => state.abort(reason))
|
|
639
|
+
});
|
|
640
|
+
const runPromiseExitPreservingTypedFailures = async (effect) => {
|
|
641
|
+
const exit = await Effect.runPromiseExit(effect);
|
|
642
|
+
if (Exit.isFailure(exit) && (Cause.hasDies(exit.cause) || Cause.hasInterrupts(exit.cause))) throw Cause.squash(exit.cause);
|
|
643
|
+
return exit;
|
|
644
|
+
};
|
|
645
|
+
//#endregion
|
|
646
|
+
//#region src/DurableObjectNamespace.ts
|
|
647
|
+
var DurableObjectNamespace_exports = /* @__PURE__ */ __exportAll({
|
|
648
|
+
DurableObjectFetchError: () => DurableObjectFetchError,
|
|
649
|
+
DurableObjectRpcError: () => DurableObjectRpcError,
|
|
650
|
+
Service: () => Service$1
|
|
651
|
+
});
|
|
652
|
+
const TypeId$1 = "effect-cf/DurableObjectNamespace";
|
|
653
|
+
/**
|
|
654
|
+
* Failure raised when invoking an RPC method on a Durable Object stub.
|
|
655
|
+
*/
|
|
656
|
+
var DurableObjectRpcError = class extends Data.TaggedError("DurableObjectRpcError") {};
|
|
657
|
+
/**
|
|
658
|
+
* Failure raised when forwarding a request to a Durable Object stub.
|
|
659
|
+
*/
|
|
660
|
+
var DurableObjectFetchError = class extends Data.TaggedError("DurableObjectFetchError") {};
|
|
661
|
+
/**
|
|
662
|
+
* Creates a typed Effect service for a Durable Object namespace binding.
|
|
663
|
+
*
|
|
664
|
+
* Returned value includes namespace helpers (`get`, `getByName`, `newUniqueId`),
|
|
665
|
+
* raw `fetch` / `call` helpers, and direct RPC helpers when `definition` is provided.
|
|
666
|
+
*
|
|
667
|
+
* @example
|
|
668
|
+
* ```ts
|
|
669
|
+
* const ChatRoom = DurableObjectDefinition.make("ChatRoom", {
|
|
670
|
+
* postMessage: DurableObjectDefinition.method({
|
|
671
|
+
* args: [Schema.String],
|
|
672
|
+
* success: Schema.Void,
|
|
673
|
+
* }),
|
|
674
|
+
* });
|
|
675
|
+
*
|
|
676
|
+
* const ChatRooms = ChatRoom.namespace("CHAT_ROOMS", { binding: "CHAT_ROOMS" });
|
|
677
|
+
*
|
|
678
|
+
* const program = Effect.gen(function* () {
|
|
679
|
+
* const room = ChatRooms.byName("general");
|
|
680
|
+
* yield* room.postMessage("hello");
|
|
681
|
+
* });
|
|
682
|
+
* ```
|
|
683
|
+
*/
|
|
684
|
+
const Service$1 = () => (id, definition) => {
|
|
685
|
+
const hasFunction = (value, key) => typeof Reflect.get(value, key) === "function";
|
|
686
|
+
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");
|
|
687
|
+
const tag = Service$3()(id, definition.binding, (value) => isDurableObjectNamespaceClient(value));
|
|
688
|
+
const newUniqueId = Effect.fnUntraced(function* (options) {
|
|
689
|
+
return (yield* tag).newUniqueId(options);
|
|
690
|
+
});
|
|
691
|
+
const idFromName = Effect.fnUntraced(function* (name) {
|
|
692
|
+
return (yield* tag).idFromName(name);
|
|
693
|
+
});
|
|
694
|
+
const idFromString = Effect.fnUntraced(function* (id) {
|
|
695
|
+
return (yield* tag).idFromString(id);
|
|
696
|
+
});
|
|
697
|
+
const get = Effect.fnUntraced(function* (id, options) {
|
|
698
|
+
return (yield* tag).get(id, options);
|
|
699
|
+
});
|
|
700
|
+
const getByName = Effect.fnUntraced(function* (name, options) {
|
|
701
|
+
return (yield* tag).getByName(name, options);
|
|
702
|
+
});
|
|
703
|
+
const jurisdiction = Effect.fnUntraced(function* (value) {
|
|
704
|
+
return (yield* tag).jurisdiction(value);
|
|
705
|
+
});
|
|
706
|
+
const fetch = (stub, input, init) => Effect.tryPromise({
|
|
707
|
+
try: () => stub.fetch(input, init),
|
|
708
|
+
catch: (cause) => new DurableObjectFetchError({
|
|
709
|
+
binding: definition.binding,
|
|
710
|
+
cause
|
|
711
|
+
})
|
|
712
|
+
});
|
|
713
|
+
const rpc = (stub, method, ...args) => Effect.gen(function* () {
|
|
714
|
+
const methodName = String(method);
|
|
715
|
+
return yield* invokeRpcMethod(stub, method, definition.definition === void 0 ? args : yield* encodeArgs(definition.definition, methodName, args).pipe(Effect.mapError((cause) => new DurableObjectRpcError({
|
|
716
|
+
binding: definition.binding,
|
|
717
|
+
method: methodName,
|
|
718
|
+
cause
|
|
719
|
+
}))), (cause) => new DurableObjectRpcError({
|
|
720
|
+
binding: definition.binding,
|
|
721
|
+
method: methodName,
|
|
722
|
+
cause
|
|
723
|
+
}));
|
|
724
|
+
});
|
|
725
|
+
const call = (stub, method, ...args) => Effect.gen(function* () {
|
|
726
|
+
const methodName = String(method);
|
|
727
|
+
const value = yield* resolve(yield* rpc(stub, method, ...args)).pipe(Effect.mapError((cause) => new DurableObjectRpcError({
|
|
728
|
+
binding: definition.binding,
|
|
729
|
+
method: methodName,
|
|
730
|
+
cause
|
|
731
|
+
})));
|
|
732
|
+
if (definition.definition === void 0) return value;
|
|
733
|
+
return yield* decodeSuccess(definition.definition, methodName, value).pipe(Effect.mapError((cause) => new DurableObjectRpcError({
|
|
734
|
+
binding: definition.binding,
|
|
735
|
+
method: methodName,
|
|
736
|
+
cause
|
|
737
|
+
})));
|
|
738
|
+
});
|
|
739
|
+
const scopedCall = (stub, method, ...args) => Effect.gen(function* () {
|
|
740
|
+
return yield* scoped(yield* rpc(stub, method, ...args));
|
|
741
|
+
});
|
|
742
|
+
const directMethods = makeDirectMethods(definition.definition, {
|
|
743
|
+
call,
|
|
744
|
+
fetch,
|
|
745
|
+
get,
|
|
746
|
+
getByName
|
|
747
|
+
});
|
|
748
|
+
return Object.assign(tag, directMethods, {
|
|
749
|
+
[TypeId$1]: TypeId$1,
|
|
750
|
+
definition,
|
|
751
|
+
newUniqueId,
|
|
752
|
+
idFromName,
|
|
753
|
+
idFromString,
|
|
754
|
+
get,
|
|
755
|
+
getByName,
|
|
756
|
+
jurisdiction,
|
|
757
|
+
fetch,
|
|
758
|
+
rpc,
|
|
759
|
+
call,
|
|
760
|
+
scopedCall
|
|
761
|
+
});
|
|
762
|
+
};
|
|
763
|
+
const makeDirectMethods = (rpcDefinition, helpers) => {
|
|
764
|
+
const methods = {};
|
|
765
|
+
if (rpcDefinition !== void 0) {
|
|
766
|
+
for (const methodName of Object.keys(rpcDefinition.methods)) methods[methodName] = (stub, ...args) => helpers.call(stub, methodName, ...args);
|
|
767
|
+
const makeClient = (getStub) => {
|
|
768
|
+
const client = { fetch: (input, init) => Effect.gen(function* () {
|
|
769
|
+
const stub = yield* getStub();
|
|
770
|
+
return yield* helpers.fetch(stub, input, init);
|
|
771
|
+
}) };
|
|
772
|
+
for (const methodName of Object.keys(rpcDefinition.methods)) client[methodName] = (...args) => Effect.gen(function* () {
|
|
773
|
+
const stub = yield* getStub();
|
|
774
|
+
return yield* helpers.call(stub, methodName, ...args);
|
|
775
|
+
});
|
|
776
|
+
return client;
|
|
777
|
+
};
|
|
778
|
+
methods.byName = (name, options) => makeClient(() => helpers.getByName(name, options));
|
|
779
|
+
methods.byId = (id, options) => makeClient(() => helpers.get(id, options));
|
|
780
|
+
}
|
|
781
|
+
return methods;
|
|
782
|
+
};
|
|
783
|
+
//#endregion
|
|
784
|
+
//#region src/DurableObjectDefinition.ts
|
|
785
|
+
var DurableObjectDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
786
|
+
DurableObject: () => DurableObject$1,
|
|
787
|
+
Tag: () => Tag$1,
|
|
788
|
+
implement: () => implement$1,
|
|
789
|
+
make: () => make$2,
|
|
790
|
+
method: () => method$1
|
|
791
|
+
});
|
|
792
|
+
const reservedMethodNames$1 = new Set([
|
|
793
|
+
"constructor",
|
|
794
|
+
"dup",
|
|
795
|
+
"fetch",
|
|
796
|
+
"alarm",
|
|
797
|
+
"webSocketMessage",
|
|
798
|
+
"webSocketClose",
|
|
799
|
+
"webSocketError"
|
|
800
|
+
]);
|
|
801
|
+
/**
|
|
802
|
+
* Defines a single RPC method schema in a Durable Object definition.
|
|
803
|
+
*/
|
|
804
|
+
const method$1 = method$4;
|
|
805
|
+
/**
|
|
806
|
+
* Creates a Durable Object RPC definition plus implementation/binding helpers.
|
|
807
|
+
*
|
|
808
|
+
* @example
|
|
809
|
+
* ```ts
|
|
810
|
+
* const ChatRoom = DurableObjectDefinition.make("ChatRoom", {
|
|
811
|
+
* postMessage: DurableObjectDefinition.method({
|
|
812
|
+
* args: [Schema.String],
|
|
813
|
+
* success: Schema.Void,
|
|
814
|
+
* }),
|
|
815
|
+
* });
|
|
816
|
+
* ```
|
|
817
|
+
*/
|
|
818
|
+
const makeDefinition = (id, methods) => {
|
|
819
|
+
assertNoReservedMethods("Durable Object", methods, reservedMethodNames$1);
|
|
820
|
+
const definition = make$5(id, methods);
|
|
821
|
+
return Object.assign(definition, {
|
|
822
|
+
make: (layer, options) => make$1(layer, {
|
|
823
|
+
...options,
|
|
824
|
+
rpc: wrapHandlers(definition, options.rpc)
|
|
825
|
+
}),
|
|
826
|
+
Namespace: () => (bindingId, binding) => Service$1()(bindingId, {
|
|
827
|
+
...binding,
|
|
828
|
+
definition
|
|
829
|
+
}),
|
|
830
|
+
namespace: (bindingId, binding) => Service$1()(bindingId, {
|
|
831
|
+
...binding,
|
|
832
|
+
definition
|
|
833
|
+
})
|
|
834
|
+
});
|
|
835
|
+
};
|
|
836
|
+
const make$2 = makeDefinition;
|
|
837
|
+
const Tag$1 = () => (id, methods) => {
|
|
838
|
+
const definition = makeDefinition(id, methods);
|
|
839
|
+
class DurableObjectDefinitionClass {
|
|
840
|
+
static id = definition.id;
|
|
841
|
+
static methods = definition.methods;
|
|
842
|
+
static make = definition.make;
|
|
843
|
+
static Namespace = definition.Namespace;
|
|
844
|
+
static namespace = definition.namespace;
|
|
845
|
+
}
|
|
846
|
+
return DurableObjectDefinitionClass;
|
|
847
|
+
};
|
|
848
|
+
const DurableObject$1 = Tag$1;
|
|
849
|
+
const wrapHandlers = (definition, handlers) => {
|
|
850
|
+
const wrapped = {};
|
|
851
|
+
for (const key of Object.keys(definition.methods)) {
|
|
852
|
+
const handler = handlers[key];
|
|
853
|
+
wrapped[key] = (...args) => Effect.gen(function* () {
|
|
854
|
+
return yield* encodeSuccess(definition, key, yield* handler(...yield* decodeArgs(definition, key, args)));
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
return wrapped;
|
|
858
|
+
};
|
|
859
|
+
/**
|
|
860
|
+
* Helper for implementing handlers with the exact method shape of a definition.
|
|
861
|
+
*/
|
|
862
|
+
const implement$1 = (_definition, handlers) => handlers;
|
|
863
|
+
//#endregion
|
|
864
|
+
//#region src/DurableObject.ts
|
|
865
|
+
var DurableObject_exports = /* @__PURE__ */ __exportAll({
|
|
866
|
+
Tag: () => Tag,
|
|
867
|
+
implement: () => implement,
|
|
868
|
+
make: () => make$1,
|
|
869
|
+
method: () => method
|
|
870
|
+
});
|
|
871
|
+
const reservedMethodNames = new Set([
|
|
872
|
+
"constructor",
|
|
873
|
+
"dup",
|
|
874
|
+
"fetch",
|
|
875
|
+
"alarm",
|
|
876
|
+
"webSocketMessage",
|
|
877
|
+
"webSocketClose",
|
|
878
|
+
"webSocketError"
|
|
879
|
+
]);
|
|
880
|
+
const RunSymbol = Symbol.for("effect-cf/DurableObject/run");
|
|
881
|
+
/**
|
|
882
|
+
* Creates a Durable Object class backed by a single managed Effect runtime.
|
|
883
|
+
*/
|
|
884
|
+
const make$1 = (layer, options = {}) => {
|
|
885
|
+
class EffectDurableObject extends DurableObject {
|
|
886
|
+
runtime;
|
|
887
|
+
constructor(state, env) {
|
|
888
|
+
super(state, env);
|
|
889
|
+
const runtimeLayer = provideEntrypointServices(layer, Layer.mergeAll(Layer.succeed(DurableObjectState, fromDurableObjectState(state)), Layer.succeed(WorkerEnvironment, env)));
|
|
890
|
+
this.runtime = ManagedRuntime.make(runtimeLayer);
|
|
891
|
+
}
|
|
892
|
+
[RunSymbol](effect) {
|
|
893
|
+
return this.runtime.runPromise(Effect.scoped(effect));
|
|
894
|
+
}
|
|
895
|
+
fetch(request) {
|
|
896
|
+
const fetchHandler = options.fetch;
|
|
897
|
+
if (fetchHandler === void 0) return Promise.resolve(new Response("Not Found", { status: 404 }));
|
|
898
|
+
return this[RunSymbol](Effect.provideService(fetchHandler, NativeRequest, request));
|
|
899
|
+
}
|
|
900
|
+
alarm(alarmInfo) {
|
|
901
|
+
if (options.alarm !== void 0) return this[RunSymbol](options.alarm(alarmInfo));
|
|
902
|
+
}
|
|
903
|
+
webSocketMessage(socket, message) {
|
|
904
|
+
if (options.webSocketMessage !== void 0) return this[RunSymbol](options.webSocketMessage(socket, message));
|
|
905
|
+
}
|
|
906
|
+
webSocketClose(socket, code, reason, wasClean) {
|
|
907
|
+
if (options.webSocketClose !== void 0) return this[RunSymbol](options.webSocketClose(socket, code, reason, wasClean));
|
|
908
|
+
}
|
|
909
|
+
webSocketError(socket, error) {
|
|
910
|
+
if (options.webSocketError !== void 0) return this[RunSymbol](options.webSocketError(socket, error));
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
defineEntrypointRpcMethods("Durable Object", EffectDurableObject.prototype, options.rpc, reservedMethodNames, (self, effect) => self[RunSymbol](effect));
|
|
914
|
+
return assumeEntrypointClass(EffectDurableObject);
|
|
915
|
+
};
|
|
916
|
+
const Tag = Tag$1;
|
|
917
|
+
const method = method$1;
|
|
918
|
+
const implement = implement$1;
|
|
919
|
+
//#endregion
|
|
920
|
+
//#region src/DurableObjectRpcWebSocket.ts
|
|
921
|
+
var DurableObjectRpcWebSocket_exports = /* @__PURE__ */ __exportAll({
|
|
922
|
+
DurableObjectRpcWebSocket: () => DurableObjectRpcWebSocket,
|
|
923
|
+
layer: () => layer
|
|
924
|
+
});
|
|
925
|
+
const defaultAttachmentKey = "effectCloudflareRpcClientId";
|
|
926
|
+
const defaultTag = "effect-cf-rpc";
|
|
927
|
+
/**
|
|
928
|
+
* Context tag for the Durable Object RPC websocket service.
|
|
929
|
+
*/
|
|
930
|
+
var DurableObjectRpcWebSocket = class extends Context.Service()("effect-cf/DurableObjectRpcWebSocket") {};
|
|
931
|
+
/**
|
|
932
|
+
* Builds a layer that bridges Durable Object websocket events to `RpcServer.Protocol`.
|
|
933
|
+
*/
|
|
934
|
+
const layer = (options = {}) => Layer.effectContext(Effect.gen(function* () {
|
|
935
|
+
const tag = options.tag ?? defaultTag;
|
|
936
|
+
const attachmentKey = options.attachmentKey ?? defaultAttachmentKey;
|
|
937
|
+
const durableObjectState = yield* DurableObjectState;
|
|
938
|
+
const serialization = yield* RpcSerialization.RpcSerialization;
|
|
939
|
+
const disconnects = yield* Queue.make();
|
|
940
|
+
const connectionsBySocket = /* @__PURE__ */ new Map();
|
|
941
|
+
const connectionsById = /* @__PURE__ */ new Map();
|
|
942
|
+
const clientIds = /* @__PURE__ */ new Set();
|
|
943
|
+
let nextClientId = 0;
|
|
944
|
+
let writeRequest;
|
|
945
|
+
const reserveClientId = (socket) => {
|
|
946
|
+
const attachment = readAttachment(socket, attachmentKey);
|
|
947
|
+
if (attachment !== void 0) {
|
|
948
|
+
nextClientId = Math.max(nextClientId, attachment + 1);
|
|
949
|
+
return attachment;
|
|
950
|
+
}
|
|
951
|
+
const id = nextClientId++;
|
|
952
|
+
writeAttachment(socket, attachmentKey, id);
|
|
953
|
+
return id;
|
|
954
|
+
};
|
|
955
|
+
const register = (socket) => {
|
|
956
|
+
const existing = connectionsBySocket.get(socket);
|
|
957
|
+
if (existing !== void 0) return existing;
|
|
958
|
+
const connection = {
|
|
959
|
+
id: reserveClientId(socket),
|
|
960
|
+
socket,
|
|
961
|
+
parser: serialization.makeUnsafe()
|
|
962
|
+
};
|
|
963
|
+
connectionsBySocket.set(socket, connection);
|
|
964
|
+
connectionsById.set(connection.id, connection);
|
|
965
|
+
clientIds.add(connection.id);
|
|
966
|
+
return connection;
|
|
967
|
+
};
|
|
968
|
+
const unregister = (socket) => Effect.sync(() => {
|
|
969
|
+
const connection = connectionsBySocket.get(socket);
|
|
970
|
+
if (connection === void 0) return;
|
|
971
|
+
connectionsBySocket.delete(socket);
|
|
972
|
+
connectionsById.delete(connection.id);
|
|
973
|
+
clientIds.delete(connection.id);
|
|
974
|
+
Queue.offerUnsafe(disconnects, connection.id);
|
|
975
|
+
});
|
|
976
|
+
for (const socket of yield* durableObjectState.getWebSockets(tag)) register(socket);
|
|
977
|
+
const send = (connection, response) => Effect.sync(() => {
|
|
978
|
+
try {
|
|
979
|
+
const encoded = connection.parser.encode(response);
|
|
980
|
+
if (encoded !== void 0) connection.socket.send(encoded);
|
|
981
|
+
} catch (cause) {
|
|
982
|
+
const encoded = connection.parser.encode(RpcMessage.ResponseDefectEncoded(cause));
|
|
983
|
+
if (encoded !== void 0) connection.socket.send(encoded);
|
|
984
|
+
}
|
|
985
|
+
});
|
|
986
|
+
const protocol = yield* RpcServer.Protocol.make((writeRequest_) => {
|
|
987
|
+
writeRequest = writeRequest_;
|
|
988
|
+
return Effect.succeed({
|
|
989
|
+
disconnects,
|
|
990
|
+
send: (clientId, response) => {
|
|
991
|
+
const connection = connectionsById.get(clientId);
|
|
992
|
+
return connection === void 0 ? Effect.void : send(connection, response);
|
|
993
|
+
},
|
|
994
|
+
end: (clientId) => Effect.sync(() => {
|
|
995
|
+
connectionsById.get(clientId)?.socket.close();
|
|
996
|
+
}),
|
|
997
|
+
clientIds: Effect.sync(() => clientIds),
|
|
998
|
+
initialMessage: Effect.succeed(Option.none()),
|
|
999
|
+
supportsAck: true,
|
|
1000
|
+
supportsTransferables: false,
|
|
1001
|
+
supportsSpanPropagation: true
|
|
1002
|
+
});
|
|
1003
|
+
});
|
|
1004
|
+
const service = DurableObjectRpcWebSocket.of({
|
|
1005
|
+
accept: (socket) => Effect.gen(function* () {
|
|
1006
|
+
register(socket);
|
|
1007
|
+
yield* durableObjectState.acceptWebSocket(socket, [tag]);
|
|
1008
|
+
}),
|
|
1009
|
+
message: (socket, message) => Effect.gen(function* () {
|
|
1010
|
+
const connection = register(socket);
|
|
1011
|
+
const decoded = yield* Effect.try({
|
|
1012
|
+
try: () => connection.parser.decode(normalizeMessage(message)),
|
|
1013
|
+
catch: RpcMessage.ResponseDefectEncoded
|
|
1014
|
+
});
|
|
1015
|
+
const run = writeRequest;
|
|
1016
|
+
if (run === void 0) {
|
|
1017
|
+
yield* send(connection, RpcMessage.ResponseDefectEncoded("RPC server is not ready"));
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
for (const current of decoded) yield* run(connection.id, current);
|
|
1021
|
+
}).pipe(Effect.catch((error) => {
|
|
1022
|
+
return send(register(socket), error);
|
|
1023
|
+
})),
|
|
1024
|
+
close: unregister,
|
|
1025
|
+
error: (socket, error) => Effect.gen(function* () {
|
|
1026
|
+
yield* Effect.logDebug("Durable Object RPC websocket error", error);
|
|
1027
|
+
yield* unregister(socket);
|
|
1028
|
+
})
|
|
1029
|
+
});
|
|
1030
|
+
return Context.mergeAll(Context.make(RpcServer.Protocol, protocol), Context.make(DurableObjectRpcWebSocket, service));
|
|
1031
|
+
}));
|
|
1032
|
+
const normalizeMessage = (message) => typeof message === "string" ? message : new Uint8Array(message);
|
|
1033
|
+
const readAttachment = (socket, key) => {
|
|
1034
|
+
const value = socket.deserializeAttachment();
|
|
1035
|
+
if (value !== null && typeof value === "object" && key in value && typeof value[key] === "number") return value[key];
|
|
1036
|
+
};
|
|
1037
|
+
const writeAttachment = (socket, key, clientId) => {
|
|
1038
|
+
const current = socket.deserializeAttachment();
|
|
1039
|
+
const attachment = current !== null && typeof current === "object" && !Array.isArray(current) ? current : {};
|
|
1040
|
+
socket.serializeAttachment({
|
|
1041
|
+
...attachment,
|
|
1042
|
+
[key]: clientId
|
|
1043
|
+
});
|
|
1044
|
+
};
|
|
1045
|
+
//#endregion
|
|
1046
|
+
//#region src/DurableObjectWebSocket.ts
|
|
1047
|
+
var DurableObjectWebSocket_exports = /* @__PURE__ */ __exportAll({ acceptUpgrade: () => acceptUpgrade });
|
|
1048
|
+
/**
|
|
1049
|
+
* Accepts a websocket upgrade and registers the server socket on `DurableObjectState`.
|
|
1050
|
+
*
|
|
1051
|
+
* @example
|
|
1052
|
+
* ```ts
|
|
1053
|
+
* const response = yield* DurableObjectWebSocket.acceptUpgrade({
|
|
1054
|
+
* tags: ["room:general"],
|
|
1055
|
+
* });
|
|
1056
|
+
*
|
|
1057
|
+
* return response.response;
|
|
1058
|
+
* ```
|
|
1059
|
+
*/
|
|
1060
|
+
const acceptUpgrade = (options = {}) => Effect.gen(function* () {
|
|
1061
|
+
const state = yield* DurableObjectState;
|
|
1062
|
+
const pair = new WebSocketPair();
|
|
1063
|
+
const client = pair[0];
|
|
1064
|
+
const server = pair[1];
|
|
1065
|
+
if (options.attachment !== void 0) server.serializeAttachment(options.attachment);
|
|
1066
|
+
yield* state.acceptWebSocket(server, options.tags === void 0 ? void 0 : [...options.tags]);
|
|
1067
|
+
return {
|
|
1068
|
+
client,
|
|
1069
|
+
server,
|
|
1070
|
+
response: new Response(null, {
|
|
1071
|
+
status: 101,
|
|
1072
|
+
webSocket: client
|
|
1073
|
+
})
|
|
1074
|
+
};
|
|
1075
|
+
});
|
|
1076
|
+
//#endregion
|
|
1077
|
+
//#region src/Kv.ts
|
|
1078
|
+
var Kv_exports = /* @__PURE__ */ __exportAll({
|
|
1079
|
+
KvOperationError: () => KvOperationError,
|
|
1080
|
+
Service: () => Service,
|
|
1081
|
+
make: () => make
|
|
1082
|
+
});
|
|
1083
|
+
const TypeId = "effect-cf/Kv";
|
|
1084
|
+
/** Error raised when a KV operation fails. */
|
|
1085
|
+
var KvOperationError = class extends Data.TaggedError("KvOperationError") {};
|
|
1086
|
+
const maybeString = (value) => value == null ? Option.none() : Option.some(value);
|
|
1087
|
+
const maybeNumber = (value) => value === void 0 ? Option.none() : Option.some(value);
|
|
1088
|
+
const kvError = (binding, operation, cause) => new KvOperationError({
|
|
1089
|
+
binding,
|
|
1090
|
+
operation,
|
|
1091
|
+
cause
|
|
1092
|
+
});
|
|
1093
|
+
const tryKvPromise = (binding, operation, evaluate) => Effect.tryPromise({
|
|
1094
|
+
try: evaluate,
|
|
1095
|
+
catch: (cause) => kvError(binding, operation, cause)
|
|
1096
|
+
});
|
|
1097
|
+
/**
|
|
1098
|
+
* Creates a typed KV service tag plus Effect helpers.
|
|
1099
|
+
*/
|
|
1100
|
+
const make = (id, definition) => Service()(id, definition);
|
|
1101
|
+
/**
|
|
1102
|
+
* Builds a KV service around a Cloudflare KV namespace binding.
|
|
1103
|
+
*
|
|
1104
|
+
* Returned service includes schema-aware `put`, `get`, `getWithMetadata`,
|
|
1105
|
+
* `list`, and `remove` helpers.
|
|
1106
|
+
*
|
|
1107
|
+
* @example
|
|
1108
|
+
* ```ts
|
|
1109
|
+
* const Sessions = Kv.make("Sessions", {
|
|
1110
|
+
* binding: "SESSIONS",
|
|
1111
|
+
* key: Schema.String,
|
|
1112
|
+
* value: Schema.Struct({ userId: Schema.String }),
|
|
1113
|
+
* });
|
|
1114
|
+
*
|
|
1115
|
+
* const program = Effect.gen(function* () {
|
|
1116
|
+
* yield* Sessions.put("abc", { userId: "u_1" });
|
|
1117
|
+
* return yield* Sessions.get("abc");
|
|
1118
|
+
* });
|
|
1119
|
+
* ```
|
|
1120
|
+
*/
|
|
1121
|
+
const Service = () => (id, definition) => {
|
|
1122
|
+
const tag = Service$3()(id, definition.binding, (value) => {
|
|
1123
|
+
if (typeof value !== "object" || value === null) return false;
|
|
1124
|
+
const resource = value;
|
|
1125
|
+
return typeof resource.get === "function" && typeof resource.put === "function" && typeof resource.delete === "function" && typeof resource.getWithMetadata === "function" && typeof resource.list === "function";
|
|
1126
|
+
});
|
|
1127
|
+
const encodeKey = Schema.encodeEffect(definition.key);
|
|
1128
|
+
const decodeKey = Schema.decodeUnknownEffect(definition.key);
|
|
1129
|
+
const encodeValue = Schema.encodeEffect(Schema.fromJsonString(Schema.toCodecJson(definition.value)));
|
|
1130
|
+
const decodeValue = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.toCodecJson(definition.value)));
|
|
1131
|
+
const put = Effect.fnUntraced(function* (key, value, options) {
|
|
1132
|
+
const kv = yield* tag;
|
|
1133
|
+
const keyEncoded = yield* encodeKey(key);
|
|
1134
|
+
const valueEncoded = yield* encodeValue(value);
|
|
1135
|
+
yield* tryKvPromise(definition.binding, "put", () => kv.put(keyEncoded, valueEncoded, options));
|
|
1136
|
+
});
|
|
1137
|
+
const get = Effect.fnUntraced(function* (key) {
|
|
1138
|
+
const kv = yield* tag;
|
|
1139
|
+
const keyEncoded = yield* encodeKey(key);
|
|
1140
|
+
const valueEncoded = yield* tryKvPromise(definition.binding, "get", () => kv.get(keyEncoded));
|
|
1141
|
+
if (valueEncoded === null) return Option.none();
|
|
1142
|
+
return yield* decodeValue(valueEncoded).pipe(Effect.map(Option.some));
|
|
1143
|
+
});
|
|
1144
|
+
const getWithMetadata = Effect.fnUntraced(function* (key, metadataSchema) {
|
|
1145
|
+
const kv = yield* tag;
|
|
1146
|
+
const keyEncoded = yield* encodeKey(key);
|
|
1147
|
+
const result = yield* tryKvPromise(definition.binding, "getWithMetadata", () => kv.getWithMetadata(keyEncoded));
|
|
1148
|
+
if (result.value === null) return Option.none();
|
|
1149
|
+
const value = yield* decodeValue(result.value);
|
|
1150
|
+
const metadata = result.metadata === null ? Option.none() : Option.some(yield* Schema.decodeUnknownEffect(metadataSchema)(result.metadata));
|
|
1151
|
+
return Option.some({
|
|
1152
|
+
value,
|
|
1153
|
+
metadata,
|
|
1154
|
+
cacheStatus: maybeString(result.cacheStatus)
|
|
1155
|
+
});
|
|
1156
|
+
});
|
|
1157
|
+
const list = Effect.fnUntraced(function* (options) {
|
|
1158
|
+
const kv = yield* tag;
|
|
1159
|
+
const { metadataSchema, ...kvOptions } = options ?? {};
|
|
1160
|
+
const result = yield* tryKvPromise(definition.binding, "list", () => kv.list(kvOptions));
|
|
1161
|
+
const keys = [];
|
|
1162
|
+
for (const key of result.keys) {
|
|
1163
|
+
const decodedName = yield* decodeKey(key.name);
|
|
1164
|
+
const decodedMetadata = key.metadata === void 0 ? Option.none() : metadataSchema === void 0 ? Option.some(key.metadata) : Option.some(yield* Schema.decodeUnknownEffect(metadataSchema)(key.metadata));
|
|
1165
|
+
keys.push({
|
|
1166
|
+
name: decodedName,
|
|
1167
|
+
expiration: maybeNumber(key.expiration),
|
|
1168
|
+
metadata: decodedMetadata
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
return {
|
|
1172
|
+
keys,
|
|
1173
|
+
listComplete: result.list_complete,
|
|
1174
|
+
cursor: maybeString("cursor" in result ? result.cursor : void 0),
|
|
1175
|
+
cacheStatus: maybeString(result.cacheStatus)
|
|
1176
|
+
};
|
|
1177
|
+
});
|
|
1178
|
+
const remove = Effect.fnUntraced(function* (key) {
|
|
1179
|
+
const kv = yield* tag;
|
|
1180
|
+
const keyEncoded = yield* encodeKey(key);
|
|
1181
|
+
yield* tryKvPromise(definition.binding, "delete", () => kv.delete(keyEncoded));
|
|
1182
|
+
});
|
|
1183
|
+
const unsafeRaw = Effect.fnUntraced(function* () {
|
|
1184
|
+
return yield* tag;
|
|
1185
|
+
});
|
|
1186
|
+
return Object.assign(tag, {
|
|
1187
|
+
[TypeId]: TypeId,
|
|
1188
|
+
definition,
|
|
1189
|
+
put,
|
|
1190
|
+
get,
|
|
1191
|
+
getWithMetadata,
|
|
1192
|
+
list,
|
|
1193
|
+
remove,
|
|
1194
|
+
unsafeRaw
|
|
1195
|
+
});
|
|
1196
|
+
};
|
|
1197
|
+
//#endregion
|
|
1198
|
+
export { Binding_exports as Binding, DurableObject_exports as DurableObject, 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, Rpc_exports as Rpc, RpcDefinition_exports as RpcDefinition, ServiceBinding_exports as ServiceBinding, Worker_exports as Worker, WorkerConfig, WorkerDefinition_exports as WorkerDefinition, WorkerEnvironment };
|