effect-cf 0.12.0 → 0.13.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 +8 -0
- package/dist/index.d.mts +1085 -1085
- package/dist/index.mjs +1382 -1432
- package/package.json +1 -1
- package/src/CloudflareOtlp.ts +0 -112
- package/src/DurableObject.ts +62 -21
- package/src/DurableObjectDefinition.ts +19 -9
- package/src/Worker.ts +88 -29
- package/src/WorkerDefinition.ts +16 -8
package/dist/index.mjs
CHANGED
|
@@ -3,1192 +3,1168 @@ import { a as WorkerConfig, i as layer$10, n as Binding_exports, o as WorkerEnvi
|
|
|
3
3
|
import { Cause, Clock, Config, ConfigProvider, Context, Data, DateTime, Duration, Effect, Exit, Layer, ManagedRuntime, Option, Queue, Schema } from "effect";
|
|
4
4
|
import { FetchHttpClient, HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
|
|
5
5
|
import { Otlp, OtlpLogger, OtlpMetrics, OtlpSerialization, OtlpTracer } from "effect/unstable/observability";
|
|
6
|
-
import { DurableObject, RpcStub, RpcTarget, WorkerEntrypoint, WorkflowEntrypoint } from "cloudflare:workers";
|
|
7
6
|
import { D1Client } from "@effect/sql-d1";
|
|
7
|
+
import { DurableObject, RpcStub, RpcTarget, WorkerEntrypoint, WorkflowEntrypoint } from "cloudflare:workers";
|
|
8
8
|
import * as RpcMessage from "effect/unstable/rpc/RpcMessage";
|
|
9
9
|
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
|
|
10
10
|
import * as RpcServer from "effect/unstable/rpc/RpcServer";
|
|
11
11
|
import { SqliteClient } from "@effect/sql-sqlite-do";
|
|
12
|
-
//#region src/
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
layer: () => layer$9,
|
|
17
|
-
makeClient: () => makeClient$6
|
|
12
|
+
//#region src/DurableObjectStorage.ts
|
|
13
|
+
var DurableObjectStorage_exports = /* @__PURE__ */ __exportAll({
|
|
14
|
+
StorageOperationError: () => StorageOperationError,
|
|
15
|
+
fromDurableObjectStorage: () => fromDurableObjectStorage
|
|
18
16
|
});
|
|
19
|
-
|
|
20
|
-
var
|
|
21
|
-
const
|
|
17
|
+
/** Error type used when a storage operation throws or rejects. */
|
|
18
|
+
var StorageOperationError = class extends Data.TaggedError("StorageOperationError") {};
|
|
19
|
+
const storageError = (operation, cause) => new StorageOperationError({
|
|
20
|
+
operation,
|
|
21
|
+
cause
|
|
22
|
+
});
|
|
23
|
+
const tryStorageSync = (operation, evaluate) => Effect.try({
|
|
22
24
|
try: evaluate,
|
|
23
|
-
catch: (cause) =>
|
|
24
|
-
binding,
|
|
25
|
-
operation,
|
|
26
|
-
cause,
|
|
27
|
-
message: `Cloudflare queue binding "${binding}" operation "${operation}" failed`
|
|
28
|
-
})
|
|
25
|
+
catch: (cause) => storageError(operation, cause)
|
|
29
26
|
});
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
27
|
+
const tryStoragePromise = (operation, evaluate) => Effect.tryPromise({
|
|
28
|
+
try: evaluate,
|
|
29
|
+
catch: (cause) => storageError(operation, cause)
|
|
30
|
+
});
|
|
31
|
+
const fromSqlCursor = (cursor) => ({
|
|
32
|
+
next: () => tryStorageSync("sql.next", () => cursor.next()),
|
|
33
|
+
toArray: () => tryStorageSync("sql.toArray", () => cursor.toArray()),
|
|
34
|
+
one: () => tryStorageSync("sql.one", () => cursor.one()),
|
|
35
|
+
raw: () => tryStorageSync("sql.raw", () => cursor.raw()),
|
|
36
|
+
get columnNames() {
|
|
37
|
+
return cursor.columnNames;
|
|
38
|
+
},
|
|
39
|
+
rowsRead: tryStorageSync("sql.rowsRead", () => cursor.rowsRead),
|
|
40
|
+
rowsWritten: tryStorageSync("sql.rowsWritten", () => cursor.rowsWritten)
|
|
41
|
+
});
|
|
42
|
+
const fromSqlStorage = (sql) => ({
|
|
43
|
+
exec: (query, ...bindings) => tryStorageSync("sql.exec", () => fromSqlCursor(sql.exec(query, ...bindings))),
|
|
44
|
+
get databaseSize() {
|
|
45
|
+
return sql.databaseSize;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
const schemaBackedSyncKvStorage = (kv, definition) => {
|
|
49
|
+
const encodeKey = Schema.encodeEffect(definition.key);
|
|
50
|
+
const decodeKey = Schema.decodeUnknownEffect(definition.key);
|
|
51
|
+
const encodeValue = Schema.encodeEffect(definition.value);
|
|
52
|
+
const decodeValue = Schema.decodeUnknownEffect(definition.value);
|
|
53
|
+
return {
|
|
54
|
+
get: (key) => Effect.gen(function* () {
|
|
55
|
+
const encodedKey = yield* encodeKey(key);
|
|
56
|
+
const encodedValue = yield* tryStorageSync("kv.get", () => kv.get(encodedKey));
|
|
57
|
+
if (encodedValue === void 0) return Option.none();
|
|
58
|
+
return yield* decodeValue(encodedValue).pipe(Effect.map(Option.some));
|
|
40
59
|
}),
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
body: yield* encodeMessage(message.body)
|
|
46
|
-
});
|
|
47
|
-
const sendBatch = queue.sendBatch;
|
|
48
|
-
if (sendBatch !== void 0) {
|
|
49
|
-
yield* tryQueuePromise(definition.binding, "sendBatch", () => sendBatch.call(queue, encodedMessages, options));
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
yield* tryQueuePromise(definition.binding, "sendBatch", async () => {
|
|
53
|
-
for (const message of encodedMessages) await queue.send(message.body, {
|
|
54
|
-
contentType: message.contentType,
|
|
55
|
-
delaySeconds: message.delaySeconds ?? options?.delaySeconds
|
|
56
|
-
});
|
|
57
|
-
});
|
|
60
|
+
put: (key, value) => Effect.gen(function* () {
|
|
61
|
+
const encodedKey = yield* encodeKey(key);
|
|
62
|
+
const encodedValue = yield* encodeValue(value);
|
|
63
|
+
yield* tryStorageSync("kv.put", () => kv.put(encodedKey, encodedValue));
|
|
58
64
|
}),
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return
|
|
68
|
-
}
|
|
69
|
-
unsafeRaw: Effect.succeed(queue)
|
|
70
|
-
});
|
|
71
|
-
};
|
|
72
|
-
const layer$9 = (tag, definition) => layer$10(tag, definition.binding, (value) => isQueue(value), makeClient$6(definition), { expected: expectedQueueProducer });
|
|
73
|
-
//#endregion
|
|
74
|
-
//#region src/QueueDefinition.ts
|
|
75
|
-
var QueueDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
76
|
-
Queue: () => Queue$1,
|
|
77
|
-
Tag: () => Tag$10,
|
|
78
|
-
implement: () => implement$7,
|
|
79
|
-
make: () => make$10
|
|
80
|
-
});
|
|
81
|
-
const makeDefinition$4 = (id, definition) => {
|
|
82
|
-
const queueDefinition = {
|
|
83
|
-
id,
|
|
84
|
-
message: definition.message
|
|
65
|
+
delete: (key) => Effect.gen(function* () {
|
|
66
|
+
const encodedKey = yield* encodeKey(key);
|
|
67
|
+
return yield* tryStorageSync("kv.delete", () => kv.delete(encodedKey));
|
|
68
|
+
}),
|
|
69
|
+
list: (options) => Effect.gen(function* () {
|
|
70
|
+
const entries = Array.from(yield* tryStorageSync("kv.list", () => kv.list(options)));
|
|
71
|
+
const decoded = [];
|
|
72
|
+
for (const [key, value] of entries) decoded.push([yield* decodeKey(key), yield* decodeValue(value)]);
|
|
73
|
+
return decoded;
|
|
74
|
+
})
|
|
85
75
|
};
|
|
86
|
-
return Object.assign(queueDefinition, { make: (layer, options) => make$7(layer, {
|
|
87
|
-
...options,
|
|
88
|
-
queue: wrapHandler$1(queueDefinition, options.queue)
|
|
89
|
-
}) });
|
|
90
|
-
};
|
|
91
|
-
const make$10 = (id, definition) => Tag$10()(id, definition);
|
|
92
|
-
const Tag$10 = () => (id, definition) => {
|
|
93
|
-
const queueDefinition = makeDefinition$4(id, definition);
|
|
94
|
-
const tag = Context.Service()(id);
|
|
95
|
-
const layer = (binding) => layer$9(tag, {
|
|
96
|
-
...binding,
|
|
97
|
-
message: definition.message
|
|
98
|
-
});
|
|
99
|
-
const send = Effect.fnUntraced(function* (message, options) {
|
|
100
|
-
yield* (yield* tag).send(message, options);
|
|
101
|
-
});
|
|
102
|
-
const sendBatch = Effect.fnUntraced(function* (messages, options) {
|
|
103
|
-
yield* (yield* tag).sendBatch(messages, options);
|
|
104
|
-
});
|
|
105
|
-
const metrics = Effect.fnUntraced(function* () {
|
|
106
|
-
return yield* (yield* tag).metrics();
|
|
107
|
-
});
|
|
108
|
-
const unsafeRaw = Effect.fnUntraced(function* () {
|
|
109
|
-
return yield* (yield* tag).unsafeRaw;
|
|
110
|
-
});
|
|
111
|
-
return Object.assign(tag, {
|
|
112
|
-
id: queueDefinition.id,
|
|
113
|
-
message: queueDefinition.message,
|
|
114
|
-
make: queueDefinition.make,
|
|
115
|
-
layer,
|
|
116
|
-
send,
|
|
117
|
-
sendBatch,
|
|
118
|
-
metrics,
|
|
119
|
-
unsafeRaw
|
|
120
|
-
});
|
|
121
|
-
};
|
|
122
|
-
const Queue$1 = Tag$10;
|
|
123
|
-
const wrapHandler$1 = (definition, handler) => {
|
|
124
|
-
const decodeBody = Schema.decodeUnknownEffect(definition.message);
|
|
125
|
-
return (batch) => Effect.gen(function* () {
|
|
126
|
-
yield* handler(yield* decodeBatch(batch.raw, decodeBody));
|
|
127
|
-
});
|
|
128
76
|
};
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
decodeBatch: () => decodeBatch,
|
|
136
|
-
fromMessage: () => fromMessage,
|
|
137
|
-
fromMessageBatch: () => fromMessageBatch,
|
|
138
|
-
implement: () => implement$6
|
|
77
|
+
const fromSyncKvStorage = (kv) => ({
|
|
78
|
+
get: (key) => tryStorageSync("kv.get", () => kv.get(key)),
|
|
79
|
+
put: (key, value) => tryStorageSync("kv.put", () => kv.put(key, value)),
|
|
80
|
+
delete: (key) => tryStorageSync("kv.delete", () => kv.delete(key)),
|
|
81
|
+
list: (options) => tryStorageSync("kv.list", () => Array.from(kv.list(options))),
|
|
82
|
+
schema: (definition) => schemaBackedSyncKvStorage(kv, definition)
|
|
139
83
|
});
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
84
|
+
const fromDurableObjectTransaction = (txn) => ({
|
|
85
|
+
get: (keyOrKeys, options) => Array.isArray(keyOrKeys) ? tryStoragePromise("transaction.get", () => txn.get(keyOrKeys, options)) : tryStoragePromise("transaction.get", () => txn.get(keyOrKeys, options)),
|
|
86
|
+
list: (options) => tryStoragePromise("transaction.list", () => txn.list(options)),
|
|
87
|
+
put: (keyOrEntries, valueOrOptions, maybeOptions) => tryStoragePromise("transaction.put", () => typeof keyOrEntries === "string" ? txn.put(keyOrEntries, valueOrOptions, maybeOptions) : txn.put(keyOrEntries, valueOrOptions)),
|
|
88
|
+
delete: (keyOrKeys, options) => Array.isArray(keyOrKeys) ? tryStoragePromise("transaction.delete", () => txn.delete(keyOrKeys, options)) : tryStoragePromise("transaction.delete", () => txn.delete(keyOrKeys, options)),
|
|
89
|
+
rollback: () => tryStorageSync("transaction.rollback", () => txn.rollback()),
|
|
90
|
+
getAlarm: (options) => tryStoragePromise("transaction.getAlarm", () => txn.getAlarm(options)),
|
|
91
|
+
setAlarm: (scheduledTime, options) => tryStoragePromise("transaction.setAlarm", () => txn.setAlarm(scheduledTime, options)),
|
|
92
|
+
deleteAlarm: (options) => tryStoragePromise("transaction.deleteAlarm", () => txn.deleteAlarm(options))
|
|
149
93
|
});
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Wraps native Cloudflare storage APIs as Effect-returning helpers.
|
|
96
|
+
*/
|
|
97
|
+
const fromDurableObjectStorage = (storage) => ({
|
|
98
|
+
get: (key, options) => tryStoragePromise("get", () => storage.get(key, options)),
|
|
99
|
+
put: (key, value, options) => tryStoragePromise("put", () => storage.put(key, value, options)),
|
|
100
|
+
delete: (key, options) => tryStoragePromise("delete", () => storage.delete(key, options)),
|
|
101
|
+
deleteAll: (options) => tryStoragePromise("deleteAll", () => storage.deleteAll(options)),
|
|
102
|
+
getAlarm: (options) => tryStoragePromise("getAlarm", () => storage.getAlarm(options)),
|
|
103
|
+
setAlarm: (scheduledTime, options) => tryStoragePromise("setAlarm", () => storage.setAlarm(scheduledTime, options)),
|
|
104
|
+
deleteAlarm: (options) => tryStoragePromise("deleteAlarm", () => storage.deleteAlarm(options)),
|
|
105
|
+
transactionSync: (closure) => Effect.context().pipe(Effect.flatMap((context) => Effect.suspend(() => {
|
|
106
|
+
try {
|
|
107
|
+
return Effect.succeed(storage.transactionSync(() => {
|
|
108
|
+
const exit = Effect.runSyncExitWith(context)(closure());
|
|
109
|
+
if (Exit.isSuccess(exit)) return exit.value;
|
|
110
|
+
throw exit;
|
|
111
|
+
}));
|
|
112
|
+
} catch (cause) {
|
|
113
|
+
if (Exit.isExit(cause) && Exit.isFailure(cause)) return Effect.failCause(cause.cause);
|
|
114
|
+
return Effect.fail(storageError("transactionSync", cause));
|
|
115
|
+
}
|
|
116
|
+
}))),
|
|
117
|
+
transaction: (closure) => Effect.context().pipe(Effect.flatMap((context) => Effect.callback((resume) => {
|
|
118
|
+
storage.transaction(async (txn) => {
|
|
119
|
+
const exit = await Effect.runPromiseExitWith(context)(closure(fromDurableObjectTransaction(txn)));
|
|
120
|
+
if (Exit.isSuccess(exit)) return exit.value;
|
|
121
|
+
throw exit;
|
|
122
|
+
}).then((value) => resume(Effect.succeed(value)), (cause) => {
|
|
123
|
+
if (Exit.isExit(cause) && Exit.isFailure(cause)) resume(Effect.failCause(cause.cause));
|
|
124
|
+
else resume(Effect.fail(storageError("transaction", cause)));
|
|
125
|
+
});
|
|
126
|
+
}))),
|
|
127
|
+
sync: () => tryStoragePromise("sync", () => storage.sync()),
|
|
128
|
+
getCurrentBookmark: () => tryStoragePromise("getCurrentBookmark", () => storage.getCurrentBookmark()),
|
|
129
|
+
onNextSessionRestoreBookmark: (bookmark) => tryStoragePromise("onNextSessionRestoreBookmark", () => storage.onNextSessionRestoreBookmark(bookmark)),
|
|
130
|
+
sql: fromSqlStorage(storage.sql),
|
|
131
|
+
kv: fromSyncKvStorage(storage.kv)
|
|
157
132
|
});
|
|
158
|
-
const decodeBatch = (batch, decodeBody) => Effect.gen(function* () {
|
|
159
|
-
const messages = [];
|
|
160
|
-
for (let index = 0; index < batch.messages.length; index++) {
|
|
161
|
-
const message = batch.messages[index];
|
|
162
|
-
const body = yield* decodeBody(message.body).pipe(Effect.mapError((cause) => new QueueMessageDecodeError({
|
|
163
|
-
queue: batch.queue,
|
|
164
|
-
messageId: message.id,
|
|
165
|
-
index,
|
|
166
|
-
cause
|
|
167
|
-
})));
|
|
168
|
-
messages.push(fromMessage(message, body));
|
|
169
|
-
}
|
|
170
|
-
return fromMessageBatch(batch, messages);
|
|
171
|
-
});
|
|
172
|
-
const Tag$9 = Tag$10;
|
|
173
|
-
const implement$6 = implement$7;
|
|
174
133
|
//#endregion
|
|
175
|
-
//#region src/
|
|
176
|
-
var
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
assertNoReservedMethodNames: () => assertNoReservedMethodNames,
|
|
185
|
-
assertNoReservedMethods: () => assertNoReservedMethods,
|
|
186
|
-
decodeArgs: () => decodeArgs,
|
|
187
|
-
decodeSuccess: () => decodeSuccess,
|
|
188
|
-
encodeArgs: () => encodeArgs,
|
|
189
|
-
encodeSuccess: () => encodeSuccess,
|
|
190
|
-
make: () => make$9,
|
|
191
|
-
method: () => method$4,
|
|
192
|
-
reservedMethodNames: () => reservedMethodNames$4
|
|
134
|
+
//#region src/DurableObjectWebSocket.ts
|
|
135
|
+
var DurableObjectWebSocket_exports = /* @__PURE__ */ __exportAll({
|
|
136
|
+
DurableWebSocketAttachmentError: () => DurableWebSocketAttachmentError,
|
|
137
|
+
DurableWebSocketCloseError: () => DurableWebSocketCloseError,
|
|
138
|
+
DurableWebSocketSendError: () => DurableWebSocketSendError,
|
|
139
|
+
acceptUpgrade: () => acceptUpgrade,
|
|
140
|
+
attachment: () => attachment,
|
|
141
|
+
fromWebSocket: () => fromWebSocket,
|
|
142
|
+
handlers: () => handlers
|
|
193
143
|
});
|
|
194
|
-
|
|
195
|
-
var
|
|
196
|
-
|
|
197
|
-
var
|
|
198
|
-
|
|
199
|
-
var
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
144
|
+
/** Error raised when sending on a Durable Object websocket fails. */
|
|
145
|
+
var DurableWebSocketSendError = class extends Data.TaggedError("DurableWebSocketSendError") {};
|
|
146
|
+
/** Error raised when closing a Durable Object websocket fails. */
|
|
147
|
+
var DurableWebSocketCloseError = class extends Data.TaggedError("DurableWebSocketCloseError") {};
|
|
148
|
+
/** Error raised when serializing or deserializing a websocket attachment fails. */
|
|
149
|
+
var DurableWebSocketAttachmentError = class extends Data.TaggedError("DurableWebSocketAttachmentError") {};
|
|
150
|
+
const wrappers = /* @__PURE__ */ new WeakMap();
|
|
151
|
+
/** Wraps a native Cloudflare websocket in the Effect-native Durable Object API. */
|
|
152
|
+
const fromWebSocket = (raw) => {
|
|
153
|
+
const existing = wrappers.get(raw);
|
|
154
|
+
if (existing !== void 0) return existing;
|
|
155
|
+
const socket = {
|
|
156
|
+
raw,
|
|
157
|
+
send: (data) => Effect.try({
|
|
158
|
+
try: () => raw.send(data),
|
|
159
|
+
catch: (cause) => new DurableWebSocketSendError({ cause })
|
|
160
|
+
}),
|
|
161
|
+
close: (code, reason) => Effect.try({
|
|
162
|
+
try: () => raw.close(code, reason),
|
|
163
|
+
catch: (cause) => new DurableWebSocketCloseError({ cause })
|
|
164
|
+
}),
|
|
165
|
+
serializeAttachment: (value) => Effect.try({
|
|
166
|
+
try: () => raw.serializeAttachment(value),
|
|
167
|
+
catch: (cause) => new DurableWebSocketAttachmentError({
|
|
168
|
+
operation: "serialize",
|
|
169
|
+
cause
|
|
170
|
+
})
|
|
171
|
+
}),
|
|
172
|
+
deserializeAttachment: Effect.try({
|
|
173
|
+
try: () => raw.deserializeAttachment(),
|
|
174
|
+
catch: (cause) => new DurableWebSocketAttachmentError({
|
|
175
|
+
operation: "deserialize",
|
|
176
|
+
cause
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
};
|
|
180
|
+
wrappers.set(raw, socket);
|
|
181
|
+
return socket;
|
|
226
182
|
};
|
|
227
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Accepts a websocket upgrade and registers the server socket on `DurableObjectState`.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```ts
|
|
188
|
+
* const response = yield* DurableObjectWebSocket.acceptUpgrade({
|
|
189
|
+
* tags: ["room:general"],
|
|
190
|
+
* });
|
|
191
|
+
*
|
|
192
|
+
* return response.response;
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
const acceptUpgrade = (options = {}) => Effect.gen(function* () {
|
|
196
|
+
const state = yield* DurableObjectState;
|
|
197
|
+
const pair = new WebSocketPair();
|
|
198
|
+
const client = pair[0];
|
|
199
|
+
const server = fromWebSocket(pair[1]);
|
|
200
|
+
if (options.attachment !== void 0) server.raw.serializeAttachment(options.attachment);
|
|
201
|
+
yield* state.acceptWebSocket(server, options.tags === void 0 ? void 0 : [...options.tags]);
|
|
228
202
|
return {
|
|
229
|
-
|
|
230
|
-
|
|
203
|
+
client,
|
|
204
|
+
server,
|
|
205
|
+
response: new Response(null, {
|
|
206
|
+
status: 101,
|
|
207
|
+
webSocket: client
|
|
208
|
+
})
|
|
231
209
|
};
|
|
232
|
-
}
|
|
233
|
-
const assertNoReservedMethodNames = (definition) => Effect.forEach(Object.keys(definition.methods), (method) => reservedMethodNames$4.has(method) ? Effect.fail(new RpcReservedMethodNameError({
|
|
234
|
-
definition: definition.id,
|
|
235
|
-
method
|
|
236
|
-
})) : Effect.void).pipe(Effect.asVoid);
|
|
237
|
-
const decodeArgs = (definition, methodName, args) => Effect.gen(function* () {
|
|
238
|
-
const methodDefinition = definition.methods[methodName];
|
|
239
|
-
if (args.length !== methodDefinition.args.length) return yield* Effect.fail(new RpcArgumentCountError({
|
|
240
|
-
definition: definition.id,
|
|
241
|
-
method: methodName,
|
|
242
|
-
expected: methodDefinition.args.length,
|
|
243
|
-
actual: args.length
|
|
244
|
-
}));
|
|
245
|
-
const decoded = [];
|
|
246
|
-
for (let index = 0; index < methodDefinition.args.length; index++) {
|
|
247
|
-
const schema = methodDefinition.args[index];
|
|
248
|
-
decoded.push(yield* Schema.decodeUnknownEffect(schema)(args[index]).pipe(Effect.mapError((cause) => new RpcArgumentDecodeError({
|
|
249
|
-
definition: definition.id,
|
|
250
|
-
method: methodName,
|
|
251
|
-
index,
|
|
252
|
-
cause
|
|
253
|
-
}))));
|
|
254
|
-
}
|
|
255
|
-
return decoded;
|
|
256
210
|
});
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
encoded.push(yield* Schema.encodeEffect(schema)(args[index]).pipe(Effect.mapError((cause) => new RpcArgumentEncodeError({
|
|
269
|
-
definition: definition.id,
|
|
270
|
-
method: methodName,
|
|
271
|
-
index,
|
|
211
|
+
/** Creates typed attachment helpers for accepted and rehydrated sockets. */
|
|
212
|
+
const attachment = (schema) => {
|
|
213
|
+
const serialize = (socket, value) => Schema.encodeEffect(schema)(value).pipe(Effect.mapError((cause) => new DurableWebSocketAttachmentError({
|
|
214
|
+
operation: "serialize",
|
|
215
|
+
cause
|
|
216
|
+
})), Effect.flatMap((encoded) => socket.serializeAttachment(encoded)));
|
|
217
|
+
const deserialize = (socket) => Effect.gen(function* () {
|
|
218
|
+
const value = yield* socket.deserializeAttachment;
|
|
219
|
+
if (value == null) return Option.none();
|
|
220
|
+
return Option.some(yield* Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError((cause) => new DurableWebSocketAttachmentError({
|
|
221
|
+
operation: "deserialize",
|
|
272
222
|
cause
|
|
273
223
|
}))));
|
|
274
|
-
}
|
|
275
|
-
return encoded;
|
|
276
|
-
});
|
|
277
|
-
const encodeSuccess = (definition, methodName, value) => {
|
|
278
|
-
const methodDefinition = definition.methods[methodName];
|
|
279
|
-
return Schema.encodeEffect(methodDefinition.success)(value).pipe(Effect.mapError((cause) => new RpcSuccessEncodeError({
|
|
280
|
-
definition: definition.id,
|
|
281
|
-
method: methodName,
|
|
282
|
-
cause
|
|
283
|
-
})));
|
|
284
|
-
};
|
|
285
|
-
const decodeSuccess = (definition, methodName, value) => {
|
|
286
|
-
const methodDefinition = definition.methods[methodName];
|
|
287
|
-
return Schema.decodeUnknownEffect(methodDefinition.success)(value).pipe(Effect.mapError((cause) => new RpcSuccessDecodeError({
|
|
288
|
-
definition: definition.id,
|
|
289
|
-
method: methodName,
|
|
290
|
-
cause
|
|
291
|
-
})));
|
|
292
|
-
};
|
|
293
|
-
const make$9 = (id, methods) => {
|
|
294
|
-
const definition = {
|
|
295
|
-
id,
|
|
296
|
-
methods
|
|
297
|
-
};
|
|
298
|
-
const reserved = Object.keys(definition.methods).find((methodName) => reservedMethodNames$4.has(methodName));
|
|
299
|
-
if (reserved !== void 0) throw new RpcReservedMethodNameError({
|
|
300
|
-
definition: id,
|
|
301
|
-
method: reserved
|
|
302
224
|
});
|
|
303
|
-
|
|
225
|
+
const rehydrate = (options = {}) => Effect.gen(function* () {
|
|
226
|
+
const sockets = yield* (yield* DurableObjectState).getWebSockets(options.tag);
|
|
227
|
+
const restored = [];
|
|
228
|
+
const onInvalid = options.onInvalid ?? "ignore";
|
|
229
|
+
for (const socket of sockets) {
|
|
230
|
+
const decoded = yield* deserialize(socket).pipe(Effect.match({
|
|
231
|
+
onFailure: (error) => ({
|
|
232
|
+
_tag: "Failure",
|
|
233
|
+
error
|
|
234
|
+
}),
|
|
235
|
+
onSuccess: (value) => ({
|
|
236
|
+
_tag: "Success",
|
|
237
|
+
value
|
|
238
|
+
})
|
|
239
|
+
}));
|
|
240
|
+
if (decoded._tag === "Success" && Option.isSome(decoded.value)) {
|
|
241
|
+
restored.push({
|
|
242
|
+
socket,
|
|
243
|
+
attachment: decoded.value.value
|
|
244
|
+
});
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (decoded._tag === "Failure" && onInvalid === "fail") return yield* Effect.fail(decoded.error);
|
|
248
|
+
if (decoded._tag === "Failure" && onInvalid === "ignore-and-close") yield* socket.close(1008, "invalid websocket attachment").pipe(Effect.ignore);
|
|
249
|
+
}
|
|
250
|
+
return restored;
|
|
251
|
+
});
|
|
252
|
+
return {
|
|
253
|
+
serialize,
|
|
254
|
+
deserialize,
|
|
255
|
+
rehydrate,
|
|
256
|
+
schema
|
|
257
|
+
};
|
|
304
258
|
};
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
dispose: () => dispose,
|
|
311
|
-
isDisposable: () => isDisposable,
|
|
312
|
-
resolve: () => resolve,
|
|
313
|
-
scoped: () => scoped
|
|
314
|
-
});
|
|
315
|
-
const isDisposable = (value) => (typeof value === "object" || typeof value === "function") && value !== null && Symbol.dispose in value && typeof value[Symbol.dispose] === "function";
|
|
316
|
-
const dispose = (value) => Effect.sync(() => {
|
|
317
|
-
if (isDisposable(value)) value[Symbol.dispose]();
|
|
318
|
-
});
|
|
319
|
-
const resolve = (value) => isPromiseLike(value) ? Effect.tryPromise({
|
|
320
|
-
try: () => value,
|
|
321
|
-
catch: (cause) => cause
|
|
322
|
-
}) : Effect.sync(() => value);
|
|
323
|
-
const scoped = (value) => Effect.acquireRelease(resolve(value), (resolved) => dispose(resolved));
|
|
324
|
-
const isPromiseLike = (value) => (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
|
|
325
|
-
//#endregion
|
|
326
|
-
//#region src/internal/RpcInvocation.ts
|
|
327
|
-
const isPropertyTarget = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
|
|
328
|
-
const lookupRpcMethod = (target, method, makeError) => Effect.try({
|
|
329
|
-
try: () => {
|
|
330
|
-
if (!isPropertyTarget(target)) throw new TypeError(`RPC target is not object-like`);
|
|
331
|
-
const value = Reflect.get(target, method);
|
|
332
|
-
if (typeof value !== "function") throw new TypeError(`RPC method "${String(method)}" is not callable`);
|
|
333
|
-
return ((...args) => Reflect.apply(value, target, args));
|
|
334
|
-
},
|
|
335
|
-
catch: makeError
|
|
336
|
-
});
|
|
337
|
-
const invokeRpcMethod = (target, method, args, makeError) => Effect.gen(function* () {
|
|
338
|
-
const fn = yield* lookupRpcMethod(target, method, makeError);
|
|
339
|
-
return yield* Effect.try({
|
|
340
|
-
try: () => fn(...args),
|
|
341
|
-
catch: makeError
|
|
342
|
-
});
|
|
259
|
+
/** Maps compact websocket lifecycle handler names to `DurableObject.make` options. */
|
|
260
|
+
const handlers = (options) => ({
|
|
261
|
+
webSocketMessage: options.message,
|
|
262
|
+
webSocketClose: options.close,
|
|
263
|
+
webSocketError: options.error
|
|
343
264
|
});
|
|
344
265
|
//#endregion
|
|
345
|
-
//#region src/
|
|
346
|
-
var
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
ServiceBindingRpcError: () => ServiceBindingRpcError,
|
|
350
|
-
isServiceBindingClient: () => isServiceBindingClient,
|
|
351
|
-
layer: () => layer$8,
|
|
352
|
-
makeClient: () => makeClient$5,
|
|
353
|
-
makeDirectMethods: () => makeDirectMethods$1
|
|
266
|
+
//#region src/DurableObjectState.ts
|
|
267
|
+
var DurableObjectState_exports = /* @__PURE__ */ __exportAll({
|
|
268
|
+
DurableObjectState: () => DurableObjectState,
|
|
269
|
+
fromDurableObjectState: () => fromDurableObjectState
|
|
354
270
|
});
|
|
355
|
-
const TypeId$2 = "effect-cf/ServiceBinding";
|
|
356
|
-
const expectedServiceBinding = "Worker service binding with fetch()";
|
|
357
271
|
/**
|
|
358
|
-
*
|
|
272
|
+
* Context tag for accessing the current Durable Object state service.
|
|
359
273
|
*/
|
|
360
|
-
var
|
|
274
|
+
var DurableObjectState = class extends Context.Service()("effect-cf/DurableObjectState") {};
|
|
361
275
|
/**
|
|
362
|
-
*
|
|
276
|
+
* Wraps a native Cloudflare `DurableObjectState` as a {@link DurableObjectStateService}.
|
|
363
277
|
*/
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
}));
|
|
386
|
-
});
|
|
387
|
-
const decodeSuccess$2 = (methodName, value) => Effect.gen(function* () {
|
|
388
|
-
if (definition.definition === void 0) return value;
|
|
389
|
-
return yield* decodeSuccess(definition.definition, methodName, value).pipe(Effect.mapError((cause) => new ServiceBindingRpcError({
|
|
390
|
-
binding: definition.binding,
|
|
391
|
-
method: methodName,
|
|
392
|
-
cause
|
|
393
|
-
})));
|
|
394
|
-
});
|
|
395
|
-
const call = (method, ...args) => Effect.gen(function* () {
|
|
396
|
-
const methodName = String(method);
|
|
397
|
-
return yield* decodeSuccess$2(methodName, yield* resolve(yield* rpc(method, ...args)).pipe(Effect.mapError((cause) => new ServiceBindingRpcError({
|
|
398
|
-
binding: definition.binding,
|
|
399
|
-
method: methodName,
|
|
400
|
-
cause
|
|
401
|
-
}))));
|
|
402
|
-
});
|
|
403
|
-
const scopedCall = (method, ...args) => Effect.gen(function* () {
|
|
404
|
-
return yield* decodeSuccess$2(String(method), yield* scoped(yield* rpc(method, ...args)));
|
|
405
|
-
});
|
|
406
|
-
const directMethods = makeDirectMethods$1(definition.definition, call);
|
|
407
|
-
return Object.assign(directMethods, {
|
|
408
|
-
fetch,
|
|
409
|
-
rpc,
|
|
410
|
-
call,
|
|
411
|
-
scopedCall
|
|
412
|
-
});
|
|
413
|
-
};
|
|
278
|
+
const fromDurableObjectState = (state) => ({
|
|
279
|
+
raw: state,
|
|
280
|
+
id: state.id,
|
|
281
|
+
storage: fromDurableObjectStorage(state.storage),
|
|
282
|
+
waitUntil: (promise) => Effect.sync(() => state.waitUntil(promise)),
|
|
283
|
+
blockConcurrencyWhile: (effect) => Effect.context().pipe(Effect.flatMap((context) => Effect.promise(() => state.blockConcurrencyWhile(() => runPromiseExitPreservingTypedFailures(Effect.provideContext(effect, context))))), Effect.flatten),
|
|
284
|
+
blockConcurrencyWhileOrReset: (effect) => Effect.context().pipe(Effect.flatMap((context) => Effect.promise(() => state.blockConcurrencyWhile(() => Effect.runPromise(Effect.provideContext(effect, context)))))),
|
|
285
|
+
acceptWebSocket: (ws, tags) => Effect.sync(() => state.acceptWebSocket(ws.raw, tags)),
|
|
286
|
+
getWebSockets: (tag) => Effect.sync(() => state.getWebSockets(tag).map((socket) => fromWebSocket(socket))),
|
|
287
|
+
setWebSocketAutoResponse: (pair) => Effect.sync(() => state.setWebSocketAutoResponse(pair)),
|
|
288
|
+
getWebSocketAutoResponse: Effect.sync(() => state.getWebSocketAutoResponse()),
|
|
289
|
+
getWebSocketAutoResponseTimestamp: (ws) => Effect.sync(() => state.getWebSocketAutoResponseTimestamp(ws.raw)),
|
|
290
|
+
setHibernatableWebSocketEventTimeout: (timeoutMs) => Effect.sync(() => state.setHibernatableWebSocketEventTimeout(timeoutMs)),
|
|
291
|
+
getHibernatableWebSocketEventTimeout: Effect.sync(() => state.getHibernatableWebSocketEventTimeout()),
|
|
292
|
+
getTags: (ws) => Effect.sync(() => state.getTags(ws.raw)),
|
|
293
|
+
abort: (reason) => Effect.sync(() => state.abort(reason))
|
|
294
|
+
});
|
|
295
|
+
const runPromiseExitPreservingTypedFailures = async (effect) => {
|
|
296
|
+
const exit = await Effect.runPromiseExit(effect);
|
|
297
|
+
if (Exit.isFailure(exit) && (Cause.hasDies(exit.cause) || Cause.hasInterrupts(exit.cause))) throw Cause.squash(exit.cause);
|
|
298
|
+
return exit;
|
|
414
299
|
};
|
|
415
|
-
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region src/CloudflareOtlp.ts
|
|
302
|
+
var CloudflareOtlp_exports = /* @__PURE__ */ __exportAll({
|
|
303
|
+
CloudflareOtlpSettings: () => CloudflareOtlpSettings,
|
|
304
|
+
durableObjectLayer: () => durableObjectLayer,
|
|
305
|
+
layer: () => layer$9,
|
|
306
|
+
layerJson: () => layerJson,
|
|
307
|
+
layerProtobuf: () => layerProtobuf,
|
|
308
|
+
settingsConfig: () => settingsConfig,
|
|
309
|
+
settingsLayer: () => settingsLayer,
|
|
310
|
+
workerLayer: () => workerLayer
|
|
311
|
+
});
|
|
416
312
|
/**
|
|
417
|
-
*
|
|
313
|
+
* Supported OpenTelemetry environment configuration for Cloudflare OTLP export.
|
|
418
314
|
*
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
* - `rpc(...)` for raw Cloudflare RPC results
|
|
423
|
-
* - `call(...)` for resolved and decoded RPC results
|
|
424
|
-
* - `scopedCall(...)` for scoped and decoded disposable RPC results
|
|
425
|
-
* - direct RPC methods when `definition` is provided
|
|
315
|
+
* This config intentionally uses the conventional `OTEL_*` variable names so
|
|
316
|
+
* deployments can share the same settings used by other OpenTelemetry SDKs.
|
|
317
|
+
* It covers the OTLP HTTP settings supported by the Effect OTLP layers:
|
|
426
318
|
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
319
|
+
* - `OTEL_EXPORTER_OTLP_ENDPOINT`
|
|
320
|
+
* - `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`
|
|
321
|
+
* - `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`
|
|
322
|
+
* - `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`
|
|
323
|
+
* - `OTEL_EXPORTER_OTLP_HEADERS`
|
|
324
|
+
* - `OTEL_EXPORTER_OTLP_LOGS_HEADERS`
|
|
325
|
+
* - `OTEL_EXPORTER_OTLP_TRACES_HEADERS`
|
|
326
|
+
* - `OTEL_EXPORTER_OTLP_METRICS_HEADERS`
|
|
327
|
+
* - `OTEL_SERVICE_NAME`
|
|
328
|
+
* - `OTEL_RESOURCE_ATTRIBUTES`
|
|
435
329
|
*
|
|
436
|
-
*
|
|
330
|
+
* `OTEL_SERVICE_VERSION` is also accepted as an effect-cf convenience alias.
|
|
331
|
+
* The standard OpenTelemetry way to configure service version is
|
|
332
|
+
* `OTEL_RESOURCE_ATTRIBUTES=service.version=...`.
|
|
437
333
|
*
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
* const next = yield* counter.increment(1);
|
|
441
|
-
* return next;
|
|
442
|
-
* });
|
|
443
|
-
* ```
|
|
334
|
+
* Consumers with non-standard binding names should map those names into
|
|
335
|
+
* {@link CloudflareOtlpSettings} rather than changing this config globally.
|
|
444
336
|
*/
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
return yield* (yield* tag).scopedCall(method, ...args);
|
|
458
|
-
});
|
|
459
|
-
const directMethods = makeDirectMethods$1(definition.definition, call);
|
|
460
|
-
return Object.assign(tag, directMethods, {
|
|
461
|
-
[TypeId$2]: TypeId$2,
|
|
462
|
-
definition,
|
|
463
|
-
fetch,
|
|
464
|
-
rpc,
|
|
465
|
-
call,
|
|
466
|
-
scopedCall
|
|
467
|
-
});
|
|
468
|
-
};
|
|
469
|
-
const makeDirectMethods$1 = (rpcDefinition, call) => {
|
|
470
|
-
const methods = {};
|
|
471
|
-
if (rpcDefinition !== void 0) for (const methodName of Object.keys(rpcDefinition.methods)) methods[methodName] = (...args) => call(methodName, ...args);
|
|
472
|
-
return methods;
|
|
473
|
-
};
|
|
474
|
-
//#endregion
|
|
475
|
-
//#region src/WorkerDefinition.ts
|
|
476
|
-
var WorkerDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
477
|
-
Tag: () => Tag$8,
|
|
478
|
-
Worker: () => Worker,
|
|
479
|
-
implement: () => implement$5,
|
|
480
|
-
make: () => make$8,
|
|
481
|
-
method: () => method$3
|
|
337
|
+
const settingsConfig = Config.all({
|
|
338
|
+
endpoint: Config.string("OTEL_EXPORTER_OTLP_ENDPOINT").pipe(Config.option),
|
|
339
|
+
logsEndpoint: Config.string("OTEL_EXPORTER_OTLP_LOGS_ENDPOINT").pipe(Config.option),
|
|
340
|
+
tracesEndpoint: Config.string("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT").pipe(Config.option),
|
|
341
|
+
metricsEndpoint: Config.string("OTEL_EXPORTER_OTLP_METRICS_ENDPOINT").pipe(Config.option),
|
|
342
|
+
headers: Config.string("OTEL_EXPORTER_OTLP_HEADERS").pipe(Config.option),
|
|
343
|
+
logsHeaders: Config.string("OTEL_EXPORTER_OTLP_LOGS_HEADERS").pipe(Config.option),
|
|
344
|
+
tracesHeaders: Config.string("OTEL_EXPORTER_OTLP_TRACES_HEADERS").pipe(Config.option),
|
|
345
|
+
metricsHeaders: Config.string("OTEL_EXPORTER_OTLP_METRICS_HEADERS").pipe(Config.option),
|
|
346
|
+
serviceName: Config.string("OTEL_SERVICE_NAME").pipe(Config.option),
|
|
347
|
+
serviceVersion: Config.string("OTEL_SERVICE_VERSION").pipe(Config.option),
|
|
348
|
+
resourceAttributes: Config.schema(Config.Record(Schema.String, Schema.String), "OTEL_RESOURCE_ATTRIBUTES").pipe(Config.option)
|
|
482
349
|
});
|
|
483
|
-
const reservedMethodNames$3 = new Set([
|
|
484
|
-
"constructor",
|
|
485
|
-
"dup",
|
|
486
|
-
"fetch",
|
|
487
|
-
"connect",
|
|
488
|
-
"queue",
|
|
489
|
-
"scheduled",
|
|
490
|
-
"tail",
|
|
491
|
-
"tailStream",
|
|
492
|
-
"test",
|
|
493
|
-
"trace",
|
|
494
|
-
"alarm",
|
|
495
|
-
"webSocketMessage",
|
|
496
|
-
"webSocketClose",
|
|
497
|
-
"webSocketError"
|
|
498
|
-
]);
|
|
499
|
-
/**
|
|
500
|
-
* Defines a single RPC method schema in a worker definition.
|
|
501
|
-
*/
|
|
502
|
-
const method$3 = method$4;
|
|
503
350
|
/**
|
|
504
|
-
*
|
|
351
|
+
* Service carrying already-resolved Cloudflare OTLP settings.
|
|
352
|
+
*
|
|
353
|
+
* Provide this service directly when an application needs to map custom
|
|
354
|
+
* Cloudflare binding names, compute settings dynamically, or override settings
|
|
355
|
+
* in tests. When this service is present, the OTLP layers use it instead of
|
|
356
|
+
* reading {@link settingsConfig}.
|
|
505
357
|
*
|
|
506
358
|
* @example
|
|
507
359
|
* ```ts
|
|
508
|
-
* const
|
|
509
|
-
*
|
|
510
|
-
*
|
|
511
|
-
*
|
|
512
|
-
*
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
const scopedCall = (method, ...args) => Effect.gen(function* () {
|
|
543
|
-
return yield* (yield* tag).scopedCall(method, ...args);
|
|
544
|
-
});
|
|
545
|
-
const directMethods = makeDirectMethods$1(definition, call);
|
|
546
|
-
return Object.assign(tag, directMethods, {
|
|
547
|
-
id: definition.id,
|
|
548
|
-
methods: definition.methods,
|
|
549
|
-
make: definition.make,
|
|
550
|
-
layer,
|
|
551
|
-
fetch,
|
|
552
|
-
rpc,
|
|
553
|
-
call,
|
|
554
|
-
scopedCall
|
|
555
|
-
});
|
|
556
|
-
};
|
|
557
|
-
const Worker = Tag$8;
|
|
558
|
-
const wrapHandlers$1 = (definition, handlers) => {
|
|
559
|
-
const wrapped = {};
|
|
560
|
-
for (const key of Object.keys(definition.methods)) {
|
|
561
|
-
const handler = handlers[key];
|
|
562
|
-
wrapped[key] = (...args) => Effect.gen(function* () {
|
|
563
|
-
return yield* encodeSuccess(definition, key, yield* handler(...yield* decodeArgs(definition, key, args)));
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
|
-
return wrapped;
|
|
567
|
-
};
|
|
360
|
+
* const CustomOtlpSettings = Layer.effect(
|
|
361
|
+
* CloudflareOtlp.CloudflareOtlpSettings,
|
|
362
|
+
* Config.all({
|
|
363
|
+
* ...CloudflareOtlp.settingsConfig,
|
|
364
|
+
* endpoint: Config.string("MY_OTLP_ENDPOINT").pipe(Config.option),
|
|
365
|
+
* }),
|
|
366
|
+
* ).pipe(Layer.provide(WorkerConfig.layer));
|
|
367
|
+
* ```
|
|
368
|
+
*/
|
|
369
|
+
var CloudflareOtlpSettings = class extends Context.Service()("effect-cf/CloudflareOtlpSettings") {};
|
|
370
|
+
const allSignals = [
|
|
371
|
+
"logs",
|
|
372
|
+
"traces",
|
|
373
|
+
"metrics"
|
|
374
|
+
];
|
|
375
|
+
const optionToUndefined = (option) => Option.isSome(option) ? option.value : void 0;
|
|
376
|
+
const nonEmptyStringOption = (option) => Option.flatMap(option, (value) => {
|
|
377
|
+
const trimmed = value.trim();
|
|
378
|
+
return trimmed === "" ? Option.none() : Option.some(trimmed);
|
|
379
|
+
});
|
|
380
|
+
const nonEmptyRecordOption = (option) => Option.filter(option, (value) => Object.keys(value).length > 0);
|
|
381
|
+
const normalizeSettings = (settings) => ({
|
|
382
|
+
endpoint: nonEmptyStringOption(settings.endpoint),
|
|
383
|
+
logsEndpoint: nonEmptyStringOption(settings.logsEndpoint),
|
|
384
|
+
tracesEndpoint: nonEmptyStringOption(settings.tracesEndpoint),
|
|
385
|
+
metricsEndpoint: nonEmptyStringOption(settings.metricsEndpoint),
|
|
386
|
+
headers: nonEmptyStringOption(settings.headers),
|
|
387
|
+
logsHeaders: nonEmptyStringOption(settings.logsHeaders),
|
|
388
|
+
tracesHeaders: nonEmptyStringOption(settings.tracesHeaders),
|
|
389
|
+
metricsHeaders: nonEmptyStringOption(settings.metricsHeaders),
|
|
390
|
+
serviceName: nonEmptyStringOption(settings.serviceName),
|
|
391
|
+
serviceVersion: nonEmptyStringOption(settings.serviceVersion),
|
|
392
|
+
resourceAttributes: nonEmptyRecordOption(settings.resourceAttributes)
|
|
393
|
+
});
|
|
568
394
|
/**
|
|
569
|
-
*
|
|
395
|
+
* Layer that reads standard OpenTelemetry settings from the current Cloudflare
|
|
396
|
+
* `env` object.
|
|
397
|
+
*
|
|
398
|
+
* The layer depends on {@link WorkerEnvironment} and installs a
|
|
399
|
+
* Cloudflare-backed Effect `ConfigProvider`, so `settingsConfig` reads from
|
|
400
|
+
* Worker vars/secrets instead of Node process environment variables.
|
|
570
401
|
*/
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
const
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
assertNoReservedMethods(target, methods, reservedMethodNames);
|
|
578
|
-
for (const [key, method] of Object.entries(methods)) Object.defineProperty(prototype, key, {
|
|
579
|
-
enumerable: true,
|
|
580
|
-
value(...args) {
|
|
581
|
-
return run(this, Effect.suspend(() => method(...args)));
|
|
582
|
-
}
|
|
583
|
-
});
|
|
402
|
+
const settingsLayer = Layer.effect(CloudflareOtlpSettings, settingsConfig.pipe(Config.map(normalizeSettings))).pipe(Layer.provide(WorkerConfig.layer));
|
|
403
|
+
const selectedSignals = (signals) => new Set(signals ?? allSignals);
|
|
404
|
+
const withDefinedAttributes = (attributes) => {
|
|
405
|
+
const out = {};
|
|
406
|
+
for (const [key, value] of Object.entries(attributes)) if (value !== void 0) out[key] = value;
|
|
407
|
+
return out;
|
|
584
408
|
};
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
const
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
const
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
409
|
+
const parseHeaders = (input) => {
|
|
410
|
+
if (Option.isNone(input) || input.value.trim() === "") return;
|
|
411
|
+
const headers = {};
|
|
412
|
+
for (const part of input.value.split(",")) {
|
|
413
|
+
const index = part.indexOf("=");
|
|
414
|
+
if (index <= 0) continue;
|
|
415
|
+
const key = part.slice(0, index).trim();
|
|
416
|
+
const value = part.slice(index + 1).trim();
|
|
417
|
+
if (key !== "") headers[decodeHeaderComponent(key)] = decodeHeaderComponent(value);
|
|
418
|
+
}
|
|
419
|
+
return headers;
|
|
420
|
+
};
|
|
421
|
+
const mergeHeaders = (common, signalSpecific) => {
|
|
422
|
+
const commonHeaders = parseHeaders(common);
|
|
423
|
+
const signalHeaders = parseHeaders(signalSpecific);
|
|
424
|
+
if (commonHeaders === void 0 && signalHeaders === void 0) return;
|
|
601
425
|
return {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
waitUntilPropagating: (effect, options) => schedule(effect, options, "propagate"),
|
|
605
|
-
passThroughOnException: Effect.sync(() => ctx.passThroughOnException())
|
|
426
|
+
...commonHeaders,
|
|
427
|
+
...signalHeaders
|
|
606
428
|
};
|
|
607
429
|
};
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
Tag: () => Tag$7,
|
|
614
|
-
WorkerContext: () => WorkerContext,
|
|
615
|
-
implement: () => implement$4,
|
|
616
|
-
isWebSocketUpgrade: () => isWebSocketUpgrade,
|
|
617
|
-
make: () => make$7,
|
|
618
|
-
makeFetchHandler: () => makeFetchHandler,
|
|
619
|
-
method: () => method$2,
|
|
620
|
-
renderHttpResponse: () => renderHttpResponse
|
|
621
|
-
});
|
|
622
|
-
var ExecutionContext = class extends Context.Service()("effect-cf/ExecutionContext") {};
|
|
623
|
-
var WorkerContext = class extends Context.Service()("effect-cf/WorkerContext") {};
|
|
624
|
-
var NativeRequest = class extends Context.Service()("effect-cf/NativeRequest") {};
|
|
625
|
-
const isWebSocketUpgrade = (request) => request.headers.get("Upgrade")?.toLowerCase() === "websocket";
|
|
626
|
-
const reservedMethodNames$2 = new Set([
|
|
627
|
-
"constructor",
|
|
628
|
-
"dup",
|
|
629
|
-
"fetch",
|
|
630
|
-
"connect",
|
|
631
|
-
"queue",
|
|
632
|
-
"scheduled",
|
|
633
|
-
"tail",
|
|
634
|
-
"tailStream",
|
|
635
|
-
"test",
|
|
636
|
-
"trace",
|
|
637
|
-
"alarm",
|
|
638
|
-
"webSocketMessage",
|
|
639
|
-
"webSocketClose",
|
|
640
|
-
"webSocketError"
|
|
641
|
-
]);
|
|
642
|
-
const RunSymbol$1 = Symbol.for("effect-cf/Worker/run");
|
|
643
|
-
const renderHttpResponse = (effect) => Effect.flatMap(effect, (response) => Effect.map(Effect.context(), (context) => HttpServerResponse.toWeb(response, { context })));
|
|
644
|
-
const renderFetchSuccess = (effect) => Effect.flatMap(effect, (response) => response instanceof Response ? Effect.succeed(response) : Effect.map(Effect.context(), (context) => HttpServerResponse.toWeb(response, { context })));
|
|
645
|
-
const isWorkerOptions = (options) => typeof options === "object" && options !== null && ("fetch" in options || "queue" in options || "rpc" in options);
|
|
646
|
-
function make$7(layer, optionsOrFetch) {
|
|
647
|
-
const options = isWorkerOptions(optionsOrFetch) ? optionsOrFetch : { fetch: optionsOrFetch };
|
|
648
|
-
class EffectWorker extends WorkerEntrypoint {
|
|
649
|
-
runtime;
|
|
650
|
-
constructor(ctx, env) {
|
|
651
|
-
super(ctx, env);
|
|
652
|
-
let runWaitUntilEffect = () => Promise.reject(/* @__PURE__ */ new Error("WorkerContext runtime is not initialized"));
|
|
653
|
-
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)));
|
|
654
|
-
this.runtime = ManagedRuntime.make(runtimeLayer);
|
|
655
|
-
runWaitUntilEffect = (effect) => this.runtime.runPromiseExit(effect);
|
|
656
|
-
}
|
|
657
|
-
[RunSymbol$1](effect) {
|
|
658
|
-
return this.runtime.runPromise(Effect.scoped(effect));
|
|
659
|
-
}
|
|
660
|
-
fetch(request) {
|
|
661
|
-
const fetchHandler = options.fetch;
|
|
662
|
-
if (fetchHandler === void 0) return Promise.resolve(new Response("Not Found", { status: 404 }));
|
|
663
|
-
const requestServices = Layer.mergeAll(Layer.succeed(NativeRequest, request), Layer.succeed(HttpServerRequest.HttpServerRequest, HttpServerRequest.fromWeb(request)));
|
|
664
|
-
return this[RunSymbol$1](renderFetchSuccess(fetchHandler).pipe(Effect.provide(requestServices)));
|
|
665
|
-
}
|
|
666
|
-
queue(batch) {
|
|
667
|
-
const queueHandler = options.queue;
|
|
668
|
-
if (queueHandler === void 0) return Promise.resolve();
|
|
669
|
-
const messages = batch.messages.map((message) => fromMessage(message, message.body));
|
|
670
|
-
return this[RunSymbol$1](queueHandler(fromMessageBatch(batch, messages)));
|
|
671
|
-
}
|
|
430
|
+
const decodeHeaderComponent = (value) => {
|
|
431
|
+
try {
|
|
432
|
+
return decodeURIComponent(value);
|
|
433
|
+
} catch {
|
|
434
|
+
return value;
|
|
672
435
|
}
|
|
673
|
-
defineEntrypointRpcMethods("Worker", EffectWorker.prototype, options.rpc, reservedMethodNames$2, (self, effect) => self[RunSymbol$1](effect));
|
|
674
|
-
return assumeEntrypointClass(EffectWorker);
|
|
675
|
-
}
|
|
676
|
-
const makeFetchHandler = (layer, options) => {
|
|
677
|
-
const WorkerClass = make$7(layer, options);
|
|
678
|
-
return { fetch: (request, env, ctx) => Promise.resolve(new WorkerClass(ctx, env).fetch(request)) };
|
|
679
436
|
};
|
|
680
|
-
const
|
|
681
|
-
const
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
}
|
|
689
|
-
/** Error type used when a storage operation throws or rejects. */
|
|
690
|
-
var StorageOperationError = class extends Data.TaggedError("StorageOperationError") {};
|
|
691
|
-
const storageError = (operation, cause) => new StorageOperationError({
|
|
692
|
-
operation,
|
|
693
|
-
cause
|
|
437
|
+
const appendOtlpPath = (baseUrl, path) => `${baseUrl.replace(/\/+$/, "")}${path}`;
|
|
438
|
+
const makeResource = (settings, options, runtimeAttributes) => ({
|
|
439
|
+
serviceName: options.serviceName ?? optionToUndefined(settings.serviceName),
|
|
440
|
+
serviceVersion: options.serviceVersion ?? optionToUndefined(settings.serviceVersion),
|
|
441
|
+
attributes: {
|
|
442
|
+
...optionToUndefined(settings.resourceAttributes),
|
|
443
|
+
...withDefinedAttributes(runtimeAttributes),
|
|
444
|
+
...options.attributes
|
|
445
|
+
}
|
|
694
446
|
});
|
|
695
|
-
const
|
|
696
|
-
|
|
697
|
-
|
|
447
|
+
const commonOtlpOptions = (settings, options, runtimeAttributes) => ({
|
|
448
|
+
resource: makeResource(settings, options, runtimeAttributes),
|
|
449
|
+
maxBatchSize: options.maxBatchSize,
|
|
450
|
+
loggerExportInterval: options.loggerExportInterval,
|
|
451
|
+
loggerExcludeLogSpans: options.loggerExcludeLogSpans,
|
|
452
|
+
loggerMergeWithExisting: options.loggerMergeWithExisting,
|
|
453
|
+
tracerExportInterval: options.tracerExportInterval,
|
|
454
|
+
tracerContext: options.tracerContext,
|
|
455
|
+
metricsExportInterval: options.metricsExportInterval,
|
|
456
|
+
metricsTemporality: options.metricsTemporality,
|
|
457
|
+
shutdownTimeout: options.shutdownTimeout
|
|
698
458
|
});
|
|
699
|
-
const
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
one: () => tryStorageSync("sql.one", () => cursor.one()),
|
|
707
|
-
raw: () => tryStorageSync("sql.raw", () => cursor.raw()),
|
|
708
|
-
get columnNames() {
|
|
709
|
-
return cursor.columnNames;
|
|
710
|
-
},
|
|
711
|
-
rowsRead: tryStorageSync("sql.rowsRead", () => cursor.rowsRead),
|
|
712
|
-
rowsWritten: tryStorageSync("sql.rowsWritten", () => cursor.rowsWritten)
|
|
713
|
-
});
|
|
714
|
-
const fromSqlStorage = (sql) => ({
|
|
715
|
-
exec: (query, ...bindings) => tryStorageSync("sql.exec", () => fromSqlCursor(sql.exec(query, ...bindings))),
|
|
716
|
-
get databaseSize() {
|
|
717
|
-
return sql.databaseSize;
|
|
718
|
-
}
|
|
459
|
+
const serializationLayer = (serialization) => serialization === "json" ? OtlpSerialization.layerJson : OtlpSerialization.layerProtobuf;
|
|
460
|
+
const resolveSettings = Effect.gen(function* () {
|
|
461
|
+
const settings = yield* Effect.serviceOption(CloudflareOtlpSettings);
|
|
462
|
+
if (Option.isSome(settings)) return normalizeSettings(settings.value);
|
|
463
|
+
const env = yield* Effect.serviceOption(WorkerEnvironment);
|
|
464
|
+
if (Option.isSome(env)) return normalizeSettings(yield* settingsConfig.pipe(Effect.provide(ConfigProvider.layer(Effect.succeed(WorkerConfig.providerFromEnv(env.value))))));
|
|
465
|
+
return normalizeSettings(yield* settingsConfig);
|
|
719
466
|
});
|
|
720
|
-
const
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
return {
|
|
726
|
-
get: (key) => Effect.gen(function* () {
|
|
727
|
-
const encodedKey = yield* encodeKey(key);
|
|
728
|
-
const encodedValue = yield* tryStorageSync("kv.get", () => kv.get(encodedKey));
|
|
729
|
-
if (encodedValue === void 0) return Option.none();
|
|
730
|
-
return yield* decodeValue(encodedValue).pipe(Effect.map(Option.some));
|
|
731
|
-
}),
|
|
732
|
-
put: (key, value) => Effect.gen(function* () {
|
|
733
|
-
const encodedKey = yield* encodeKey(key);
|
|
734
|
-
const encodedValue = yield* encodeValue(value);
|
|
735
|
-
yield* tryStorageSync("kv.put", () => kv.put(encodedKey, encodedValue));
|
|
736
|
-
}),
|
|
737
|
-
delete: (key) => Effect.gen(function* () {
|
|
738
|
-
const encodedKey = yield* encodeKey(key);
|
|
739
|
-
return yield* tryStorageSync("kv.delete", () => kv.delete(encodedKey));
|
|
740
|
-
}),
|
|
741
|
-
list: (options) => Effect.gen(function* () {
|
|
742
|
-
const entries = Array.from(yield* tryStorageSync("kv.list", () => kv.list(options)));
|
|
743
|
-
const decoded = [];
|
|
744
|
-
for (const [key, value] of entries) decoded.push([yield* decodeKey(key), yield* decodeValue(value)]);
|
|
745
|
-
return decoded;
|
|
746
|
-
})
|
|
747
|
-
};
|
|
467
|
+
const mergeSignalLayers = (layers) => {
|
|
468
|
+
if (layers.length === 0) return Layer.empty;
|
|
469
|
+
let merged = layers[0];
|
|
470
|
+
for (let index = 1; index < layers.length; index++) merged = Layer.mergeAll(merged, layers[index]);
|
|
471
|
+
return merged;
|
|
748
472
|
};
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
473
|
+
const emptyLayer = Layer.empty;
|
|
474
|
+
const makeLayerFromSettings = (options = {}, runtimeAttributes = {}) => Layer.unwrap(Effect.map(resolveSettings, (settings) => {
|
|
475
|
+
const signals = selectedSignals(options.signals);
|
|
476
|
+
const endpoint = optionToUndefined(settings.endpoint);
|
|
477
|
+
const logsEndpoint = optionToUndefined(settings.logsEndpoint);
|
|
478
|
+
const tracesEndpoint = optionToUndefined(settings.tracesEndpoint);
|
|
479
|
+
const metricsEndpoint = optionToUndefined(settings.metricsEndpoint);
|
|
480
|
+
const hasSpecificEndpoint = logsEndpoint !== void 0 || tracesEndpoint !== void 0 || metricsEndpoint !== void 0;
|
|
481
|
+
const hasSpecificHeaders = Option.isSome(settings.logsHeaders) || Option.isSome(settings.tracesHeaders) || Option.isSome(settings.metricsHeaders);
|
|
482
|
+
const common = commonOtlpOptions(settings, options, runtimeAttributes);
|
|
483
|
+
if (endpoint !== void 0 && !hasSpecificEndpoint && !hasSpecificHeaders && signals.size === 3) return Otlp.layer({
|
|
484
|
+
baseUrl: endpoint,
|
|
485
|
+
headers: parseHeaders(settings.headers),
|
|
486
|
+
...common
|
|
487
|
+
}).pipe(Layer.provide(serializationLayer(options.serialization)), Layer.provide(FetchHttpClient.layer));
|
|
488
|
+
const layers = [];
|
|
489
|
+
if (signals.has("logs")) {
|
|
490
|
+
const url = logsEndpoint ?? (endpoint === void 0 ? void 0 : appendOtlpPath(endpoint, "/v1/logs"));
|
|
491
|
+
if (url !== void 0) layers.push(OtlpLogger.layer({
|
|
492
|
+
url,
|
|
493
|
+
resource: common.resource,
|
|
494
|
+
headers: mergeHeaders(settings.headers, settings.logsHeaders),
|
|
495
|
+
exportInterval: common.loggerExportInterval,
|
|
496
|
+
maxBatchSize: common.maxBatchSize,
|
|
497
|
+
shutdownTimeout: common.shutdownTimeout,
|
|
498
|
+
excludeLogSpans: common.loggerExcludeLogSpans,
|
|
499
|
+
mergeWithExisting: common.loggerMergeWithExisting
|
|
500
|
+
}).pipe(Layer.provide(serializationLayer(options.serialization)), Layer.provide(FetchHttpClient.layer)));
|
|
501
|
+
}
|
|
502
|
+
if (signals.has("traces")) {
|
|
503
|
+
const url = tracesEndpoint ?? (endpoint === void 0 ? void 0 : appendOtlpPath(endpoint, "/v1/traces"));
|
|
504
|
+
if (url !== void 0) layers.push(OtlpTracer.layer({
|
|
505
|
+
url,
|
|
506
|
+
resource: common.resource,
|
|
507
|
+
headers: mergeHeaders(settings.headers, settings.tracesHeaders),
|
|
508
|
+
exportInterval: common.tracerExportInterval,
|
|
509
|
+
maxBatchSize: common.maxBatchSize,
|
|
510
|
+
context: common.tracerContext,
|
|
511
|
+
shutdownTimeout: common.shutdownTimeout
|
|
512
|
+
}).pipe(Layer.provide(serializationLayer(options.serialization)), Layer.provide(FetchHttpClient.layer)));
|
|
513
|
+
}
|
|
514
|
+
if (signals.has("metrics")) {
|
|
515
|
+
const url = metricsEndpoint ?? (endpoint === void 0 ? void 0 : appendOtlpPath(endpoint, "/v1/metrics"));
|
|
516
|
+
if (url !== void 0) layers.push(OtlpMetrics.layer({
|
|
517
|
+
url,
|
|
518
|
+
resource: common.resource,
|
|
519
|
+
headers: mergeHeaders(settings.headers, settings.metricsHeaders),
|
|
520
|
+
exportInterval: common.metricsExportInterval,
|
|
521
|
+
shutdownTimeout: common.shutdownTimeout,
|
|
522
|
+
temporality: common.metricsTemporality
|
|
523
|
+
}).pipe(Layer.provide(serializationLayer(options.serialization)), Layer.provide(FetchHttpClient.layer)));
|
|
524
|
+
}
|
|
525
|
+
return mergeSignalLayers(layers);
|
|
526
|
+
}).pipe(Effect.catch((error) => Effect.logWarning("CloudflareOtlp disabled because OTLP configuration is invalid", { error: String(error) }).pipe(Effect.as(emptyLayer)))));
|
|
527
|
+
const makeLayer = (options = {}, runtimeAttributes = {}) => makeLayerFromSettings(options, runtimeAttributes);
|
|
528
|
+
/**
|
|
529
|
+
* Base OTLP telemetry layer for Cloudflare-compatible runtimes.
|
|
530
|
+
*
|
|
531
|
+
* The layer reads {@link CloudflareOtlpSettings} when provided. Otherwise it
|
|
532
|
+
* reads standard OpenTelemetry config from `WorkerEnvironment` when available,
|
|
533
|
+
* then falls back to the ambient Effect `ConfigProvider`.
|
|
534
|
+
*
|
|
535
|
+
* When only `OTEL_EXPORTER_OTLP_ENDPOINT` is configured, per-signal paths are
|
|
536
|
+
* derived by appending `/v1/logs`, `/v1/traces`, and `/v1/metrics`. Signal
|
|
537
|
+
* specific endpoints are used as-is, matching the OpenTelemetry OTLP exporter
|
|
538
|
+
* convention.
|
|
539
|
+
*/
|
|
540
|
+
const layer$9 = (options = {}) => makeLayer(options);
|
|
541
|
+
/** Base OTLP telemetry layer forced to JSON serialization. */
|
|
542
|
+
const layerJson = (options = {}) => layer$9({
|
|
543
|
+
...options,
|
|
544
|
+
serialization: "json"
|
|
755
545
|
});
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
delete: (keyOrKeys, options) => Array.isArray(keyOrKeys) ? tryStoragePromise("transaction.delete", () => txn.delete(keyOrKeys, options)) : tryStoragePromise("transaction.delete", () => txn.delete(keyOrKeys, options)),
|
|
761
|
-
rollback: () => tryStorageSync("transaction.rollback", () => txn.rollback()),
|
|
762
|
-
getAlarm: (options) => tryStoragePromise("transaction.getAlarm", () => txn.getAlarm(options)),
|
|
763
|
-
setAlarm: (scheduledTime, options) => tryStoragePromise("transaction.setAlarm", () => txn.setAlarm(scheduledTime, options)),
|
|
764
|
-
deleteAlarm: (options) => tryStoragePromise("transaction.deleteAlarm", () => txn.deleteAlarm(options))
|
|
546
|
+
/** Base OTLP telemetry layer forced to protobuf serialization. */
|
|
547
|
+
const layerProtobuf = (options = {}) => layer$9({
|
|
548
|
+
...options,
|
|
549
|
+
serialization: "protobuf"
|
|
765
550
|
});
|
|
766
551
|
/**
|
|
767
|
-
*
|
|
552
|
+
* OTLP layer with Cloudflare Worker resource attributes.
|
|
553
|
+
*
|
|
554
|
+
* Provide this layer at runtime scope for long-lived metrics aggregation, or at
|
|
555
|
+
* handler scope when traces/logs should flush as the Cloudflare event finishes.
|
|
768
556
|
*/
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
delete: (key, options) => tryStoragePromise("delete", () => storage.delete(key, options)),
|
|
773
|
-
deleteAll: (options) => tryStoragePromise("deleteAll", () => storage.deleteAll(options)),
|
|
774
|
-
getAlarm: (options) => tryStoragePromise("getAlarm", () => storage.getAlarm(options)),
|
|
775
|
-
setAlarm: (scheduledTime, options) => tryStoragePromise("setAlarm", () => storage.setAlarm(scheduledTime, options)),
|
|
776
|
-
deleteAlarm: (options) => tryStoragePromise("deleteAlarm", () => storage.deleteAlarm(options)),
|
|
777
|
-
transactionSync: (closure) => Effect.context().pipe(Effect.flatMap((context) => Effect.suspend(() => {
|
|
778
|
-
try {
|
|
779
|
-
return Effect.succeed(storage.transactionSync(() => {
|
|
780
|
-
const exit = Effect.runSyncExitWith(context)(closure());
|
|
781
|
-
if (Exit.isSuccess(exit)) return exit.value;
|
|
782
|
-
throw exit;
|
|
783
|
-
}));
|
|
784
|
-
} catch (cause) {
|
|
785
|
-
if (Exit.isExit(cause) && Exit.isFailure(cause)) return Effect.failCause(cause.cause);
|
|
786
|
-
return Effect.fail(storageError("transactionSync", cause));
|
|
787
|
-
}
|
|
788
|
-
}))),
|
|
789
|
-
transaction: (closure) => Effect.context().pipe(Effect.flatMap((context) => Effect.callback((resume) => {
|
|
790
|
-
storage.transaction(async (txn) => {
|
|
791
|
-
const exit = await Effect.runPromiseExitWith(context)(closure(fromDurableObjectTransaction(txn)));
|
|
792
|
-
if (Exit.isSuccess(exit)) return exit.value;
|
|
793
|
-
throw exit;
|
|
794
|
-
}).then((value) => resume(Effect.succeed(value)), (cause) => {
|
|
795
|
-
if (Exit.isExit(cause) && Exit.isFailure(cause)) resume(Effect.failCause(cause.cause));
|
|
796
|
-
else resume(Effect.fail(storageError("transaction", cause)));
|
|
797
|
-
});
|
|
798
|
-
}))),
|
|
799
|
-
sync: () => tryStoragePromise("sync", () => storage.sync()),
|
|
800
|
-
getCurrentBookmark: () => tryStoragePromise("getCurrentBookmark", () => storage.getCurrentBookmark()),
|
|
801
|
-
onNextSessionRestoreBookmark: (bookmark) => tryStoragePromise("onNextSessionRestoreBookmark", () => storage.onNextSessionRestoreBookmark(bookmark)),
|
|
802
|
-
sql: fromSqlStorage(storage.sql),
|
|
803
|
-
kv: fromSyncKvStorage(storage.kv)
|
|
557
|
+
const workerLayer = (options = {}) => makeLayer(options, {
|
|
558
|
+
"cloudflare.resource_type": "worker",
|
|
559
|
+
"cloudflare.worker.name": options.workerName
|
|
804
560
|
});
|
|
561
|
+
/**
|
|
562
|
+
* OTLP layer with Cloudflare Durable Object resource attributes.
|
|
563
|
+
*
|
|
564
|
+
* The layer reads {@link DurableObjectState} so it can optionally include the
|
|
565
|
+
* Durable Object id. Prefer leaving `includeObjectId` disabled unless the
|
|
566
|
+
* backend can tolerate high-cardinality resource attributes.
|
|
567
|
+
*/
|
|
568
|
+
const durableObjectLayer = (options = {}) => Layer.unwrap(Effect.map(DurableObjectState, (state) => makeLayer(options, {
|
|
569
|
+
"cloudflare.resource_type": "durable_object",
|
|
570
|
+
"cloudflare.durable_object.class": options.className,
|
|
571
|
+
"cloudflare.durable_object.id": options.includeObjectId ? state.id.toString() : void 0
|
|
572
|
+
})));
|
|
805
573
|
//#endregion
|
|
806
|
-
//#region src/
|
|
807
|
-
var
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
DurableWebSocketSendError: () => DurableWebSocketSendError,
|
|
811
|
-
acceptUpgrade: () => acceptUpgrade,
|
|
812
|
-
attachment: () => attachment,
|
|
813
|
-
fromWebSocket: () => fromWebSocket,
|
|
814
|
-
handlers: () => handlers
|
|
574
|
+
//#region src/D1.ts
|
|
575
|
+
var D1_exports = /* @__PURE__ */ __exportAll({
|
|
576
|
+
Service: () => Service$1,
|
|
577
|
+
make: () => make$10
|
|
815
578
|
});
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
const wrappers = /* @__PURE__ */ new WeakMap();
|
|
823
|
-
/** Wraps a native Cloudflare websocket in the Effect-native Durable Object API. */
|
|
824
|
-
const fromWebSocket = (raw) => {
|
|
825
|
-
const existing = wrappers.get(raw);
|
|
826
|
-
if (existing !== void 0) return existing;
|
|
827
|
-
const socket = {
|
|
828
|
-
raw,
|
|
829
|
-
send: (data) => Effect.try({
|
|
830
|
-
try: () => raw.send(data),
|
|
831
|
-
catch: (cause) => new DurableWebSocketSendError({ cause })
|
|
832
|
-
}),
|
|
833
|
-
close: (code, reason) => Effect.try({
|
|
834
|
-
try: () => raw.close(code, reason),
|
|
835
|
-
catch: (cause) => new DurableWebSocketCloseError({ cause })
|
|
836
|
-
}),
|
|
837
|
-
serializeAttachment: (value) => Effect.try({
|
|
838
|
-
try: () => raw.serializeAttachment(value),
|
|
839
|
-
catch: (cause) => new DurableWebSocketAttachmentError({
|
|
840
|
-
operation: "serialize",
|
|
841
|
-
cause
|
|
842
|
-
})
|
|
843
|
-
}),
|
|
844
|
-
deserializeAttachment: Effect.try({
|
|
845
|
-
try: () => raw.deserializeAttachment(),
|
|
846
|
-
catch: (cause) => new DurableWebSocketAttachmentError({
|
|
847
|
-
operation: "deserialize",
|
|
848
|
-
cause
|
|
849
|
-
})
|
|
850
|
-
})
|
|
851
|
-
};
|
|
852
|
-
wrappers.set(raw, socket);
|
|
853
|
-
return socket;
|
|
579
|
+
const TypeId$2 = "effect-cf/D1";
|
|
580
|
+
const expectedD1Database = "D1 database binding with prepare(), batch(), and exec()";
|
|
581
|
+
const isD1Database = (value) => {
|
|
582
|
+
if (typeof value !== "object" || value === null) return false;
|
|
583
|
+
const resource = value;
|
|
584
|
+
return typeof resource.prepare === "function" && typeof resource.batch === "function" && typeof resource.exec === "function";
|
|
854
585
|
};
|
|
855
586
|
/**
|
|
856
|
-
*
|
|
587
|
+
* Creates a typed D1 service tag plus Effect helpers.
|
|
588
|
+
*/
|
|
589
|
+
const make$10 = (id, definition) => Service$1()(id, definition);
|
|
590
|
+
/**
|
|
591
|
+
* Builds a D1 service around a Cloudflare D1 database binding.
|
|
592
|
+
*
|
|
593
|
+
* The returned service exposes the raw `D1Database` binding and `sqlLayer(...)`
|
|
594
|
+
* for providing `effect/unstable/sql` via `@effect/sql-d1`.
|
|
857
595
|
*
|
|
858
596
|
* @example
|
|
859
597
|
* ```ts
|
|
860
|
-
*
|
|
861
|
-
*
|
|
862
|
-
* })
|
|
598
|
+
* class TodoDatabase extends D1.Service<TodoDatabase>()("TodoDatabase", {
|
|
599
|
+
* binding: "TODO_DB",
|
|
600
|
+
* }) {}
|
|
863
601
|
*
|
|
864
|
-
*
|
|
602
|
+
* const SqlLive = TodoDatabase.sqlLayer();
|
|
865
603
|
* ```
|
|
866
604
|
*/
|
|
867
|
-
const
|
|
868
|
-
const
|
|
869
|
-
const
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
})
|
|
881
|
-
};
|
|
882
|
-
});
|
|
883
|
-
/** Creates typed attachment helpers for accepted and rehydrated sockets. */
|
|
884
|
-
const attachment = (schema) => {
|
|
885
|
-
const serialize = (socket, value) => Schema.encodeEffect(schema)(value).pipe(Effect.mapError((cause) => new DurableWebSocketAttachmentError({
|
|
886
|
-
operation: "serialize",
|
|
887
|
-
cause
|
|
888
|
-
})), Effect.flatMap((encoded) => socket.serializeAttachment(encoded)));
|
|
889
|
-
const deserialize = (socket) => Effect.gen(function* () {
|
|
890
|
-
const value = yield* socket.deserializeAttachment;
|
|
891
|
-
if (value == null) return Option.none();
|
|
892
|
-
return Option.some(yield* Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError((cause) => new DurableWebSocketAttachmentError({
|
|
893
|
-
operation: "deserialize",
|
|
894
|
-
cause
|
|
895
|
-
}))));
|
|
605
|
+
const Service$1 = () => (id, definition) => {
|
|
606
|
+
const tag = Service$2()(id, definition.binding, isD1Database, void 0, { expected: expectedD1Database });
|
|
607
|
+
const sqlLayer = (options) => Layer.unwrap(Effect.gen(function* () {
|
|
608
|
+
const db = yield* tag;
|
|
609
|
+
return D1Client.layer({
|
|
610
|
+
...options,
|
|
611
|
+
db
|
|
612
|
+
});
|
|
613
|
+
})).pipe(Layer.provide(tag.layer));
|
|
614
|
+
return Object.assign(tag, {
|
|
615
|
+
[TypeId$2]: TypeId$2,
|
|
616
|
+
definition,
|
|
617
|
+
sqlLayer
|
|
896
618
|
});
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
619
|
+
};
|
|
620
|
+
//#endregion
|
|
621
|
+
//#region src/QueueBinding.ts
|
|
622
|
+
var QueueBinding_exports = /* @__PURE__ */ __exportAll({
|
|
623
|
+
QueueOperationError: () => QueueOperationError,
|
|
624
|
+
isQueue: () => isQueue,
|
|
625
|
+
layer: () => layer$8,
|
|
626
|
+
makeClient: () => makeClient$6
|
|
627
|
+
});
|
|
628
|
+
const expectedQueueProducer = "Queue producer binding with send(); optional sendBatch()/metrics()";
|
|
629
|
+
var QueueOperationError = class extends Data.TaggedError("QueueOperationError") {};
|
|
630
|
+
const tryQueuePromise = (binding, operation, evaluate) => Effect.tryPromise({
|
|
631
|
+
try: evaluate,
|
|
632
|
+
catch: (cause) => new QueueOperationError({
|
|
633
|
+
binding,
|
|
634
|
+
operation,
|
|
635
|
+
cause,
|
|
636
|
+
message: `Cloudflare queue binding "${binding}" operation "${operation}" failed`
|
|
637
|
+
})
|
|
638
|
+
});
|
|
639
|
+
const isQueue = (value) => {
|
|
640
|
+
if (typeof value !== "object" || value === null) return false;
|
|
641
|
+
return typeof value.send === "function";
|
|
642
|
+
};
|
|
643
|
+
const makeClient$6 = (definition) => {
|
|
644
|
+
const encodeMessage = Schema.encodeEffect(definition.message);
|
|
645
|
+
return (queue) => ({
|
|
646
|
+
send: Effect.fnUntraced(function* (message, options) {
|
|
647
|
+
const encoded = yield* encodeMessage(message);
|
|
648
|
+
yield* tryQueuePromise(definition.binding, "send", () => queue.send(encoded, options));
|
|
649
|
+
}),
|
|
650
|
+
sendBatch: Effect.fnUntraced(function* (messages, options) {
|
|
651
|
+
const encodedMessages = [];
|
|
652
|
+
for (const message of messages) encodedMessages.push({
|
|
653
|
+
...message,
|
|
654
|
+
body: yield* encodeMessage(message.body)
|
|
655
|
+
});
|
|
656
|
+
const sendBatch = queue.sendBatch;
|
|
657
|
+
if (sendBatch !== void 0) {
|
|
658
|
+
yield* tryQueuePromise(definition.binding, "sendBatch", () => sendBatch.call(queue, encodedMessages, options));
|
|
659
|
+
return;
|
|
918
660
|
}
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
661
|
+
yield* tryQueuePromise(definition.binding, "sendBatch", async () => {
|
|
662
|
+
for (const message of encodedMessages) await queue.send(message.body, {
|
|
663
|
+
contentType: message.contentType,
|
|
664
|
+
delaySeconds: message.delaySeconds ?? options?.delaySeconds
|
|
665
|
+
});
|
|
666
|
+
});
|
|
667
|
+
}),
|
|
668
|
+
metrics: () => {
|
|
669
|
+
const metrics = queue.metrics;
|
|
670
|
+
if (metrics === void 0) return Effect.fail(new QueueOperationError({
|
|
671
|
+
binding: definition.binding,
|
|
672
|
+
operation: "metrics",
|
|
673
|
+
cause: /* @__PURE__ */ new Error(`Queue binding "${definition.binding}" does not provide metrics()`),
|
|
674
|
+
message: `Cloudflare queue binding "${definition.binding}" does not provide metrics()`
|
|
675
|
+
}));
|
|
676
|
+
return tryQueuePromise(definition.binding, "metrics", () => metrics.call(queue));
|
|
677
|
+
},
|
|
678
|
+
unsafeRaw: Effect.succeed(queue)
|
|
923
679
|
});
|
|
924
|
-
return {
|
|
925
|
-
serialize,
|
|
926
|
-
deserialize,
|
|
927
|
-
rehydrate,
|
|
928
|
-
schema
|
|
929
|
-
};
|
|
930
680
|
};
|
|
931
|
-
|
|
932
|
-
const handlers = (options) => ({
|
|
933
|
-
webSocketMessage: options.message,
|
|
934
|
-
webSocketClose: options.close,
|
|
935
|
-
webSocketError: options.error
|
|
936
|
-
});
|
|
681
|
+
const layer$8 = (tag, definition) => layer$10(tag, definition.binding, (value) => isQueue(value), makeClient$6(definition), { expected: expectedQueueProducer });
|
|
937
682
|
//#endregion
|
|
938
|
-
//#region src/
|
|
939
|
-
var
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
* Context tag for accessing the current Durable Object state service.
|
|
945
|
-
*/
|
|
946
|
-
var DurableObjectState = class extends Context.Service()("effect-cf/DurableObjectState") {};
|
|
947
|
-
/**
|
|
948
|
-
* Wraps a native Cloudflare `DurableObjectState` as a {@link DurableObjectStateService}.
|
|
949
|
-
*/
|
|
950
|
-
const fromDurableObjectState = (state) => ({
|
|
951
|
-
raw: state,
|
|
952
|
-
id: state.id,
|
|
953
|
-
storage: fromDurableObjectStorage(state.storage),
|
|
954
|
-
waitUntil: (promise) => Effect.sync(() => state.waitUntil(promise)),
|
|
955
|
-
blockConcurrencyWhile: (effect) => Effect.context().pipe(Effect.flatMap((context) => Effect.promise(() => state.blockConcurrencyWhile(() => runPromiseExitPreservingTypedFailures(Effect.provideContext(effect, context))))), Effect.flatten),
|
|
956
|
-
blockConcurrencyWhileOrReset: (effect) => Effect.context().pipe(Effect.flatMap((context) => Effect.promise(() => state.blockConcurrencyWhile(() => Effect.runPromise(Effect.provideContext(effect, context)))))),
|
|
957
|
-
acceptWebSocket: (ws, tags) => Effect.sync(() => state.acceptWebSocket(ws.raw, tags)),
|
|
958
|
-
getWebSockets: (tag) => Effect.sync(() => state.getWebSockets(tag).map((socket) => fromWebSocket(socket))),
|
|
959
|
-
setWebSocketAutoResponse: (pair) => Effect.sync(() => state.setWebSocketAutoResponse(pair)),
|
|
960
|
-
getWebSocketAutoResponse: Effect.sync(() => state.getWebSocketAutoResponse()),
|
|
961
|
-
getWebSocketAutoResponseTimestamp: (ws) => Effect.sync(() => state.getWebSocketAutoResponseTimestamp(ws.raw)),
|
|
962
|
-
setHibernatableWebSocketEventTimeout: (timeoutMs) => Effect.sync(() => state.setHibernatableWebSocketEventTimeout(timeoutMs)),
|
|
963
|
-
getHibernatableWebSocketEventTimeout: Effect.sync(() => state.getHibernatableWebSocketEventTimeout()),
|
|
964
|
-
getTags: (ws) => Effect.sync(() => state.getTags(ws.raw)),
|
|
965
|
-
abort: (reason) => Effect.sync(() => state.abort(reason))
|
|
683
|
+
//#region src/QueueDefinition.ts
|
|
684
|
+
var QueueDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
685
|
+
Queue: () => Queue$1,
|
|
686
|
+
Tag: () => Tag$10,
|
|
687
|
+
implement: () => implement$7,
|
|
688
|
+
make: () => make$9
|
|
966
689
|
});
|
|
967
|
-
const
|
|
968
|
-
const
|
|
969
|
-
|
|
970
|
-
|
|
690
|
+
const makeDefinition$4 = (id, definition) => {
|
|
691
|
+
const queueDefinition = {
|
|
692
|
+
id,
|
|
693
|
+
message: definition.message
|
|
694
|
+
};
|
|
695
|
+
return Object.assign(queueDefinition, { make: (layer, options) => make$6(layer, {
|
|
696
|
+
...options,
|
|
697
|
+
queue: wrapHandler$1(queueDefinition, options.queue)
|
|
698
|
+
}) });
|
|
699
|
+
};
|
|
700
|
+
const make$9 = (id, definition) => Tag$10()(id, definition);
|
|
701
|
+
const Tag$10 = () => (id, definition) => {
|
|
702
|
+
const queueDefinition = makeDefinition$4(id, definition);
|
|
703
|
+
const tag = Context.Service()(id);
|
|
704
|
+
const layer = (binding) => layer$8(tag, {
|
|
705
|
+
...binding,
|
|
706
|
+
message: definition.message
|
|
707
|
+
});
|
|
708
|
+
const send = Effect.fnUntraced(function* (message, options) {
|
|
709
|
+
yield* (yield* tag).send(message, options);
|
|
710
|
+
});
|
|
711
|
+
const sendBatch = Effect.fnUntraced(function* (messages, options) {
|
|
712
|
+
yield* (yield* tag).sendBatch(messages, options);
|
|
713
|
+
});
|
|
714
|
+
const metrics = Effect.fnUntraced(function* () {
|
|
715
|
+
return yield* (yield* tag).metrics();
|
|
716
|
+
});
|
|
717
|
+
const unsafeRaw = Effect.fnUntraced(function* () {
|
|
718
|
+
return yield* (yield* tag).unsafeRaw;
|
|
719
|
+
});
|
|
720
|
+
return Object.assign(tag, {
|
|
721
|
+
id: queueDefinition.id,
|
|
722
|
+
message: queueDefinition.message,
|
|
723
|
+
make: queueDefinition.make,
|
|
724
|
+
layer,
|
|
725
|
+
send,
|
|
726
|
+
sendBatch,
|
|
727
|
+
metrics,
|
|
728
|
+
unsafeRaw
|
|
729
|
+
});
|
|
730
|
+
};
|
|
731
|
+
const Queue$1 = Tag$10;
|
|
732
|
+
const wrapHandler$1 = (definition, handler) => {
|
|
733
|
+
const decodeBody = Schema.decodeUnknownEffect(definition.message);
|
|
734
|
+
return (batch) => Effect.gen(function* () {
|
|
735
|
+
yield* handler(yield* decodeBatch(batch.raw, decodeBody));
|
|
736
|
+
});
|
|
971
737
|
};
|
|
738
|
+
const implement$7 = (_definition, handler) => handler;
|
|
972
739
|
//#endregion
|
|
973
|
-
//#region src/
|
|
974
|
-
var
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
740
|
+
//#region src/Queue.ts
|
|
741
|
+
var Queue_exports = /* @__PURE__ */ __exportAll({
|
|
742
|
+
QueueMessageDecodeError: () => QueueMessageDecodeError,
|
|
743
|
+
Tag: () => Tag$9,
|
|
744
|
+
decodeBatch: () => decodeBatch,
|
|
745
|
+
fromMessage: () => fromMessage,
|
|
746
|
+
fromMessageBatch: () => fromMessageBatch,
|
|
747
|
+
implement: () => implement$6
|
|
981
748
|
});
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
749
|
+
var QueueMessageDecodeError = class extends Data.TaggedError("QueueMessageDecodeError") {};
|
|
750
|
+
const fromMessage = (message, body) => ({
|
|
751
|
+
raw: message,
|
|
752
|
+
id: message.id,
|
|
753
|
+
timestamp: message.timestamp,
|
|
754
|
+
body,
|
|
755
|
+
attempts: message.attempts,
|
|
756
|
+
ack: Effect.sync(() => message.ack()),
|
|
757
|
+
retry: (options) => Effect.sync(() => message.retry(options))
|
|
758
|
+
});
|
|
759
|
+
const fromMessageBatch = (batch, messages) => ({
|
|
760
|
+
raw: batch,
|
|
761
|
+
messages,
|
|
762
|
+
queue: batch.queue,
|
|
763
|
+
metadata: batch.metadata,
|
|
764
|
+
ackAll: Effect.sync(() => batch.ackAll()),
|
|
765
|
+
retryAll: (options) => Effect.sync(() => batch.retryAll(options))
|
|
766
|
+
});
|
|
767
|
+
const decodeBatch = (batch, decodeBody) => Effect.gen(function* () {
|
|
768
|
+
const messages = [];
|
|
769
|
+
for (let index = 0; index < batch.messages.length; index++) {
|
|
770
|
+
const message = batch.messages[index];
|
|
771
|
+
const body = yield* decodeBody(message.body).pipe(Effect.mapError((cause) => new QueueMessageDecodeError({
|
|
772
|
+
queue: batch.queue,
|
|
773
|
+
messageId: message.id,
|
|
774
|
+
index,
|
|
775
|
+
cause
|
|
776
|
+
})));
|
|
777
|
+
messages.push(fromMessage(message, body));
|
|
778
|
+
}
|
|
779
|
+
return fromMessageBatch(batch, messages);
|
|
780
|
+
});
|
|
781
|
+
const Tag$9 = Tag$10;
|
|
782
|
+
const implement$6 = implement$7;
|
|
783
|
+
//#endregion
|
|
784
|
+
//#region src/RpcDefinition.ts
|
|
785
|
+
var RpcDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
786
|
+
ReservedMethodNameError: () => ReservedMethodNameError,
|
|
787
|
+
RpcArgumentCountError: () => RpcArgumentCountError,
|
|
788
|
+
RpcArgumentDecodeError: () => RpcArgumentDecodeError,
|
|
789
|
+
RpcArgumentEncodeError: () => RpcArgumentEncodeError,
|
|
790
|
+
RpcReservedMethodNameError: () => RpcReservedMethodNameError,
|
|
791
|
+
RpcSuccessDecodeError: () => RpcSuccessDecodeError,
|
|
792
|
+
RpcSuccessEncodeError: () => RpcSuccessEncodeError,
|
|
793
|
+
assertNoReservedMethodNames: () => assertNoReservedMethodNames,
|
|
794
|
+
assertNoReservedMethods: () => assertNoReservedMethods,
|
|
795
|
+
decodeArgs: () => decodeArgs,
|
|
796
|
+
decodeSuccess: () => decodeSuccess,
|
|
797
|
+
encodeArgs: () => encodeArgs,
|
|
798
|
+
encodeSuccess: () => encodeSuccess,
|
|
799
|
+
make: () => make$8,
|
|
800
|
+
method: () => method$4,
|
|
801
|
+
reservedMethodNames: () => reservedMethodNames$4
|
|
802
|
+
});
|
|
803
|
+
var RpcReservedMethodNameError = class extends Data.TaggedError("RpcReservedMethodNameError") {};
|
|
804
|
+
var RpcArgumentCountError = class extends Data.TaggedError("RpcArgumentCountError") {};
|
|
805
|
+
var RpcArgumentDecodeError = class extends Data.TaggedError("RpcArgumentDecodeError") {};
|
|
806
|
+
var RpcArgumentEncodeError = class extends Data.TaggedError("RpcArgumentEncodeError") {};
|
|
807
|
+
var RpcSuccessDecodeError = class extends Data.TaggedError("RpcSuccessDecodeError") {};
|
|
808
|
+
var RpcSuccessEncodeError = class extends Data.TaggedError("RpcSuccessEncodeError") {};
|
|
809
|
+
const reservedMethodNames$4 = new Set([
|
|
810
|
+
"constructor",
|
|
811
|
+
"fetch",
|
|
812
|
+
"connect",
|
|
813
|
+
"alarm",
|
|
814
|
+
"webSocketMessage",
|
|
815
|
+
"webSocketClose",
|
|
816
|
+
"webSocketError",
|
|
817
|
+
"then",
|
|
818
|
+
"dup",
|
|
819
|
+
"dispose",
|
|
820
|
+
"serialize",
|
|
821
|
+
"deserialize"
|
|
822
|
+
]);
|
|
823
|
+
var ReservedMethodNameError = class extends Error {
|
|
824
|
+
method;
|
|
825
|
+
target;
|
|
826
|
+
constructor(target, method) {
|
|
827
|
+
super(`${target} RPC method "${method}" is reserved by Cloudflare Workers RPC`);
|
|
828
|
+
this.name = "ReservedMethodNameError";
|
|
829
|
+
this.target = target;
|
|
830
|
+
this.method = method;
|
|
831
|
+
}
|
|
832
|
+
};
|
|
833
|
+
const assertNoReservedMethods = (target, methods, reserved) => {
|
|
834
|
+
for (const method of Object.keys(methods)) if (reserved.has(method)) throw new ReservedMethodNameError(target, method);
|
|
835
|
+
};
|
|
836
|
+
function method$4(definition) {
|
|
837
|
+
return {
|
|
838
|
+
args: definition.args ?? [],
|
|
839
|
+
success: definition.success
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
const assertNoReservedMethodNames = (definition) => Effect.forEach(Object.keys(definition.methods), (method) => reservedMethodNames$4.has(method) ? Effect.fail(new RpcReservedMethodNameError({
|
|
843
|
+
definition: definition.id,
|
|
844
|
+
method
|
|
845
|
+
})) : Effect.void).pipe(Effect.asVoid);
|
|
846
|
+
const decodeArgs = (definition, methodName, args) => Effect.gen(function* () {
|
|
847
|
+
const methodDefinition = definition.methods[methodName];
|
|
848
|
+
if (args.length !== methodDefinition.args.length) return yield* Effect.fail(new RpcArgumentCountError({
|
|
849
|
+
definition: definition.id,
|
|
850
|
+
method: methodName,
|
|
851
|
+
expected: methodDefinition.args.length,
|
|
852
|
+
actual: args.length
|
|
853
|
+
}));
|
|
854
|
+
const decoded = [];
|
|
855
|
+
for (let index = 0; index < methodDefinition.args.length; index++) {
|
|
856
|
+
const schema = methodDefinition.args[index];
|
|
857
|
+
decoded.push(yield* Schema.decodeUnknownEffect(schema)(args[index]).pipe(Effect.mapError((cause) => new RpcArgumentDecodeError({
|
|
858
|
+
definition: definition.id,
|
|
859
|
+
method: methodName,
|
|
860
|
+
index,
|
|
861
|
+
cause
|
|
862
|
+
}))));
|
|
863
|
+
}
|
|
864
|
+
return decoded;
|
|
865
|
+
});
|
|
866
|
+
const encodeArgs = (definition, methodName, args) => Effect.gen(function* () {
|
|
867
|
+
const methodDefinition = definition.methods[methodName];
|
|
868
|
+
if (args.length !== methodDefinition.args.length) return yield* Effect.fail(new RpcArgumentCountError({
|
|
869
|
+
definition: definition.id,
|
|
870
|
+
method: methodName,
|
|
871
|
+
expected: methodDefinition.args.length,
|
|
872
|
+
actual: args.length
|
|
873
|
+
}));
|
|
874
|
+
const encoded = [];
|
|
875
|
+
for (let index = 0; index < methodDefinition.args.length; index++) {
|
|
876
|
+
const schema = methodDefinition.args[index];
|
|
877
|
+
encoded.push(yield* Schema.encodeEffect(schema)(args[index]).pipe(Effect.mapError((cause) => new RpcArgumentEncodeError({
|
|
878
|
+
definition: definition.id,
|
|
879
|
+
method: methodName,
|
|
880
|
+
index,
|
|
881
|
+
cause
|
|
882
|
+
}))));
|
|
883
|
+
}
|
|
884
|
+
return encoded;
|
|
885
|
+
});
|
|
886
|
+
const encodeSuccess = (definition, methodName, value) => {
|
|
887
|
+
const methodDefinition = definition.methods[methodName];
|
|
888
|
+
return Schema.encodeEffect(methodDefinition.success)(value).pipe(Effect.mapError((cause) => new RpcSuccessEncodeError({
|
|
889
|
+
definition: definition.id,
|
|
890
|
+
method: methodName,
|
|
891
|
+
cause
|
|
892
|
+
})));
|
|
893
|
+
};
|
|
894
|
+
const decodeSuccess = (definition, methodName, value) => {
|
|
895
|
+
const methodDefinition = definition.methods[methodName];
|
|
896
|
+
return Schema.decodeUnknownEffect(methodDefinition.success)(value).pipe(Effect.mapError((cause) => new RpcSuccessDecodeError({
|
|
897
|
+
definition: definition.id,
|
|
898
|
+
method: methodName,
|
|
899
|
+
cause
|
|
900
|
+
})));
|
|
901
|
+
};
|
|
902
|
+
const make$8 = (id, methods) => {
|
|
903
|
+
const definition = {
|
|
904
|
+
id,
|
|
905
|
+
methods
|
|
906
|
+
};
|
|
907
|
+
const reserved = Object.keys(definition.methods).find((methodName) => reservedMethodNames$4.has(methodName));
|
|
908
|
+
if (reserved !== void 0) throw new RpcReservedMethodNameError({
|
|
909
|
+
definition: id,
|
|
910
|
+
method: reserved
|
|
911
|
+
});
|
|
912
|
+
return definition;
|
|
913
|
+
};
|
|
914
|
+
//#endregion
|
|
915
|
+
//#region src/Rpc.ts
|
|
916
|
+
var Rpc_exports = /* @__PURE__ */ __exportAll({
|
|
917
|
+
RpcStub: () => RpcStub,
|
|
918
|
+
RpcTarget: () => RpcTarget,
|
|
919
|
+
dispose: () => dispose,
|
|
920
|
+
isDisposable: () => isDisposable,
|
|
921
|
+
resolve: () => resolve,
|
|
922
|
+
scoped: () => scoped
|
|
923
|
+
});
|
|
924
|
+
const isDisposable = (value) => (typeof value === "object" || typeof value === "function") && value !== null && Symbol.dispose in value && typeof value[Symbol.dispose] === "function";
|
|
925
|
+
const dispose = (value) => Effect.sync(() => {
|
|
926
|
+
if (isDisposable(value)) value[Symbol.dispose]();
|
|
927
|
+
});
|
|
928
|
+
const resolve = (value) => isPromiseLike(value) ? Effect.tryPromise({
|
|
929
|
+
try: () => value,
|
|
930
|
+
catch: (cause) => cause
|
|
931
|
+
}) : Effect.sync(() => value);
|
|
932
|
+
const scoped = (value) => Effect.acquireRelease(resolve(value), (resolved) => dispose(resolved));
|
|
933
|
+
const isPromiseLike = (value) => (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
|
|
934
|
+
//#endregion
|
|
935
|
+
//#region src/internal/RpcInvocation.ts
|
|
936
|
+
const isPropertyTarget = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
|
|
937
|
+
const lookupRpcMethod = (target, method, makeError) => Effect.try({
|
|
938
|
+
try: () => {
|
|
939
|
+
if (!isPropertyTarget(target)) throw new TypeError(`RPC target is not object-like`);
|
|
940
|
+
const value = Reflect.get(target, method);
|
|
941
|
+
if (typeof value !== "function") throw new TypeError(`RPC method "${String(method)}" is not callable`);
|
|
942
|
+
return ((...args) => Reflect.apply(value, target, args));
|
|
943
|
+
},
|
|
944
|
+
catch: makeError
|
|
945
|
+
});
|
|
946
|
+
const invokeRpcMethod = (target, method, args, makeError) => Effect.gen(function* () {
|
|
947
|
+
const fn = yield* lookupRpcMethod(target, method, makeError);
|
|
948
|
+
return yield* Effect.try({
|
|
949
|
+
try: () => fn(...args),
|
|
950
|
+
catch: makeError
|
|
951
|
+
});
|
|
952
|
+
});
|
|
953
|
+
//#endregion
|
|
954
|
+
//#region src/ServiceBinding.ts
|
|
955
|
+
var ServiceBinding_exports = /* @__PURE__ */ __exportAll({
|
|
956
|
+
Service: () => Service,
|
|
957
|
+
ServiceBindingFetchError: () => ServiceBindingFetchError,
|
|
958
|
+
ServiceBindingRpcError: () => ServiceBindingRpcError,
|
|
959
|
+
isServiceBindingClient: () => isServiceBindingClient,
|
|
960
|
+
layer: () => layer$7,
|
|
961
|
+
makeClient: () => makeClient$5,
|
|
962
|
+
makeDirectMethods: () => makeDirectMethods$1
|
|
963
|
+
});
|
|
964
|
+
const TypeId$1 = "effect-cf/ServiceBinding";
|
|
965
|
+
const expectedServiceBinding = "Worker service binding with fetch()";
|
|
987
966
|
/**
|
|
988
|
-
* Failure raised when
|
|
967
|
+
* Failure raised when calling `fetch` on a service binding.
|
|
989
968
|
*/
|
|
990
|
-
var
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
const
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
const fetch = (stub, input, init) => Effect.tryPromise({
|
|
1002
|
-
try: () => stub.fetch(input, init),
|
|
1003
|
-
catch: (cause) => new DurableObjectFetchError({
|
|
969
|
+
var ServiceBindingFetchError = class extends Data.TaggedError("ServiceBindingFetchError") {};
|
|
970
|
+
/**
|
|
971
|
+
* Failure raised when invoking an RPC method on a service binding.
|
|
972
|
+
*/
|
|
973
|
+
var ServiceBindingRpcError = class extends Data.TaggedError("ServiceBindingRpcError") {};
|
|
974
|
+
const isServiceBindingClient = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "fetch") === "function";
|
|
975
|
+
const makeClient$5 = (definition) => {
|
|
976
|
+
return (service) => {
|
|
977
|
+
const fetch = (input, init) => Effect.tryPromise({
|
|
978
|
+
try: () => service.fetch(input, init),
|
|
979
|
+
catch: (cause) => new ServiceBindingFetchError({
|
|
1004
980
|
binding: definition.binding,
|
|
1005
981
|
cause
|
|
1006
982
|
})
|
|
1007
983
|
});
|
|
1008
|
-
const rpc = (
|
|
984
|
+
const rpc = (method, ...args) => Effect.gen(function* () {
|
|
1009
985
|
const methodName = String(method);
|
|
1010
|
-
return yield* invokeRpcMethod(
|
|
986
|
+
return yield* invokeRpcMethod(service, method, definition.definition === void 0 ? args : yield* encodeArgs(definition.definition, methodName, args).pipe(Effect.mapError((cause) => new ServiceBindingRpcError({
|
|
1011
987
|
binding: definition.binding,
|
|
1012
988
|
method: methodName,
|
|
1013
989
|
cause
|
|
1014
|
-
}))), (cause) => new
|
|
990
|
+
}))), (cause) => new ServiceBindingRpcError({
|
|
1015
991
|
binding: definition.binding,
|
|
1016
992
|
method: methodName,
|
|
1017
993
|
cause
|
|
1018
994
|
}));
|
|
1019
995
|
});
|
|
1020
|
-
const decodeSuccess$
|
|
996
|
+
const decodeSuccess$2 = (methodName, value) => Effect.gen(function* () {
|
|
1021
997
|
if (definition.definition === void 0) return value;
|
|
1022
|
-
return yield* decodeSuccess(definition.definition, methodName, value).pipe(Effect.mapError((cause) => new
|
|
998
|
+
return yield* decodeSuccess(definition.definition, methodName, value).pipe(Effect.mapError((cause) => new ServiceBindingRpcError({
|
|
1023
999
|
binding: definition.binding,
|
|
1024
1000
|
method: methodName,
|
|
1025
1001
|
cause
|
|
1026
1002
|
})));
|
|
1027
1003
|
});
|
|
1028
|
-
const call = (
|
|
1004
|
+
const call = (method, ...args) => Effect.gen(function* () {
|
|
1029
1005
|
const methodName = String(method);
|
|
1030
|
-
return yield* decodeSuccess$
|
|
1006
|
+
return yield* decodeSuccess$2(methodName, yield* resolve(yield* rpc(method, ...args)).pipe(Effect.mapError((cause) => new ServiceBindingRpcError({
|
|
1031
1007
|
binding: definition.binding,
|
|
1032
1008
|
method: methodName,
|
|
1033
1009
|
cause
|
|
1034
1010
|
}))));
|
|
1035
1011
|
});
|
|
1036
|
-
const scopedCall = (
|
|
1037
|
-
return yield* decodeSuccess$
|
|
1038
|
-
});
|
|
1039
|
-
const directMethods = makeDirectMethods(definition.definition, {
|
|
1040
|
-
call,
|
|
1041
|
-
fetch,
|
|
1042
|
-
get,
|
|
1043
|
-
getByName
|
|
1012
|
+
const scopedCall = (method, ...args) => Effect.gen(function* () {
|
|
1013
|
+
return yield* decodeSuccess$2(String(method), yield* scoped(yield* rpc(method, ...args)));
|
|
1044
1014
|
});
|
|
1015
|
+
const directMethods = makeDirectMethods$1(definition.definition, call);
|
|
1045
1016
|
return Object.assign(directMethods, {
|
|
1046
|
-
newUniqueId,
|
|
1047
|
-
idFromName,
|
|
1048
|
-
idFromString,
|
|
1049
|
-
get,
|
|
1050
|
-
getByName,
|
|
1051
|
-
jurisdiction,
|
|
1052
1017
|
fetch,
|
|
1053
1018
|
rpc,
|
|
1054
1019
|
call,
|
|
1055
|
-
scopedCall
|
|
1056
|
-
unsafeRaw: Effect.succeed(namespace)
|
|
1020
|
+
scopedCall
|
|
1057
1021
|
});
|
|
1058
1022
|
};
|
|
1059
1023
|
};
|
|
1060
|
-
const layer$7 = (tag, definition) => layer$10(tag, definition.binding, (value) =>
|
|
1061
|
-
|
|
1024
|
+
const layer$7 = (tag, definition) => layer$10(tag, definition.binding, (value) => isServiceBindingClient(value), makeClient$5(definition), { expected: expectedServiceBinding });
|
|
1025
|
+
/**
|
|
1026
|
+
* Creates a typed Effect service for a Worker service binding.
|
|
1027
|
+
*
|
|
1028
|
+
* Returned value includes:
|
|
1029
|
+
* - a Context tag for dependency injection
|
|
1030
|
+
* - `fetch(...)` for raw HTTP forwarding
|
|
1031
|
+
* - `rpc(...)` for raw Cloudflare RPC results
|
|
1032
|
+
* - `call(...)` for resolved and decoded RPC results
|
|
1033
|
+
* - `scopedCall(...)` for scoped and decoded disposable RPC results
|
|
1034
|
+
* - direct RPC methods when `definition` is provided
|
|
1035
|
+
*
|
|
1036
|
+
* @example
|
|
1037
|
+
* ```ts
|
|
1038
|
+
* const Counter = WorkerDefinition.make("Counter", {
|
|
1039
|
+
* increment: WorkerDefinition.method({
|
|
1040
|
+
* args: [Schema.Number],
|
|
1041
|
+
* success: Schema.Number,
|
|
1042
|
+
* }),
|
|
1043
|
+
* });
|
|
1044
|
+
*
|
|
1045
|
+
* const CounterLive = Counter.layer({ binding: "COUNTER" });
|
|
1046
|
+
*
|
|
1047
|
+
* const program = Effect.gen(function* () {
|
|
1048
|
+
* const counter = yield* Counter;
|
|
1049
|
+
* const next = yield* counter.increment(1);
|
|
1050
|
+
* return next;
|
|
1051
|
+
* });
|
|
1052
|
+
* ```
|
|
1053
|
+
*/
|
|
1054
|
+
const Service = () => (id, definition) => {
|
|
1055
|
+
const tag = Service$2()(id, definition.binding, (value) => isServiceBindingClient(value), makeClient$5(definition));
|
|
1056
|
+
const fetch = (input, init) => Effect.gen(function* () {
|
|
1057
|
+
return yield* (yield* tag).fetch(input, init);
|
|
1058
|
+
});
|
|
1059
|
+
const rpc = (method, ...args) => Effect.gen(function* () {
|
|
1060
|
+
return yield* (yield* tag).rpc(method, ...args);
|
|
1061
|
+
});
|
|
1062
|
+
const call = (method, ...args) => Effect.gen(function* () {
|
|
1063
|
+
return yield* (yield* tag).call(method, ...args);
|
|
1064
|
+
});
|
|
1065
|
+
const scopedCall = (method, ...args) => Effect.gen(function* () {
|
|
1066
|
+
return yield* (yield* tag).scopedCall(method, ...args);
|
|
1067
|
+
});
|
|
1068
|
+
const directMethods = makeDirectMethods$1(definition.definition, call);
|
|
1069
|
+
return Object.assign(tag, directMethods, {
|
|
1070
|
+
[TypeId$1]: TypeId$1,
|
|
1071
|
+
definition,
|
|
1072
|
+
fetch,
|
|
1073
|
+
rpc,
|
|
1074
|
+
call,
|
|
1075
|
+
scopedCall
|
|
1076
|
+
});
|
|
1077
|
+
};
|
|
1078
|
+
const makeDirectMethods$1 = (rpcDefinition, call) => {
|
|
1062
1079
|
const methods = {};
|
|
1063
|
-
if (rpcDefinition !== void 0)
|
|
1064
|
-
for (const methodName of Object.keys(rpcDefinition.methods)) methods[methodName] = (stub, ...args) => helpers.call(stub, methodName, ...args);
|
|
1065
|
-
const makeClient = (getStub) => {
|
|
1066
|
-
const client = { fetch: (input, init) => Effect.gen(function* () {
|
|
1067
|
-
const stub = yield* getStub();
|
|
1068
|
-
return yield* helpers.fetch(stub, input, init);
|
|
1069
|
-
}) };
|
|
1070
|
-
for (const methodName of Object.keys(rpcDefinition.methods)) client[methodName] = (...args) => Effect.gen(function* () {
|
|
1071
|
-
const stub = yield* getStub();
|
|
1072
|
-
return yield* helpers.call(stub, methodName, ...args);
|
|
1073
|
-
});
|
|
1074
|
-
return client;
|
|
1075
|
-
};
|
|
1076
|
-
methods.byName = (name, options) => makeClient(() => helpers.getByName(name, options));
|
|
1077
|
-
methods.byId = (id, options) => makeClient(() => helpers.get(id, options));
|
|
1078
|
-
}
|
|
1080
|
+
if (rpcDefinition !== void 0) for (const methodName of Object.keys(rpcDefinition.methods)) methods[methodName] = (...args) => call(methodName, ...args);
|
|
1079
1081
|
return methods;
|
|
1080
1082
|
};
|
|
1081
1083
|
//#endregion
|
|
1082
|
-
//#region src/
|
|
1083
|
-
var
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
implement: () => implement$
|
|
1087
|
-
make: () => make$
|
|
1088
|
-
method: () => method$
|
|
1084
|
+
//#region src/WorkerDefinition.ts
|
|
1085
|
+
var WorkerDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
1086
|
+
Tag: () => Tag$8,
|
|
1087
|
+
Worker: () => Worker,
|
|
1088
|
+
implement: () => implement$5,
|
|
1089
|
+
make: () => make$7,
|
|
1090
|
+
method: () => method$3
|
|
1089
1091
|
});
|
|
1090
|
-
const reservedMethodNames$
|
|
1092
|
+
const reservedMethodNames$3 = new Set([
|
|
1091
1093
|
"constructor",
|
|
1092
1094
|
"dup",
|
|
1093
1095
|
"fetch",
|
|
1096
|
+
"connect",
|
|
1097
|
+
"queue",
|
|
1098
|
+
"scheduled",
|
|
1099
|
+
"tail",
|
|
1100
|
+
"tailStream",
|
|
1101
|
+
"test",
|
|
1102
|
+
"trace",
|
|
1094
1103
|
"alarm",
|
|
1095
1104
|
"webSocketMessage",
|
|
1096
1105
|
"webSocketClose",
|
|
1097
1106
|
"webSocketError"
|
|
1098
1107
|
]);
|
|
1099
1108
|
/**
|
|
1100
|
-
* Defines a single RPC method schema in a
|
|
1109
|
+
* Defines a single RPC method schema in a worker definition.
|
|
1101
1110
|
*/
|
|
1102
|
-
const method$
|
|
1111
|
+
const method$3 = method$4;
|
|
1103
1112
|
/**
|
|
1104
|
-
* Creates a
|
|
1113
|
+
* Creates a typed worker RPC definition plus helpers for implementation and bindings.
|
|
1105
1114
|
*
|
|
1106
1115
|
* @example
|
|
1107
1116
|
* ```ts
|
|
1108
|
-
* const
|
|
1109
|
-
*
|
|
1110
|
-
* args: [Schema.
|
|
1111
|
-
* success: Schema.
|
|
1117
|
+
* const CounterWorker = WorkerDefinition.make("CounterWorker", {
|
|
1118
|
+
* increment: WorkerDefinition.method({
|
|
1119
|
+
* args: [Schema.Number],
|
|
1120
|
+
* success: Schema.Number,
|
|
1112
1121
|
* }),
|
|
1113
1122
|
* });
|
|
1114
1123
|
* ```
|
|
1115
1124
|
*/
|
|
1116
|
-
const makeDefinition$
|
|
1117
|
-
assertNoReservedMethods("
|
|
1118
|
-
const definition = make$
|
|
1119
|
-
return Object.assign(definition, { make: (layer, options) => make$
|
|
1125
|
+
const makeDefinition$3 = (id, methods) => {
|
|
1126
|
+
assertNoReservedMethods("Worker", methods, reservedMethodNames$3);
|
|
1127
|
+
const definition = make$8(id, methods);
|
|
1128
|
+
return Object.assign(definition, { make: (layer, options) => make$6(layer, {
|
|
1120
1129
|
...options,
|
|
1121
|
-
rpc: wrapHandlers(definition, options.rpc)
|
|
1130
|
+
rpc: wrapHandlers$1(definition, options.rpc)
|
|
1122
1131
|
}) });
|
|
1123
1132
|
};
|
|
1124
|
-
const make$
|
|
1125
|
-
const Tag$
|
|
1126
|
-
const definition = makeDefinition$
|
|
1133
|
+
const make$7 = (id, methods) => Tag$8()(id, methods);
|
|
1134
|
+
const Tag$8 = () => (id, methods) => {
|
|
1135
|
+
const definition = makeDefinition$3(id, methods);
|
|
1127
1136
|
const tag = Context.Service()(id);
|
|
1128
1137
|
const bindingDefinition = (binding) => ({
|
|
1129
1138
|
...binding,
|
|
1130
1139
|
definition
|
|
1131
1140
|
});
|
|
1132
1141
|
const layer = (binding) => layer$7(tag, bindingDefinition(binding));
|
|
1133
|
-
const
|
|
1134
|
-
return yield* (yield* tag).
|
|
1135
|
-
});
|
|
1136
|
-
const idFromName = Effect.fnUntraced(function* (name) {
|
|
1137
|
-
return yield* (yield* tag).idFromName(name);
|
|
1138
|
-
});
|
|
1139
|
-
const idFromString = Effect.fnUntraced(function* (value) {
|
|
1140
|
-
return yield* (yield* tag).idFromString(value);
|
|
1141
|
-
});
|
|
1142
|
-
const get = Effect.fnUntraced(function* (objectId, options) {
|
|
1143
|
-
return yield* (yield* tag).get(objectId, options);
|
|
1144
|
-
});
|
|
1145
|
-
const getByName = Effect.fnUntraced(function* (name, options) {
|
|
1146
|
-
return yield* (yield* tag).getByName(name, options);
|
|
1147
|
-
});
|
|
1148
|
-
const jurisdiction = Effect.fnUntraced(function* (value) {
|
|
1149
|
-
return yield* (yield* tag).jurisdiction(value);
|
|
1150
|
-
});
|
|
1151
|
-
const fetch = (stub, input, init) => Effect.gen(function* () {
|
|
1152
|
-
return yield* (yield* tag).fetch(stub, input, init);
|
|
1153
|
-
});
|
|
1154
|
-
const rpc = (stub, method, ...args) => Effect.gen(function* () {
|
|
1155
|
-
return yield* (yield* tag).rpc(stub, method, ...args);
|
|
1156
|
-
});
|
|
1157
|
-
const call = (stub, method, ...args) => Effect.gen(function* () {
|
|
1158
|
-
return yield* (yield* tag).call(stub, method, ...args);
|
|
1142
|
+
const fetch = (input, init) => Effect.gen(function* () {
|
|
1143
|
+
return yield* (yield* tag).fetch(input, init);
|
|
1159
1144
|
});
|
|
1160
|
-
const
|
|
1161
|
-
return yield* (yield* tag).
|
|
1145
|
+
const rpc = (method, ...args) => Effect.gen(function* () {
|
|
1146
|
+
return yield* (yield* tag).rpc(method, ...args);
|
|
1162
1147
|
});
|
|
1163
|
-
const
|
|
1164
|
-
return yield* (yield* tag).
|
|
1148
|
+
const call = (method, ...args) => Effect.gen(function* () {
|
|
1149
|
+
return yield* (yield* tag).call(method, ...args);
|
|
1165
1150
|
});
|
|
1166
|
-
const
|
|
1167
|
-
|
|
1168
|
-
fetch,
|
|
1169
|
-
get,
|
|
1170
|
-
getByName
|
|
1151
|
+
const scopedCall = (method, ...args) => Effect.gen(function* () {
|
|
1152
|
+
return yield* (yield* tag).scopedCall(method, ...args);
|
|
1171
1153
|
});
|
|
1154
|
+
const directMethods = makeDirectMethods$1(definition, call);
|
|
1172
1155
|
return Object.assign(tag, directMethods, {
|
|
1173
1156
|
id: definition.id,
|
|
1174
1157
|
methods: definition.methods,
|
|
1175
1158
|
make: definition.make,
|
|
1176
1159
|
layer,
|
|
1177
|
-
newUniqueId,
|
|
1178
|
-
idFromName,
|
|
1179
|
-
idFromString,
|
|
1180
|
-
get,
|
|
1181
|
-
getByName,
|
|
1182
|
-
jurisdiction,
|
|
1183
1160
|
fetch,
|
|
1184
1161
|
rpc,
|
|
1185
1162
|
call,
|
|
1186
|
-
scopedCall
|
|
1187
|
-
unsafeRaw
|
|
1163
|
+
scopedCall
|
|
1188
1164
|
});
|
|
1189
1165
|
};
|
|
1190
|
-
const
|
|
1191
|
-
const wrapHandlers = (definition, handlers) => {
|
|
1166
|
+
const Worker = Tag$8;
|
|
1167
|
+
const wrapHandlers$1 = (definition, handlers) => {
|
|
1192
1168
|
const wrapped = {};
|
|
1193
1169
|
for (const key of Object.keys(definition.methods)) {
|
|
1194
1170
|
const handler = handlers[key];
|
|
@@ -1201,444 +1177,418 @@ const wrapHandlers = (definition, handlers) => {
|
|
|
1201
1177
|
/**
|
|
1202
1178
|
* Helper for implementing handlers with the exact method shape of a definition.
|
|
1203
1179
|
*/
|
|
1204
|
-
const implement$
|
|
1180
|
+
const implement$5 = (_definition, handlers) => handlers;
|
|
1205
1181
|
//#endregion
|
|
1206
|
-
//#region src/
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
method
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
"dup",
|
|
1216
|
-
"fetch",
|
|
1217
|
-
"alarm",
|
|
1218
|
-
"webSocketMessage",
|
|
1219
|
-
"webSocketClose",
|
|
1220
|
-
"webSocketError"
|
|
1221
|
-
]);
|
|
1222
|
-
const RunSymbol = Symbol.for("effect-cf/DurableObject/run");
|
|
1223
|
-
/**
|
|
1224
|
-
* Creates a Durable Object class backed by a single managed Effect runtime.
|
|
1225
|
-
*/
|
|
1226
|
-
const make$5 = (layer, options = {}) => {
|
|
1227
|
-
class EffectDurableObject extends DurableObject {
|
|
1228
|
-
runtime;
|
|
1229
|
-
constructor(state, env) {
|
|
1230
|
-
super(state, env);
|
|
1231
|
-
const runtimeLayer = provideEntrypointServices(layer, Layer.mergeAll(Layer.succeed(DurableObjectState, fromDurableObjectState(state)), Layer.succeed(WorkerEnvironment, env)));
|
|
1232
|
-
this.runtime = ManagedRuntime.make(runtimeLayer);
|
|
1233
|
-
const initialize = options.initialize;
|
|
1234
|
-
if (initialize !== void 0) state.waitUntil(this[RunSymbol](initialize));
|
|
1235
|
-
}
|
|
1236
|
-
[RunSymbol](effect) {
|
|
1237
|
-
return this.runtime.runPromise(Effect.scoped(effect));
|
|
1238
|
-
}
|
|
1239
|
-
fetch(request) {
|
|
1240
|
-
const fetchHandler = options.fetch;
|
|
1241
|
-
if (fetchHandler === void 0) return Promise.resolve(new Response("Not Found", { status: 404 }));
|
|
1242
|
-
return this[RunSymbol](Effect.provideService(fetchHandler, NativeRequest, request));
|
|
1243
|
-
}
|
|
1244
|
-
alarm(alarmInfo) {
|
|
1245
|
-
const logicalAlarms = options.alarms?.pipe(Effect.asVoid);
|
|
1246
|
-
const rawAlarm = options.alarm?.(alarmInfo);
|
|
1247
|
-
if (logicalAlarms !== void 0 && rawAlarm !== void 0) return this[RunSymbol](Effect.gen(function* () {
|
|
1248
|
-
yield* logicalAlarms;
|
|
1249
|
-
yield* rawAlarm;
|
|
1250
|
-
}));
|
|
1251
|
-
if (logicalAlarms !== void 0) return this[RunSymbol](logicalAlarms);
|
|
1252
|
-
if (rawAlarm !== void 0) return this[RunSymbol](rawAlarm);
|
|
1253
|
-
}
|
|
1254
|
-
webSocketMessage(socket, message) {
|
|
1255
|
-
if (options.webSocketMessage !== void 0) return this[RunSymbol](options.webSocketMessage(fromWebSocket(socket), message));
|
|
1182
|
+
//#region src/internal/Entrypoint.ts
|
|
1183
|
+
const provideEntrypointServices = (layer, services) => layer.pipe(Layer.provideMerge(services));
|
|
1184
|
+
const defineEntrypointRpcMethods = (target, prototype, rpc, reservedMethodNames, run) => {
|
|
1185
|
+
const methods = rpc ?? {};
|
|
1186
|
+
assertNoReservedMethods(target, methods, reservedMethodNames);
|
|
1187
|
+
for (const [key, method] of Object.entries(methods)) Object.defineProperty(prototype, key, {
|
|
1188
|
+
enumerable: true,
|
|
1189
|
+
value(...args) {
|
|
1190
|
+
return run(this, Effect.suspend(() => method(...args)));
|
|
1256
1191
|
}
|
|
1257
|
-
|
|
1258
|
-
|
|
1192
|
+
});
|
|
1193
|
+
};
|
|
1194
|
+
const assumeEntrypointClass = (entrypoint) => entrypoint;
|
|
1195
|
+
//#endregion
|
|
1196
|
+
//#region src/internal/WorkerContext.ts
|
|
1197
|
+
const causeError = (cause) => new Error(Cause.pretty(cause));
|
|
1198
|
+
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))));
|
|
1199
|
+
const fromExecutionContext = (ctx, runPromiseExit) => {
|
|
1200
|
+
const schedule = (effect, options, mode) => Effect.context().pipe(Effect.flatMap((context) => Effect.sync(() => {
|
|
1201
|
+
const runHandler = (cause) => runPromiseExit(Effect.scoped(Effect.provideContext(failureHandler(cause, options), context))).then((exit) => {
|
|
1202
|
+
if (Exit.isFailure(exit)) console.error("WorkerContext.waitUntil failure handler failed", Cause.pretty(exit.cause));
|
|
1203
|
+
});
|
|
1204
|
+
ctx.waitUntil(runPromiseExit(Effect.scoped(Effect.provideContext(effect, context))).then(async (exit) => {
|
|
1205
|
+
if (Exit.isSuccess(exit)) return;
|
|
1206
|
+
await runHandler(exit.cause);
|
|
1207
|
+
if (mode === "propagate") throw causeError(exit.cause);
|
|
1208
|
+
}));
|
|
1209
|
+
})));
|
|
1210
|
+
return {
|
|
1211
|
+
raw: ctx,
|
|
1212
|
+
waitUntil: (effect, options) => schedule(effect, options, options?.mode ?? "observe"),
|
|
1213
|
+
waitUntilPropagating: (effect, options) => schedule(effect, options, "propagate"),
|
|
1214
|
+
passThroughOnException: Effect.sync(() => ctx.passThroughOnException())
|
|
1215
|
+
};
|
|
1216
|
+
};
|
|
1217
|
+
//#endregion
|
|
1218
|
+
//#region src/Worker.ts
|
|
1219
|
+
var Worker_exports = /* @__PURE__ */ __exportAll({
|
|
1220
|
+
ExecutionContext: () => ExecutionContext,
|
|
1221
|
+
NativeRequest: () => NativeRequest,
|
|
1222
|
+
Tag: () => Tag$7,
|
|
1223
|
+
WorkerContext: () => WorkerContext,
|
|
1224
|
+
implement: () => implement$4,
|
|
1225
|
+
isWebSocketUpgrade: () => isWebSocketUpgrade,
|
|
1226
|
+
make: () => make$6,
|
|
1227
|
+
makeFetchHandler: () => makeFetchHandler,
|
|
1228
|
+
method: () => method$2,
|
|
1229
|
+
renderHttpResponse: () => renderHttpResponse
|
|
1230
|
+
});
|
|
1231
|
+
var ExecutionContext = class extends Context.Service()("effect-cf/ExecutionContext") {};
|
|
1232
|
+
var WorkerContext = class extends Context.Service()("effect-cf/WorkerContext") {};
|
|
1233
|
+
var NativeRequest = class extends Context.Service()("effect-cf/NativeRequest") {};
|
|
1234
|
+
const isWebSocketUpgrade = (request) => request.headers.get("Upgrade")?.toLowerCase() === "websocket";
|
|
1235
|
+
const reservedMethodNames$2 = new Set([
|
|
1236
|
+
"constructor",
|
|
1237
|
+
"dup",
|
|
1238
|
+
"fetch",
|
|
1239
|
+
"connect",
|
|
1240
|
+
"queue",
|
|
1241
|
+
"scheduled",
|
|
1242
|
+
"tail",
|
|
1243
|
+
"tailStream",
|
|
1244
|
+
"test",
|
|
1245
|
+
"trace",
|
|
1246
|
+
"alarm",
|
|
1247
|
+
"webSocketMessage",
|
|
1248
|
+
"webSocketClose",
|
|
1249
|
+
"webSocketError"
|
|
1250
|
+
]);
|
|
1251
|
+
const RunSymbol$1 = Symbol.for("effect-cf/Worker/run");
|
|
1252
|
+
const renderHttpResponse = (effect) => Effect.flatMap(effect, (response) => Effect.map(Effect.context(), (context) => HttpServerResponse.toWeb(response, { context })));
|
|
1253
|
+
const renderFetchSuccess = (effect) => Effect.flatMap(effect, (response) => response instanceof Response ? Effect.succeed(response) : Effect.map(Effect.context(), (context) => HttpServerResponse.toWeb(response, { context })));
|
|
1254
|
+
const isWorkerOptions = (options) => typeof options === "object" && options !== null && ("eventLayer" in options || "fetch" in options || "queue" in options || "rpc" in options);
|
|
1255
|
+
function make$6(layer, optionsOrFetch) {
|
|
1256
|
+
const options = isWorkerOptions(optionsOrFetch) ? optionsOrFetch : { fetch: optionsOrFetch };
|
|
1257
|
+
class EffectWorker extends WorkerEntrypoint {
|
|
1258
|
+
runtime;
|
|
1259
|
+
constructor(ctx, env) {
|
|
1260
|
+
super(ctx, env);
|
|
1261
|
+
let runWaitUntilEffect = () => Promise.reject(/* @__PURE__ */ new Error("WorkerContext runtime is not initialized"));
|
|
1262
|
+
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)));
|
|
1263
|
+
this.runtime = ManagedRuntime.make(runtimeLayer);
|
|
1264
|
+
runWaitUntilEffect = (effect) => this.runtime.runPromiseExit(effect);
|
|
1259
1265
|
}
|
|
1260
|
-
|
|
1261
|
-
|
|
1266
|
+
[RunSymbol$1](effect, runOptions = {}) {
|
|
1267
|
+
const effectWithEventLayer = runOptions.eventLayer === false || options.eventLayer === void 0 ? effect : effect.pipe(Effect.provide(options.eventLayer, { local: true }));
|
|
1268
|
+
return this.runtime.runPromise(Effect.scoped(effectWithEventLayer));
|
|
1269
|
+
}
|
|
1270
|
+
fetch(request) {
|
|
1271
|
+
const fetchHandler = options.fetch;
|
|
1272
|
+
if (fetchHandler === void 0) return Promise.resolve(new Response("Not Found", { status: 404 }));
|
|
1273
|
+
const requestServices = Layer.mergeAll(Layer.succeed(NativeRequest, request), Layer.succeed(HttpServerRequest.HttpServerRequest, HttpServerRequest.fromWeb(request)));
|
|
1274
|
+
return this[RunSymbol$1](renderFetchSuccess(fetchHandler).pipe(Effect.provide(requestServices)));
|
|
1275
|
+
}
|
|
1276
|
+
queue(batch) {
|
|
1277
|
+
const queueHandler = options.queue;
|
|
1278
|
+
if (queueHandler === void 0) return Promise.resolve();
|
|
1279
|
+
const messages = batch.messages.map((message) => fromMessage(message, message.body));
|
|
1280
|
+
return this[RunSymbol$1](queueHandler(fromMessageBatch(batch, messages)));
|
|
1262
1281
|
}
|
|
1263
1282
|
}
|
|
1264
|
-
defineEntrypointRpcMethods("
|
|
1265
|
-
return assumeEntrypointClass(
|
|
1283
|
+
defineEntrypointRpcMethods("Worker", EffectWorker.prototype, options.rpc, reservedMethodNames$2, (self, effect) => self[RunSymbol$1](effect));
|
|
1284
|
+
return assumeEntrypointClass(EffectWorker);
|
|
1285
|
+
}
|
|
1286
|
+
const makeFetchHandler = (layer, options) => {
|
|
1287
|
+
const WorkerClass = make$6(layer, options);
|
|
1288
|
+
return { fetch: (request, env, ctx) => Promise.resolve(new WorkerClass(ctx, env).fetch(request)) };
|
|
1266
1289
|
};
|
|
1267
|
-
const Tag$
|
|
1268
|
-
const method = method$
|
|
1269
|
-
const implement$
|
|
1290
|
+
const Tag$7 = Tag$8;
|
|
1291
|
+
const method$2 = method$3;
|
|
1292
|
+
const implement$4 = implement$5;
|
|
1270
1293
|
//#endregion
|
|
1271
|
-
//#region src/
|
|
1272
|
-
var
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
instrumentWorkerOptions: () => instrumentWorkerOptions,
|
|
1294
|
+
//#region src/DurableObjectNamespace.ts
|
|
1295
|
+
var DurableObjectNamespace_exports = /* @__PURE__ */ __exportAll({
|
|
1296
|
+
DurableObjectFetchError: () => DurableObjectFetchError,
|
|
1297
|
+
DurableObjectRpcError: () => DurableObjectRpcError,
|
|
1298
|
+
isDurableObjectNamespaceClient: () => isDurableObjectNamespaceClient,
|
|
1277
1299
|
layer: () => layer$6,
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
settingsConfig: () => settingsConfig,
|
|
1281
|
-
settingsLayer: () => settingsLayer,
|
|
1282
|
-
workerLayer: () => workerLayer
|
|
1283
|
-
});
|
|
1284
|
-
/**
|
|
1285
|
-
* Supported OpenTelemetry environment configuration for Cloudflare OTLP export.
|
|
1286
|
-
*
|
|
1287
|
-
* This config intentionally uses the conventional `OTEL_*` variable names so
|
|
1288
|
-
* deployments can share the same settings used by other OpenTelemetry SDKs.
|
|
1289
|
-
* It covers the OTLP HTTP settings supported by the Effect OTLP layers:
|
|
1290
|
-
*
|
|
1291
|
-
* - `OTEL_EXPORTER_OTLP_ENDPOINT`
|
|
1292
|
-
* - `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`
|
|
1293
|
-
* - `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`
|
|
1294
|
-
* - `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`
|
|
1295
|
-
* - `OTEL_EXPORTER_OTLP_HEADERS`
|
|
1296
|
-
* - `OTEL_EXPORTER_OTLP_LOGS_HEADERS`
|
|
1297
|
-
* - `OTEL_EXPORTER_OTLP_TRACES_HEADERS`
|
|
1298
|
-
* - `OTEL_EXPORTER_OTLP_METRICS_HEADERS`
|
|
1299
|
-
* - `OTEL_SERVICE_NAME`
|
|
1300
|
-
* - `OTEL_RESOURCE_ATTRIBUTES`
|
|
1301
|
-
*
|
|
1302
|
-
* `OTEL_SERVICE_VERSION` is also accepted as an effect-cf convenience alias.
|
|
1303
|
-
* The standard OpenTelemetry way to configure service version is
|
|
1304
|
-
* `OTEL_RESOURCE_ATTRIBUTES=service.version=...`.
|
|
1305
|
-
*
|
|
1306
|
-
* Consumers with non-standard binding names should map those names into
|
|
1307
|
-
* {@link CloudflareOtlpSettings} rather than changing this config globally.
|
|
1308
|
-
*/
|
|
1309
|
-
const settingsConfig = Config.all({
|
|
1310
|
-
endpoint: Config.string("OTEL_EXPORTER_OTLP_ENDPOINT").pipe(Config.option),
|
|
1311
|
-
logsEndpoint: Config.string("OTEL_EXPORTER_OTLP_LOGS_ENDPOINT").pipe(Config.option),
|
|
1312
|
-
tracesEndpoint: Config.string("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT").pipe(Config.option),
|
|
1313
|
-
metricsEndpoint: Config.string("OTEL_EXPORTER_OTLP_METRICS_ENDPOINT").pipe(Config.option),
|
|
1314
|
-
headers: Config.string("OTEL_EXPORTER_OTLP_HEADERS").pipe(Config.option),
|
|
1315
|
-
logsHeaders: Config.string("OTEL_EXPORTER_OTLP_LOGS_HEADERS").pipe(Config.option),
|
|
1316
|
-
tracesHeaders: Config.string("OTEL_EXPORTER_OTLP_TRACES_HEADERS").pipe(Config.option),
|
|
1317
|
-
metricsHeaders: Config.string("OTEL_EXPORTER_OTLP_METRICS_HEADERS").pipe(Config.option),
|
|
1318
|
-
serviceName: Config.string("OTEL_SERVICE_NAME").pipe(Config.option),
|
|
1319
|
-
serviceVersion: Config.string("OTEL_SERVICE_VERSION").pipe(Config.option),
|
|
1320
|
-
resourceAttributes: Config.schema(Config.Record(Schema.String, Schema.String), "OTEL_RESOURCE_ATTRIBUTES").pipe(Config.option)
|
|
1300
|
+
makeClient: () => makeClient$4,
|
|
1301
|
+
makeDirectMethods: () => makeDirectMethods
|
|
1321
1302
|
});
|
|
1303
|
+
const expectedDurableObjectNamespace = "Durable Object namespace binding with getByName(), get(), idFromName(), idFromString(), newUniqueId(), and jurisdiction()";
|
|
1322
1304
|
/**
|
|
1323
|
-
*
|
|
1324
|
-
*
|
|
1325
|
-
* Provide this service directly when an application needs to map custom
|
|
1326
|
-
* Cloudflare binding names, compute settings dynamically, or override settings
|
|
1327
|
-
* in tests. When this service is present, the OTLP layers use it instead of
|
|
1328
|
-
* reading {@link settingsConfig}.
|
|
1329
|
-
*
|
|
1330
|
-
* @example
|
|
1331
|
-
* ```ts
|
|
1332
|
-
* const CustomOtlpSettings = Layer.effect(
|
|
1333
|
-
* CloudflareOtlp.CloudflareOtlpSettings,
|
|
1334
|
-
* Config.all({
|
|
1335
|
-
* ...CloudflareOtlp.settingsConfig,
|
|
1336
|
-
* endpoint: Config.string("MY_OTLP_ENDPOINT").pipe(Config.option),
|
|
1337
|
-
* }),
|
|
1338
|
-
* ).pipe(Layer.provide(WorkerConfig.layer));
|
|
1339
|
-
* ```
|
|
1305
|
+
* Failure raised when invoking an RPC method on a Durable Object stub.
|
|
1340
1306
|
*/
|
|
1341
|
-
var
|
|
1342
|
-
const allSignals = [
|
|
1343
|
-
"logs",
|
|
1344
|
-
"traces",
|
|
1345
|
-
"metrics"
|
|
1346
|
-
];
|
|
1347
|
-
const optionToUndefined = (option) => Option.isSome(option) ? option.value : void 0;
|
|
1348
|
-
const nonEmptyStringOption = (option) => Option.flatMap(option, (value) => {
|
|
1349
|
-
const trimmed = value.trim();
|
|
1350
|
-
return trimmed === "" ? Option.none() : Option.some(trimmed);
|
|
1351
|
-
});
|
|
1352
|
-
const nonEmptyRecordOption = (option) => Option.filter(option, (value) => Object.keys(value).length > 0);
|
|
1353
|
-
const normalizeSettings = (settings) => ({
|
|
1354
|
-
endpoint: nonEmptyStringOption(settings.endpoint),
|
|
1355
|
-
logsEndpoint: nonEmptyStringOption(settings.logsEndpoint),
|
|
1356
|
-
tracesEndpoint: nonEmptyStringOption(settings.tracesEndpoint),
|
|
1357
|
-
metricsEndpoint: nonEmptyStringOption(settings.metricsEndpoint),
|
|
1358
|
-
headers: nonEmptyStringOption(settings.headers),
|
|
1359
|
-
logsHeaders: nonEmptyStringOption(settings.logsHeaders),
|
|
1360
|
-
tracesHeaders: nonEmptyStringOption(settings.tracesHeaders),
|
|
1361
|
-
metricsHeaders: nonEmptyStringOption(settings.metricsHeaders),
|
|
1362
|
-
serviceName: nonEmptyStringOption(settings.serviceName),
|
|
1363
|
-
serviceVersion: nonEmptyStringOption(settings.serviceVersion),
|
|
1364
|
-
resourceAttributes: nonEmptyRecordOption(settings.resourceAttributes)
|
|
1365
|
-
});
|
|
1307
|
+
var DurableObjectRpcError = class extends Data.TaggedError("DurableObjectRpcError") {};
|
|
1366
1308
|
/**
|
|
1367
|
-
*
|
|
1368
|
-
* `env` object.
|
|
1369
|
-
*
|
|
1370
|
-
* The layer depends on {@link WorkerEnvironment} and installs a
|
|
1371
|
-
* Cloudflare-backed Effect `ConfigProvider`, so `settingsConfig` reads from
|
|
1372
|
-
* Worker vars/secrets instead of Node process environment variables.
|
|
1309
|
+
* Failure raised when forwarding a request to a Durable Object stub.
|
|
1373
1310
|
*/
|
|
1374
|
-
|
|
1375
|
-
const
|
|
1376
|
-
const
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
const
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
const
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
const
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1311
|
+
var DurableObjectFetchError = class extends Data.TaggedError("DurableObjectFetchError") {};
|
|
1312
|
+
const hasFunction$1 = (value, key) => typeof Reflect.get(value, key) === "function";
|
|
1313
|
+
const isDurableObjectNamespaceClient = (value) => typeof value === "object" && value !== null && hasFunction$1(value, "getByName") && hasFunction$1(value, "get") && hasFunction$1(value, "idFromName") && hasFunction$1(value, "idFromString") && hasFunction$1(value, "newUniqueId") && hasFunction$1(value, "jurisdiction");
|
|
1314
|
+
const makeClient$4 = (definition) => {
|
|
1315
|
+
return (namespace) => {
|
|
1316
|
+
const newUniqueId = (options) => Effect.sync(() => namespace.newUniqueId(options));
|
|
1317
|
+
const idFromName = (name) => Effect.sync(() => namespace.idFromName(name));
|
|
1318
|
+
const idFromString = (id) => Effect.sync(() => namespace.idFromString(id));
|
|
1319
|
+
const get = (id, options) => Effect.sync(() => namespace.get(id, options));
|
|
1320
|
+
const getByName = (name, options) => Effect.sync(() => namespace.getByName(name, options));
|
|
1321
|
+
const jurisdiction = (value) => Effect.sync(() => namespace.jurisdiction(value));
|
|
1322
|
+
const fetch = (stub, input, init) => Effect.tryPromise({
|
|
1323
|
+
try: () => stub.fetch(input, init),
|
|
1324
|
+
catch: (cause) => new DurableObjectFetchError({
|
|
1325
|
+
binding: definition.binding,
|
|
1326
|
+
cause
|
|
1327
|
+
})
|
|
1328
|
+
});
|
|
1329
|
+
const rpc = (stub, method, ...args) => Effect.gen(function* () {
|
|
1330
|
+
const methodName = String(method);
|
|
1331
|
+
return yield* invokeRpcMethod(stub, method, definition.definition === void 0 ? args : yield* encodeArgs(definition.definition, methodName, args).pipe(Effect.mapError((cause) => new DurableObjectRpcError({
|
|
1332
|
+
binding: definition.binding,
|
|
1333
|
+
method: methodName,
|
|
1334
|
+
cause
|
|
1335
|
+
}))), (cause) => new DurableObjectRpcError({
|
|
1336
|
+
binding: definition.binding,
|
|
1337
|
+
method: methodName,
|
|
1338
|
+
cause
|
|
1339
|
+
}));
|
|
1340
|
+
});
|
|
1341
|
+
const decodeSuccess$1 = (methodName, value) => Effect.gen(function* () {
|
|
1342
|
+
if (definition.definition === void 0) return value;
|
|
1343
|
+
return yield* decodeSuccess(definition.definition, methodName, value).pipe(Effect.mapError((cause) => new DurableObjectRpcError({
|
|
1344
|
+
binding: definition.binding,
|
|
1345
|
+
method: methodName,
|
|
1346
|
+
cause
|
|
1347
|
+
})));
|
|
1348
|
+
});
|
|
1349
|
+
const call = (stub, method, ...args) => Effect.gen(function* () {
|
|
1350
|
+
const methodName = String(method);
|
|
1351
|
+
return yield* decodeSuccess$1(methodName, yield* resolve(yield* rpc(stub, method, ...args)).pipe(Effect.mapError((cause) => new DurableObjectRpcError({
|
|
1352
|
+
binding: definition.binding,
|
|
1353
|
+
method: methodName,
|
|
1354
|
+
cause
|
|
1355
|
+
}))));
|
|
1356
|
+
});
|
|
1357
|
+
const scopedCall = (stub, method, ...args) => Effect.gen(function* () {
|
|
1358
|
+
return yield* decodeSuccess$1(String(method), yield* scoped(yield* rpc(stub, method, ...args)));
|
|
1359
|
+
});
|
|
1360
|
+
const directMethods = makeDirectMethods(definition.definition, {
|
|
1361
|
+
call,
|
|
1362
|
+
fetch,
|
|
1363
|
+
get,
|
|
1364
|
+
getByName
|
|
1365
|
+
});
|
|
1366
|
+
return Object.assign(directMethods, {
|
|
1367
|
+
newUniqueId,
|
|
1368
|
+
idFromName,
|
|
1369
|
+
idFromString,
|
|
1370
|
+
get,
|
|
1371
|
+
getByName,
|
|
1372
|
+
jurisdiction,
|
|
1373
|
+
fetch,
|
|
1374
|
+
rpc,
|
|
1375
|
+
call,
|
|
1376
|
+
scopedCall,
|
|
1377
|
+
unsafeRaw: Effect.succeed(namespace)
|
|
1378
|
+
});
|
|
1400
1379
|
};
|
|
1401
1380
|
};
|
|
1402
|
-
const
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
const
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
resource: makeResource(settings, options, runtimeAttributes),
|
|
1421
|
-
maxBatchSize: options.maxBatchSize,
|
|
1422
|
-
loggerExportInterval: options.loggerExportInterval,
|
|
1423
|
-
loggerExcludeLogSpans: options.loggerExcludeLogSpans,
|
|
1424
|
-
loggerMergeWithExisting: options.loggerMergeWithExisting,
|
|
1425
|
-
tracerExportInterval: options.tracerExportInterval,
|
|
1426
|
-
tracerContext: options.tracerContext,
|
|
1427
|
-
metricsExportInterval: options.metricsExportInterval,
|
|
1428
|
-
metricsTemporality: options.metricsTemporality,
|
|
1429
|
-
shutdownTimeout: options.shutdownTimeout
|
|
1430
|
-
});
|
|
1431
|
-
const serializationLayer = (serialization) => serialization === "json" ? OtlpSerialization.layerJson : OtlpSerialization.layerProtobuf;
|
|
1432
|
-
const resolveSettings = Effect.gen(function* () {
|
|
1433
|
-
const settings = yield* Effect.serviceOption(CloudflareOtlpSettings);
|
|
1434
|
-
if (Option.isSome(settings)) return normalizeSettings(settings.value);
|
|
1435
|
-
const env = yield* Effect.serviceOption(WorkerEnvironment);
|
|
1436
|
-
if (Option.isSome(env)) return normalizeSettings(yield* settingsConfig.pipe(Effect.provide(ConfigProvider.layer(Effect.succeed(WorkerConfig.providerFromEnv(env.value))))));
|
|
1437
|
-
return normalizeSettings(yield* settingsConfig);
|
|
1438
|
-
});
|
|
1439
|
-
const mergeSignalLayers = (layers) => {
|
|
1440
|
-
if (layers.length === 0) return Layer.empty;
|
|
1441
|
-
let merged = layers[0];
|
|
1442
|
-
for (let index = 1; index < layers.length; index++) merged = Layer.mergeAll(merged, layers[index]);
|
|
1443
|
-
return merged;
|
|
1444
|
-
};
|
|
1445
|
-
const emptyLayer = Layer.empty;
|
|
1446
|
-
const makeLayerFromSettings = (options = {}, runtimeAttributes = {}) => Layer.unwrap(Effect.map(resolveSettings, (settings) => {
|
|
1447
|
-
const signals = selectedSignals(options.signals);
|
|
1448
|
-
const endpoint = optionToUndefined(settings.endpoint);
|
|
1449
|
-
const logsEndpoint = optionToUndefined(settings.logsEndpoint);
|
|
1450
|
-
const tracesEndpoint = optionToUndefined(settings.tracesEndpoint);
|
|
1451
|
-
const metricsEndpoint = optionToUndefined(settings.metricsEndpoint);
|
|
1452
|
-
const hasSpecificEndpoint = logsEndpoint !== void 0 || tracesEndpoint !== void 0 || metricsEndpoint !== void 0;
|
|
1453
|
-
const hasSpecificHeaders = Option.isSome(settings.logsHeaders) || Option.isSome(settings.tracesHeaders) || Option.isSome(settings.metricsHeaders);
|
|
1454
|
-
const common = commonOtlpOptions(settings, options, runtimeAttributes);
|
|
1455
|
-
if (endpoint !== void 0 && !hasSpecificEndpoint && !hasSpecificHeaders && signals.size === 3) return Otlp.layer({
|
|
1456
|
-
baseUrl: endpoint,
|
|
1457
|
-
headers: parseHeaders(settings.headers),
|
|
1458
|
-
...common
|
|
1459
|
-
}).pipe(Layer.provide(serializationLayer(options.serialization)), Layer.provide(FetchHttpClient.layer));
|
|
1460
|
-
const layers = [];
|
|
1461
|
-
if (signals.has("logs")) {
|
|
1462
|
-
const url = logsEndpoint ?? (endpoint === void 0 ? void 0 : appendOtlpPath(endpoint, "/v1/logs"));
|
|
1463
|
-
if (url !== void 0) layers.push(OtlpLogger.layer({
|
|
1464
|
-
url,
|
|
1465
|
-
resource: common.resource,
|
|
1466
|
-
headers: mergeHeaders(settings.headers, settings.logsHeaders),
|
|
1467
|
-
exportInterval: common.loggerExportInterval,
|
|
1468
|
-
maxBatchSize: common.maxBatchSize,
|
|
1469
|
-
shutdownTimeout: common.shutdownTimeout,
|
|
1470
|
-
excludeLogSpans: common.loggerExcludeLogSpans,
|
|
1471
|
-
mergeWithExisting: common.loggerMergeWithExisting
|
|
1472
|
-
}).pipe(Layer.provide(serializationLayer(options.serialization)), Layer.provide(FetchHttpClient.layer)));
|
|
1473
|
-
}
|
|
1474
|
-
if (signals.has("traces")) {
|
|
1475
|
-
const url = tracesEndpoint ?? (endpoint === void 0 ? void 0 : appendOtlpPath(endpoint, "/v1/traces"));
|
|
1476
|
-
if (url !== void 0) layers.push(OtlpTracer.layer({
|
|
1477
|
-
url,
|
|
1478
|
-
resource: common.resource,
|
|
1479
|
-
headers: mergeHeaders(settings.headers, settings.tracesHeaders),
|
|
1480
|
-
exportInterval: common.tracerExportInterval,
|
|
1481
|
-
maxBatchSize: common.maxBatchSize,
|
|
1482
|
-
context: common.tracerContext,
|
|
1483
|
-
shutdownTimeout: common.shutdownTimeout
|
|
1484
|
-
}).pipe(Layer.provide(serializationLayer(options.serialization)), Layer.provide(FetchHttpClient.layer)));
|
|
1485
|
-
}
|
|
1486
|
-
if (signals.has("metrics")) {
|
|
1487
|
-
const url = metricsEndpoint ?? (endpoint === void 0 ? void 0 : appendOtlpPath(endpoint, "/v1/metrics"));
|
|
1488
|
-
if (url !== void 0) layers.push(OtlpMetrics.layer({
|
|
1489
|
-
url,
|
|
1490
|
-
resource: common.resource,
|
|
1491
|
-
headers: mergeHeaders(settings.headers, settings.metricsHeaders),
|
|
1492
|
-
exportInterval: common.metricsExportInterval,
|
|
1493
|
-
shutdownTimeout: common.shutdownTimeout,
|
|
1494
|
-
temporality: common.metricsTemporality
|
|
1495
|
-
}).pipe(Layer.provide(serializationLayer(options.serialization)), Layer.provide(FetchHttpClient.layer)));
|
|
1381
|
+
const layer$6 = (tag, definition) => layer$10(tag, definition.binding, (value) => isDurableObjectNamespaceClient(value), makeClient$4(definition), { expected: expectedDurableObjectNamespace });
|
|
1382
|
+
const makeDirectMethods = (rpcDefinition, helpers) => {
|
|
1383
|
+
const methods = {};
|
|
1384
|
+
if (rpcDefinition !== void 0) {
|
|
1385
|
+
for (const methodName of Object.keys(rpcDefinition.methods)) methods[methodName] = (stub, ...args) => helpers.call(stub, methodName, ...args);
|
|
1386
|
+
const makeClient = (getStub) => {
|
|
1387
|
+
const client = { fetch: (input, init) => Effect.gen(function* () {
|
|
1388
|
+
const stub = yield* getStub();
|
|
1389
|
+
return yield* helpers.fetch(stub, input, init);
|
|
1390
|
+
}) };
|
|
1391
|
+
for (const methodName of Object.keys(rpcDefinition.methods)) client[methodName] = (...args) => Effect.gen(function* () {
|
|
1392
|
+
const stub = yield* getStub();
|
|
1393
|
+
return yield* helpers.call(stub, methodName, ...args);
|
|
1394
|
+
});
|
|
1395
|
+
return client;
|
|
1396
|
+
};
|
|
1397
|
+
methods.byName = (name, options) => makeClient(() => helpers.getByName(name, options));
|
|
1398
|
+
methods.byId = (id, options) => makeClient(() => helpers.get(id, options));
|
|
1496
1399
|
}
|
|
1497
|
-
return
|
|
1498
|
-
}
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
* When only `OTEL_EXPORTER_OTLP_ENDPOINT` is configured, per-signal paths are
|
|
1508
|
-
* derived by appending `/v1/logs`, `/v1/traces`, and `/v1/metrics`. Signal
|
|
1509
|
-
* specific endpoints are used as-is, matching the OpenTelemetry OTLP exporter
|
|
1510
|
-
* convention.
|
|
1511
|
-
*/
|
|
1512
|
-
const layer$6 = (options = {}) => makeLayer(options);
|
|
1513
|
-
/** Base OTLP telemetry layer forced to JSON serialization. */
|
|
1514
|
-
const layerJson = (options = {}) => layer$6({
|
|
1515
|
-
...options,
|
|
1516
|
-
serialization: "json"
|
|
1517
|
-
});
|
|
1518
|
-
/** Base OTLP telemetry layer forced to protobuf serialization. */
|
|
1519
|
-
const layerProtobuf = (options = {}) => layer$6({
|
|
1520
|
-
...options,
|
|
1521
|
-
serialization: "protobuf"
|
|
1400
|
+
return methods;
|
|
1401
|
+
};
|
|
1402
|
+
//#endregion
|
|
1403
|
+
//#region src/DurableObjectDefinition.ts
|
|
1404
|
+
var DurableObjectDefinition_exports = /* @__PURE__ */ __exportAll({
|
|
1405
|
+
DurableObject: () => DurableObject$1,
|
|
1406
|
+
Tag: () => Tag$6,
|
|
1407
|
+
implement: () => implement$3,
|
|
1408
|
+
make: () => make$5,
|
|
1409
|
+
method: () => method$1
|
|
1522
1410
|
});
|
|
1411
|
+
const reservedMethodNames$1 = new Set([
|
|
1412
|
+
"constructor",
|
|
1413
|
+
"dup",
|
|
1414
|
+
"fetch",
|
|
1415
|
+
"alarm",
|
|
1416
|
+
"webSocketMessage",
|
|
1417
|
+
"webSocketClose",
|
|
1418
|
+
"webSocketError"
|
|
1419
|
+
]);
|
|
1523
1420
|
/**
|
|
1524
|
-
*
|
|
1525
|
-
*
|
|
1526
|
-
* Provide this layer at runtime scope for long-lived metrics aggregation, or at
|
|
1527
|
-
* handler scope when traces/logs should flush as the Cloudflare event finishes.
|
|
1421
|
+
* Defines a single RPC method schema in a Durable Object definition.
|
|
1528
1422
|
*/
|
|
1529
|
-
const
|
|
1530
|
-
"cloudflare.resource_type": "worker",
|
|
1531
|
-
"cloudflare.worker.name": options.workerName
|
|
1532
|
-
});
|
|
1423
|
+
const method$1 = method$4;
|
|
1533
1424
|
/**
|
|
1534
|
-
*
|
|
1425
|
+
* Creates a Durable Object RPC definition plus implementation/binding helpers.
|
|
1535
1426
|
*
|
|
1536
|
-
*
|
|
1537
|
-
*
|
|
1538
|
-
*
|
|
1427
|
+
* @example
|
|
1428
|
+
* ```ts
|
|
1429
|
+
* const ChatRoom = DurableObjectDefinition.make("ChatRoom", {
|
|
1430
|
+
* postMessage: DurableObjectDefinition.method({
|
|
1431
|
+
* args: [Schema.String],
|
|
1432
|
+
* success: Schema.Void,
|
|
1433
|
+
* }),
|
|
1434
|
+
* });
|
|
1435
|
+
* ```
|
|
1539
1436
|
*/
|
|
1540
|
-
const
|
|
1541
|
-
"
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
return new Proxy(rpc, { get(target, property, receiver) {
|
|
1548
|
-
const handler = Reflect.get(target, property, receiver);
|
|
1549
|
-
if (typeof handler !== "function") return handler;
|
|
1550
|
-
return (...args) => Effect.suspend(() => Reflect.apply(handler, receiver, args)).pipe(Effect.provide(layer));
|
|
1551
|
-
} });
|
|
1437
|
+
const makeDefinition$2 = (id, methods) => {
|
|
1438
|
+
assertNoReservedMethods("Durable Object", methods, reservedMethodNames$1);
|
|
1439
|
+
const definition = make$8(id, methods);
|
|
1440
|
+
return Object.assign(definition, { make: (layer, options) => make$4(layer, {
|
|
1441
|
+
...options,
|
|
1442
|
+
rpc: wrapHandlers(definition, options.rpc)
|
|
1443
|
+
}) });
|
|
1552
1444
|
};
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
const
|
|
1562
|
-
const
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1445
|
+
const make$5 = (id, methods) => Tag$6()(id, methods);
|
|
1446
|
+
const Tag$6 = () => (id, methods) => {
|
|
1447
|
+
const definition = makeDefinition$2(id, methods);
|
|
1448
|
+
const tag = Context.Service()(id);
|
|
1449
|
+
const bindingDefinition = (binding) => ({
|
|
1450
|
+
...binding,
|
|
1451
|
+
definition
|
|
1452
|
+
});
|
|
1453
|
+
const layer = (binding) => layer$6(tag, bindingDefinition(binding));
|
|
1454
|
+
const newUniqueId = Effect.fnUntraced(function* (options) {
|
|
1455
|
+
return yield* (yield* tag).newUniqueId(options);
|
|
1456
|
+
});
|
|
1457
|
+
const idFromName = Effect.fnUntraced(function* (name) {
|
|
1458
|
+
return yield* (yield* tag).idFromName(name);
|
|
1459
|
+
});
|
|
1460
|
+
const idFromString = Effect.fnUntraced(function* (value) {
|
|
1461
|
+
return yield* (yield* tag).idFromString(value);
|
|
1462
|
+
});
|
|
1463
|
+
const get = Effect.fnUntraced(function* (objectId, options) {
|
|
1464
|
+
return yield* (yield* tag).get(objectId, options);
|
|
1465
|
+
});
|
|
1466
|
+
const getByName = Effect.fnUntraced(function* (name, options) {
|
|
1467
|
+
return yield* (yield* tag).getByName(name, options);
|
|
1468
|
+
});
|
|
1469
|
+
const jurisdiction = Effect.fnUntraced(function* (value) {
|
|
1470
|
+
return yield* (yield* tag).jurisdiction(value);
|
|
1471
|
+
});
|
|
1472
|
+
const fetch = (stub, input, init) => Effect.gen(function* () {
|
|
1473
|
+
return yield* (yield* tag).fetch(stub, input, init);
|
|
1474
|
+
});
|
|
1475
|
+
const rpc = (stub, method, ...args) => Effect.gen(function* () {
|
|
1476
|
+
return yield* (yield* tag).rpc(stub, method, ...args);
|
|
1477
|
+
});
|
|
1478
|
+
const call = (stub, method, ...args) => Effect.gen(function* () {
|
|
1479
|
+
return yield* (yield* tag).call(stub, method, ...args);
|
|
1480
|
+
});
|
|
1481
|
+
const scopedCall = (stub, method, ...args) => Effect.gen(function* () {
|
|
1482
|
+
return yield* (yield* tag).scopedCall(stub, method, ...args);
|
|
1483
|
+
});
|
|
1484
|
+
const unsafeRaw = Effect.fnUntraced(function* () {
|
|
1485
|
+
return yield* (yield* tag).unsafeRaw;
|
|
1486
|
+
});
|
|
1487
|
+
const directMethods = makeDirectMethods(definition, {
|
|
1488
|
+
call,
|
|
1489
|
+
fetch,
|
|
1490
|
+
get,
|
|
1491
|
+
getByName
|
|
1492
|
+
});
|
|
1493
|
+
return Object.assign(tag, directMethods, {
|
|
1494
|
+
id: definition.id,
|
|
1495
|
+
methods: definition.methods,
|
|
1496
|
+
make: definition.make,
|
|
1497
|
+
layer,
|
|
1498
|
+
newUniqueId,
|
|
1499
|
+
idFromName,
|
|
1500
|
+
idFromString,
|
|
1501
|
+
get,
|
|
1502
|
+
getByName,
|
|
1503
|
+
jurisdiction,
|
|
1504
|
+
fetch,
|
|
1505
|
+
rpc,
|
|
1506
|
+
call,
|
|
1507
|
+
scopedCall,
|
|
1508
|
+
unsafeRaw
|
|
1509
|
+
});
|
|
1510
|
+
};
|
|
1511
|
+
const DurableObject$1 = Tag$6;
|
|
1512
|
+
const wrapHandlers = (definition, handlers) => {
|
|
1513
|
+
const wrapped = {};
|
|
1514
|
+
for (const key of Object.keys(definition.methods)) {
|
|
1515
|
+
const handler = handlers[key];
|
|
1516
|
+
wrapped[key] = (...args) => Effect.gen(function* () {
|
|
1517
|
+
return yield* encodeSuccess(definition, key, yield* handler(...yield* decodeArgs(definition, key, args)));
|
|
1518
|
+
});
|
|
1519
|
+
}
|
|
1520
|
+
return wrapped;
|
|
1569
1521
|
};
|
|
1570
1522
|
/**
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1573
|
-
* Each defined handler is provided with {@link durableObjectLayer}. Because
|
|
1574
|
-
* Durable Object handlers run inside `Effect.scoped`, the exporter scope closes
|
|
1575
|
-
* and flushes at the end of each Cloudflare event.
|
|
1523
|
+
* Helper for implementing handlers with the exact method shape of a definition.
|
|
1576
1524
|
*/
|
|
1577
|
-
const
|
|
1578
|
-
const telemetryLayer = durableObjectLayer(options);
|
|
1579
|
-
const alarm = handlers.alarm;
|
|
1580
|
-
const webSocketMessage = handlers.webSocketMessage;
|
|
1581
|
-
const webSocketClose = handlers.webSocketClose;
|
|
1582
|
-
const webSocketError = handlers.webSocketError;
|
|
1583
|
-
return {
|
|
1584
|
-
...handlers,
|
|
1585
|
-
initialize: handlers.initialize === void 0 ? void 0 : handlers.initialize.pipe(Effect.provide(telemetryLayer)),
|
|
1586
|
-
fetch: handlers.fetch === void 0 ? void 0 : handlers.fetch.pipe(Effect.provide(telemetryLayer)),
|
|
1587
|
-
alarms: handlers.alarms === void 0 ? void 0 : handlers.alarms.pipe(Effect.provide(telemetryLayer)),
|
|
1588
|
-
alarm: alarm === void 0 ? void 0 : (alarmInfo) => alarm(alarmInfo).pipe(Effect.provide(telemetryLayer)),
|
|
1589
|
-
webSocketMessage: webSocketMessage === void 0 ? void 0 : (socket, message) => webSocketMessage(socket, message).pipe(Effect.provide(telemetryLayer)),
|
|
1590
|
-
webSocketClose: webSocketClose === void 0 ? void 0 : (socket, code, reason, wasClean) => webSocketClose(socket, code, reason, wasClean).pipe(Effect.provide(telemetryLayer)),
|
|
1591
|
-
webSocketError: webSocketError === void 0 ? void 0 : (socket, error) => webSocketError(socket, error).pipe(Effect.provide(telemetryLayer)),
|
|
1592
|
-
rpc: provideRpcLayer(handlers.rpc, telemetryLayer)
|
|
1593
|
-
};
|
|
1594
|
-
};
|
|
1525
|
+
const implement$3 = (_definition, handlers) => handlers;
|
|
1595
1526
|
//#endregion
|
|
1596
|
-
//#region src/
|
|
1597
|
-
var
|
|
1598
|
-
|
|
1599
|
-
|
|
1527
|
+
//#region src/DurableObject.ts
|
|
1528
|
+
var DurableObject_exports = /* @__PURE__ */ __exportAll({
|
|
1529
|
+
Tag: () => Tag$5,
|
|
1530
|
+
implement: () => implement$2,
|
|
1531
|
+
make: () => make$4,
|
|
1532
|
+
method: () => method
|
|
1600
1533
|
});
|
|
1601
|
-
const
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
const make$4 = (id, definition) => Service()(id, definition);
|
|
1534
|
+
const reservedMethodNames = new Set([
|
|
1535
|
+
"constructor",
|
|
1536
|
+
"dup",
|
|
1537
|
+
"fetch",
|
|
1538
|
+
"alarm",
|
|
1539
|
+
"webSocketMessage",
|
|
1540
|
+
"webSocketClose",
|
|
1541
|
+
"webSocketError"
|
|
1542
|
+
]);
|
|
1543
|
+
const RunSymbol = Symbol.for("effect-cf/DurableObject/run");
|
|
1612
1544
|
/**
|
|
1613
|
-
*
|
|
1614
|
-
*
|
|
1615
|
-
* The returned service exposes the raw `D1Database` binding and `sqlLayer(...)`
|
|
1616
|
-
* for providing `effect/unstable/sql` via `@effect/sql-d1`.
|
|
1617
|
-
*
|
|
1618
|
-
* @example
|
|
1619
|
-
* ```ts
|
|
1620
|
-
* class TodoDatabase extends D1.Service<TodoDatabase>()("TodoDatabase", {
|
|
1621
|
-
* binding: "TODO_DB",
|
|
1622
|
-
* }) {}
|
|
1623
|
-
*
|
|
1624
|
-
* const SqlLive = TodoDatabase.sqlLayer();
|
|
1625
|
-
* ```
|
|
1545
|
+
* Creates a Durable Object class backed by a single managed Effect runtime.
|
|
1626
1546
|
*/
|
|
1627
|
-
const
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
[
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1547
|
+
const make$4 = (layer, options = {}) => {
|
|
1548
|
+
class EffectDurableObject extends DurableObject {
|
|
1549
|
+
runtime;
|
|
1550
|
+
constructor(state, env) {
|
|
1551
|
+
super(state, env);
|
|
1552
|
+
const runtimeLayer = provideEntrypointServices(layer, Layer.mergeAll(Layer.succeed(DurableObjectState, fromDurableObjectState(state)), Layer.succeed(WorkerEnvironment, env)));
|
|
1553
|
+
this.runtime = ManagedRuntime.make(runtimeLayer);
|
|
1554
|
+
const initialize = options.initialize;
|
|
1555
|
+
if (initialize !== void 0) state.waitUntil(this[RunSymbol](initialize, { eventLayer: false }));
|
|
1556
|
+
}
|
|
1557
|
+
[RunSymbol](effect, runOptions = {}) {
|
|
1558
|
+
const effectWithEventLayer = runOptions.eventLayer === false || options.eventLayer === void 0 ? effect : effect.pipe(Effect.provide(options.eventLayer, { local: true }));
|
|
1559
|
+
return this.runtime.runPromise(Effect.scoped(effectWithEventLayer));
|
|
1560
|
+
}
|
|
1561
|
+
fetch(request) {
|
|
1562
|
+
const fetchHandler = options.fetch;
|
|
1563
|
+
if (fetchHandler === void 0) return Promise.resolve(new Response("Not Found", { status: 404 }));
|
|
1564
|
+
return this[RunSymbol](Effect.provideService(fetchHandler, NativeRequest, request));
|
|
1565
|
+
}
|
|
1566
|
+
alarm(alarmInfo) {
|
|
1567
|
+
const logicalAlarms = options.alarms?.pipe(Effect.asVoid);
|
|
1568
|
+
const rawAlarm = options.alarm?.(alarmInfo);
|
|
1569
|
+
if (logicalAlarms !== void 0 && rawAlarm !== void 0) return this[RunSymbol](Effect.gen(function* () {
|
|
1570
|
+
yield* logicalAlarms;
|
|
1571
|
+
yield* rawAlarm;
|
|
1572
|
+
}));
|
|
1573
|
+
if (logicalAlarms !== void 0) return this[RunSymbol](logicalAlarms);
|
|
1574
|
+
if (rawAlarm !== void 0) return this[RunSymbol](rawAlarm);
|
|
1575
|
+
}
|
|
1576
|
+
webSocketMessage(socket, message) {
|
|
1577
|
+
if (options.webSocketMessage !== void 0) return this[RunSymbol](options.webSocketMessage(fromWebSocket(socket), message));
|
|
1578
|
+
}
|
|
1579
|
+
webSocketClose(socket, code, reason, wasClean) {
|
|
1580
|
+
if (options.webSocketClose !== void 0) return this[RunSymbol](options.webSocketClose(fromWebSocket(socket), code, reason, wasClean));
|
|
1581
|
+
}
|
|
1582
|
+
webSocketError(socket, error) {
|
|
1583
|
+
if (options.webSocketError !== void 0) return this[RunSymbol](options.webSocketError(fromWebSocket(socket), error));
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
defineEntrypointRpcMethods("Durable Object", EffectDurableObject.prototype, options.rpc, reservedMethodNames, (self, effect) => self[RunSymbol](effect));
|
|
1587
|
+
return assumeEntrypointClass(EffectDurableObject);
|
|
1641
1588
|
};
|
|
1589
|
+
const Tag$5 = Tag$6;
|
|
1590
|
+
const method = method$1;
|
|
1591
|
+
const implement$2 = implement$3;
|
|
1642
1592
|
//#endregion
|
|
1643
1593
|
//#region src/DurableObjectAlarm.ts
|
|
1644
1594
|
var DurableObjectAlarm_exports = /* @__PURE__ */ __exportAll({
|