@junctionpanel/relay 0.1.16

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/dist/base64.js ADDED
@@ -0,0 +1,17 @@
1
+ import { fromByteArray, toByteArray } from "base64-js";
2
+ export function arrayBufferToBase64(buffer) {
3
+ return fromByteArray(new Uint8Array(buffer));
4
+ }
5
+ export function base64ToArrayBuffer(base64) {
6
+ const normalized = (() => {
7
+ const trimmed = base64.trim();
8
+ const standard = trimmed.replace(/-/g, "+").replace(/_/g, "/");
9
+ const padLen = (4 - (standard.length % 4)) % 4;
10
+ return standard + "=".repeat(padLen);
11
+ })();
12
+ const bytes = toByteArray(normalized);
13
+ const out = new Uint8Array(bytes.byteLength);
14
+ out.set(bytes);
15
+ return out.buffer;
16
+ }
17
+ //# sourceMappingURL=base64.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64.js","sourceRoot":"","sources":["../src/base64.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEvD,MAAM,UAAU,mBAAmB,CAAC,MAAmB;IACrD,OAAO,aAAa,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE;QACvB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC,CAAC,EAAE,CAAC;IAEL,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC7C,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACf,OAAO,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Cloudflare Durable Objects adapter for the relay.
3
+ *
4
+ * This module provides a Durable Object class that can be deployed to
5
+ * Cloudflare Workers. It uses WebSocket hibernation for cost efficiency.
6
+ *
7
+ * Each session gets its own Durable Object instance, identified by session ID.
8
+ *
9
+ * Wrangler config:
10
+ * ```jsonc
11
+ * {
12
+ * "durable_objects": {
13
+ * "bindings": [{ "name": "RELAY", "class_name": "RelayDurableObject" }]
14
+ * },
15
+ * "migrations": [{ "tag": "v1", "new_classes": ["RelayDurableObject"] }]
16
+ * }
17
+ * ```
18
+ */
19
+ interface DurableObjectState {
20
+ acceptWebSocket(ws: WebSocket, tags?: string[]): void;
21
+ getWebSockets(tag?: string): WebSocket[];
22
+ }
23
+ interface Env {
24
+ RELAY: DurableObjectNamespace;
25
+ }
26
+ interface DurableObjectNamespace {
27
+ idFromName(name: string): DurableObjectId;
28
+ get(id: DurableObjectId): DurableObjectStub;
29
+ }
30
+ interface DurableObjectId {
31
+ toString(): string;
32
+ }
33
+ interface DurableObjectStub {
34
+ fetch(request: Request): Promise<Response>;
35
+ }
36
+ export declare class RelayDurableObject {
37
+ private state;
38
+ private pendingFrames;
39
+ constructor(state: DurableObjectState);
40
+ private createWebSocketPair;
41
+ private requireWebSocketUpgrade;
42
+ private asSwitchingProtocolsResponse;
43
+ private hasServerDataSocket;
44
+ private hasClientSocket;
45
+ private nudgeOrResetControlForConnection;
46
+ private bufferFrame;
47
+ private flushFrames;
48
+ private listConnectedConnectionIds;
49
+ private notifyControls;
50
+ private fetchV1;
51
+ private fetchV2;
52
+ fetch(request: Request): Promise<Response>;
53
+ /**
54
+ * Called when a WebSocket message is received (wakes from hibernation).
55
+ */
56
+ webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void;
57
+ /**
58
+ * Called when a WebSocket closes (wakes from hibernation).
59
+ */
60
+ webSocketClose(ws: WebSocket, code: number, reason: string, _wasClean: boolean): void;
61
+ /**
62
+ * Called on WebSocket error.
63
+ */
64
+ webSocketError(ws: WebSocket, error: unknown): void;
65
+ }
66
+ /**
67
+ * Worker entry point that routes requests to the appropriate Durable Object.
68
+ */
69
+ declare const _default: {
70
+ fetch(request: Request, env: Env): Promise<Response>;
71
+ };
72
+ export default _default;
73
+ //# sourceMappingURL=cloudflare-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-adapter.d.ts","sourceRoot":"","sources":["../src/cloudflare-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAwBH,UAAU,kBAAkB;IAC1B,eAAe,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtD,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC;CAC1C;AAOD,UAAU,GAAG;IACX,KAAK,EAAE,sBAAsB,CAAC;CAC/B;AAED,UAAU,sBAAsB;IAC9B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAC;IAC1C,GAAG,CAAC,EAAE,EAAE,eAAe,GAAG,iBAAiB,CAAC;CAC7C;AAED,UAAU,eAAe;IACvB,QAAQ,IAAI,MAAM,CAAC;CACpB;AAED,UAAU,iBAAiB;IACzB,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC5C;AAkBD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,aAAa,CAAkD;gBAE3D,KAAK,EAAE,kBAAkB;IAIrC,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,uBAAuB;IAQ/B,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,gCAAgC;IAiCxC,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,0BAA0B;IAelC,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,OAAO;IAyBf,OAAO,CAAC,OAAO;IA+ET,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IA2BhD;;OAEG;IACH,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAqEpE;;OAEG;IACH,cAAc,CACZ,EAAE,EAAE,SAAS,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,OAAO,GACjB,IAAI;IA8CP;;OAEG;IACH,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;CAOpD;AAED;;GAEG;;mBAEoB,OAAO,OAAO,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;;AAD5D,wBAmCE"}
@@ -0,0 +1,420 @@
1
+ /**
2
+ * Cloudflare Durable Objects adapter for the relay.
3
+ *
4
+ * This module provides a Durable Object class that can be deployed to
5
+ * Cloudflare Workers. It uses WebSocket hibernation for cost efficiency.
6
+ *
7
+ * Each session gets its own Durable Object instance, identified by session ID.
8
+ *
9
+ * Wrangler config:
10
+ * ```jsonc
11
+ * {
12
+ * "durable_objects": {
13
+ * "bindings": [{ "name": "RELAY", "class_name": "RelayDurableObject" }]
14
+ * },
15
+ * "migrations": [{ "tag": "v1", "new_classes": ["RelayDurableObject"] }]
16
+ * }
17
+ * ```
18
+ */
19
+ const LEGACY_RELAY_VERSION = "1";
20
+ const CURRENT_RELAY_VERSION = "2";
21
+ function resolveRelayVersion(rawValue) {
22
+ if (rawValue == null)
23
+ return LEGACY_RELAY_VERSION;
24
+ const value = rawValue.trim();
25
+ if (!value)
26
+ return LEGACY_RELAY_VERSION;
27
+ if (value === LEGACY_RELAY_VERSION || value === CURRENT_RELAY_VERSION) {
28
+ return value;
29
+ }
30
+ return null;
31
+ }
32
+ export class RelayDurableObject {
33
+ constructor(state) {
34
+ this.pendingFrames = new Map();
35
+ this.state = state;
36
+ }
37
+ createWebSocketPair() {
38
+ const pair = new globalThis.WebSocketPair();
39
+ return [pair[0], pair[1]];
40
+ }
41
+ requireWebSocketUpgrade(request) {
42
+ const upgradeHeader = request.headers.get("Upgrade");
43
+ if (!upgradeHeader || upgradeHeader.toLowerCase() !== "websocket") {
44
+ return new Response("Expected WebSocket upgrade", { status: 426 });
45
+ }
46
+ return null;
47
+ }
48
+ asSwitchingProtocolsResponse(client) {
49
+ return new Response(null, {
50
+ status: 101,
51
+ webSocket: client,
52
+ });
53
+ }
54
+ hasServerDataSocket(connectionId) {
55
+ try {
56
+ return this.state.getWebSockets(`server:${connectionId}`).length > 0;
57
+ }
58
+ catch {
59
+ return false;
60
+ }
61
+ }
62
+ hasClientSocket(connectionId) {
63
+ try {
64
+ return this.state.getWebSockets(`client:${connectionId}`).length > 0;
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }
70
+ nudgeOrResetControlForConnection(connectionId) {
71
+ // If the daemon's control WS becomes half-open, the DO can't reliably detect it via ws.send errors
72
+ // (Cloudflare may accept writes even if the other side is no longer reading).
73
+ //
74
+ // Instead, observe whether the daemon reacts by opening the per-connection server-data socket.
75
+ // If it doesn't, nudge with a sync message; if still no reaction, force-close the control
76
+ // socket(s) so the daemon reconnects.
77
+ const initialDelayMs = 10000;
78
+ const secondDelayMs = 5000;
79
+ setTimeout(() => {
80
+ if (!this.hasClientSocket(connectionId))
81
+ return;
82
+ if (this.hasServerDataSocket(connectionId))
83
+ return;
84
+ // First nudge: send a full sync list.
85
+ this.notifyControls({ type: "sync", connectionIds: this.listConnectedConnectionIds() });
86
+ setTimeout(() => {
87
+ if (!this.hasClientSocket(connectionId))
88
+ return;
89
+ if (this.hasServerDataSocket(connectionId))
90
+ return;
91
+ // Still nothing: assume control is stuck and force a reconnect.
92
+ for (const ws of this.state.getWebSockets("server-control")) {
93
+ try {
94
+ ws.close(1011, "Control unresponsive");
95
+ }
96
+ catch {
97
+ // ignore
98
+ }
99
+ }
100
+ }, secondDelayMs);
101
+ }, initialDelayMs);
102
+ }
103
+ bufferFrame(connectionId, message) {
104
+ const existing = this.pendingFrames.get(connectionId) ?? [];
105
+ existing.push(message);
106
+ // Prevent unbounded memory growth if a daemon never connects.
107
+ if (existing.length > 200) {
108
+ existing.splice(0, existing.length - 200);
109
+ }
110
+ this.pendingFrames.set(connectionId, existing);
111
+ }
112
+ flushFrames(connectionId, serverWs) {
113
+ const frames = this.pendingFrames.get(connectionId);
114
+ if (!frames || frames.length === 0)
115
+ return;
116
+ this.pendingFrames.delete(connectionId);
117
+ for (const frame of frames) {
118
+ try {
119
+ serverWs.send(frame);
120
+ }
121
+ catch {
122
+ // If we can't flush, re-buffer and let the daemon re-establish.
123
+ this.bufferFrame(connectionId, frame);
124
+ break;
125
+ }
126
+ }
127
+ }
128
+ listConnectedConnectionIds() {
129
+ const out = new Set();
130
+ for (const ws of this.state.getWebSockets("client")) {
131
+ try {
132
+ const attachment = ws.deserializeAttachment();
133
+ if (attachment?.role === "client" && typeof attachment.connectionId === "string" && attachment.connectionId) {
134
+ out.add(attachment.connectionId);
135
+ }
136
+ }
137
+ catch {
138
+ // ignore
139
+ }
140
+ }
141
+ return Array.from(out);
142
+ }
143
+ notifyControls(message) {
144
+ const text = JSON.stringify(message);
145
+ for (const ws of this.state.getWebSockets("server-control")) {
146
+ try {
147
+ ws.send(text);
148
+ }
149
+ catch {
150
+ // If the control socket is dead, close it so the daemon can reconnect.
151
+ try {
152
+ ws.close(1011, "Control send failed");
153
+ }
154
+ catch {
155
+ // ignore
156
+ }
157
+ }
158
+ }
159
+ }
160
+ fetchV1(request, role, serverId) {
161
+ const upgradeError = this.requireWebSocketUpgrade(request);
162
+ if (upgradeError)
163
+ return upgradeError;
164
+ for (const ws of this.state.getWebSockets(role)) {
165
+ ws.close(1008, "Replaced by new connection");
166
+ }
167
+ const [client, server] = this.createWebSocketPair();
168
+ this.state.acceptWebSocket(server, [role]);
169
+ const attachment = {
170
+ serverId,
171
+ role,
172
+ version: LEGACY_RELAY_VERSION,
173
+ connectionId: null,
174
+ createdAt: Date.now(),
175
+ };
176
+ server.serializeAttachment(attachment);
177
+ console.log(`[Relay DO] v1:${role} connected to session ${serverId}`);
178
+ return this.asSwitchingProtocolsResponse(client);
179
+ }
180
+ fetchV2(request, role, serverId, connectionId) {
181
+ const upgradeError = this.requireWebSocketUpgrade(request);
182
+ if (upgradeError)
183
+ return upgradeError;
184
+ // If a client didn't provide a connectionId, the relay assigns one for routing.
185
+ const resolvedConnectionId = role === "client" && !connectionId
186
+ ? `conn_${crypto.randomUUID().replace(/-/g, "").slice(0, 16)}`
187
+ : connectionId;
188
+ const isServerControl = role === "server" && !resolvedConnectionId;
189
+ const isServerData = role === "server" && !!resolvedConnectionId;
190
+ // Close any existing server-side connection with the same identity.
191
+ // - server-control: single per serverId
192
+ // - server-data: single per connectionId
193
+ // - client: many sockets per connectionId are allowed
194
+ if (isServerControl) {
195
+ for (const ws of this.state.getWebSockets("server-control")) {
196
+ ws.close(1008, "Replaced by new connection");
197
+ }
198
+ }
199
+ else if (isServerData) {
200
+ for (const ws of this.state.getWebSockets(`server:${resolvedConnectionId}`)) {
201
+ ws.close(1008, "Replaced by new connection");
202
+ }
203
+ }
204
+ const [client, server] = this.createWebSocketPair();
205
+ const tags = [];
206
+ if (role === "client") {
207
+ tags.push("client", `client:${resolvedConnectionId}`);
208
+ }
209
+ else if (isServerControl) {
210
+ tags.push("server-control");
211
+ }
212
+ else {
213
+ tags.push("server", `server:${resolvedConnectionId}`);
214
+ }
215
+ this.state.acceptWebSocket(server, tags);
216
+ const attachment = {
217
+ serverId,
218
+ role,
219
+ version: CURRENT_RELAY_VERSION,
220
+ connectionId: resolvedConnectionId || null,
221
+ createdAt: Date.now(),
222
+ };
223
+ server.serializeAttachment(attachment);
224
+ console.log(`[Relay DO] v2:${role}${isServerControl ? "(control)" : ""}${isServerData ? `(data:${resolvedConnectionId})` : role === "client" ? `(${resolvedConnectionId})` : ""} connected to session ${serverId}`);
225
+ if (role === "client") {
226
+ this.notifyControls({ type: "connected", connectionId: resolvedConnectionId });
227
+ this.nudgeOrResetControlForConnection(resolvedConnectionId);
228
+ }
229
+ if (isServerControl) {
230
+ // Send current connection list so the daemon can attach existing connections.
231
+ try {
232
+ server.send(JSON.stringify({ type: "sync", connectionIds: this.listConnectedConnectionIds() }));
233
+ }
234
+ catch {
235
+ // ignore
236
+ }
237
+ }
238
+ if (isServerData && resolvedConnectionId) {
239
+ this.flushFrames(resolvedConnectionId, server);
240
+ }
241
+ return this.asSwitchingProtocolsResponse(client);
242
+ }
243
+ async fetch(request) {
244
+ const url = new URL(request.url);
245
+ const role = url.searchParams.get("role");
246
+ const serverId = url.searchParams.get("serverId");
247
+ const connectionIdRaw = url.searchParams.get("connectionId");
248
+ const connectionId = typeof connectionIdRaw === "string" ? connectionIdRaw.trim() : "";
249
+ const version = resolveRelayVersion(url.searchParams.get("v"));
250
+ if (!role || (role !== "server" && role !== "client")) {
251
+ return new Response("Missing or invalid role parameter", { status: 400 });
252
+ }
253
+ if (!serverId) {
254
+ return new Response("Missing serverId parameter", { status: 400 });
255
+ }
256
+ if (!version) {
257
+ return new Response("Invalid v parameter (expected 1 or 2)", { status: 400 });
258
+ }
259
+ if (version === LEGACY_RELAY_VERSION) {
260
+ return this.fetchV1(request, role, serverId);
261
+ }
262
+ return this.fetchV2(request, role, serverId, connectionId);
263
+ }
264
+ /**
265
+ * Called when a WebSocket message is received (wakes from hibernation).
266
+ */
267
+ webSocketMessage(ws, message) {
268
+ const attachment = ws.deserializeAttachment();
269
+ if (!attachment) {
270
+ console.error("[Relay DO] Message from WebSocket without attachment");
271
+ return;
272
+ }
273
+ const version = attachment.version ?? LEGACY_RELAY_VERSION;
274
+ if (version === LEGACY_RELAY_VERSION) {
275
+ const targetRole = attachment.role === "server" ? "client" : "server";
276
+ const targets = this.state.getWebSockets(targetRole);
277
+ for (const target of targets) {
278
+ try {
279
+ target.send(message);
280
+ }
281
+ catch (error) {
282
+ console.error(`[Relay DO] Failed to forward to ${targetRole}:`, error);
283
+ }
284
+ }
285
+ return;
286
+ }
287
+ const { role, connectionId } = attachment;
288
+ if (!connectionId) {
289
+ // Control channel: support simple app-level keepalive.
290
+ if (typeof message === "string") {
291
+ try {
292
+ const parsed = JSON.parse(message);
293
+ if (parsed?.type === "ping") {
294
+ try {
295
+ ws.send(JSON.stringify({ type: "pong", ts: Date.now() }));
296
+ }
297
+ catch {
298
+ // ignore
299
+ }
300
+ }
301
+ }
302
+ catch {
303
+ // ignore non-JSON control payloads
304
+ }
305
+ }
306
+ return;
307
+ }
308
+ if (role === "client") {
309
+ const servers = this.state.getWebSockets(`server:${connectionId}`);
310
+ if (servers.length === 0) {
311
+ this.bufferFrame(connectionId, message);
312
+ return;
313
+ }
314
+ for (const target of servers) {
315
+ try {
316
+ target.send(message);
317
+ }
318
+ catch (error) {
319
+ console.error(`[Relay DO] Failed to forward client->server(${connectionId}):`, error);
320
+ }
321
+ }
322
+ return;
323
+ }
324
+ // server data socket -> client
325
+ const targets = this.state.getWebSockets(`client:${connectionId}`);
326
+ for (const target of targets) {
327
+ try {
328
+ target.send(message);
329
+ }
330
+ catch (error) {
331
+ console.error(`[Relay DO] Failed to forward server->client(${connectionId}):`, error);
332
+ }
333
+ }
334
+ }
335
+ /**
336
+ * Called when a WebSocket closes (wakes from hibernation).
337
+ */
338
+ webSocketClose(ws, code, reason, _wasClean) {
339
+ const attachment = ws.deserializeAttachment();
340
+ if (!attachment)
341
+ return;
342
+ const version = attachment.version ?? LEGACY_RELAY_VERSION;
343
+ console.log(`[Relay DO] v${version}:${attachment.role}${attachment.connectionId ? `(${attachment.connectionId})` : ""} disconnected from session ${attachment.serverId} (${code}: ${reason})`);
344
+ if (version === LEGACY_RELAY_VERSION) {
345
+ return;
346
+ }
347
+ if (attachment.role === "client" && attachment.connectionId) {
348
+ const remainingClientSockets = this.state
349
+ .getWebSockets(`client:${attachment.connectionId}`)
350
+ .some((socket) => socket !== ws);
351
+ if (remainingClientSockets) {
352
+ return;
353
+ }
354
+ this.pendingFrames.delete(attachment.connectionId);
355
+ // Last socket for this session closed: now clean up matching server-data socket.
356
+ for (const serverWs of this.state.getWebSockets(`server:${attachment.connectionId}`)) {
357
+ try {
358
+ serverWs.close(1001, "Client disconnected");
359
+ }
360
+ catch {
361
+ // ignore
362
+ }
363
+ }
364
+ this.notifyControls({ type: "disconnected", connectionId: attachment.connectionId });
365
+ return;
366
+ }
367
+ if (attachment.role === "server" && attachment.connectionId) {
368
+ // Force the client to reconnect and re-handshake when the daemon side drops.
369
+ for (const clientWs of this.state.getWebSockets(`client:${attachment.connectionId}`)) {
370
+ try {
371
+ clientWs.close(1012, "Server disconnected");
372
+ }
373
+ catch {
374
+ // ignore
375
+ }
376
+ }
377
+ }
378
+ }
379
+ /**
380
+ * Called on WebSocket error.
381
+ */
382
+ webSocketError(ws, error) {
383
+ const attachment = ws.deserializeAttachment();
384
+ console.error(`[Relay DO] WebSocket error for ${attachment?.role ?? "unknown"}:`, error);
385
+ }
386
+ }
387
+ /**
388
+ * Worker entry point that routes requests to the appropriate Durable Object.
389
+ */
390
+ export default {
391
+ async fetch(request, env) {
392
+ const url = new URL(request.url);
393
+ // Health check
394
+ if (url.pathname === "/health") {
395
+ return new Response(JSON.stringify({ status: "ok" }), {
396
+ headers: { "Content-Type": "application/json" },
397
+ });
398
+ }
399
+ // Relay endpoint
400
+ if (url.pathname === "/ws") {
401
+ const serverId = url.searchParams.get("serverId");
402
+ if (!serverId) {
403
+ return new Response("Missing serverId parameter", { status: 400 });
404
+ }
405
+ const version = resolveRelayVersion(url.searchParams.get("v"));
406
+ if (!version) {
407
+ return new Response("Invalid v parameter (expected 1 or 2)", { status: 400 });
408
+ }
409
+ // Route to a version-isolated Durable Object instance.
410
+ const id = env.RELAY.idFromName(`relay-v${version}:${serverId}`);
411
+ const stub = env.RELAY.get(id);
412
+ const normalizedUrl = new URL(request.url);
413
+ normalizedUrl.searchParams.set("v", version);
414
+ const normalizedRequest = new Request(normalizedUrl.toString(), request);
415
+ return stub.fetch(normalizedRequest);
416
+ }
417
+ return new Response("Not found", { status: 404 });
418
+ },
419
+ };
420
+ //# sourceMappingURL=cloudflare-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-adapter.js","sourceRoot":"","sources":["../src/cloudflare-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * E2EE crypto primitives using NaCl (tweetnacl).
3
+ *
4
+ * - Key exchange: Curve25519 (nacl.box.before)
5
+ * - Encryption: XSalsa20-Poly1305 (nacl.box.after / open.after)
6
+ *
7
+ * Bundle format (binary):
8
+ * [nonce (24 bytes)] [ciphertext...]
9
+ *
10
+ * Transport format:
11
+ * The encrypted-channel sends the bundle as base64 text over WebSocket.
12
+ */
13
+ export type KeyPair = {
14
+ publicKey: Uint8Array;
15
+ secretKey: Uint8Array;
16
+ };
17
+ export type SharedKey = Uint8Array;
18
+ export declare function generateKeyPair(): KeyPair;
19
+ export declare function exportPublicKey(publicKey: Uint8Array): string;
20
+ export declare function importPublicKey(base64: string): Uint8Array;
21
+ export declare function exportSecretKey(secretKey: Uint8Array): string;
22
+ export declare function importSecretKey(base64: string): Uint8Array;
23
+ export declare function deriveSharedKey(ourSecretKey: Uint8Array, peerPublicKey: Uint8Array): SharedKey;
24
+ /**
25
+ * Encrypts data and returns the binary bundle:
26
+ * [nonce (24)] [ciphertext...]
27
+ */
28
+ export declare function encrypt(sharedKey: SharedKey, data: string | ArrayBuffer): ArrayBuffer;
29
+ export declare function decrypt(sharedKey: SharedKey, data: ArrayBuffer): string | ArrayBuffer;
30
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;GAWG;AAKH,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC;AA+CnC,wBAAgB,eAAe,IAAI,OAAO,CAIzC;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAK7D;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAM1D;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAK7D;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAM1D;AAED,wBAAgB,eAAe,CAC7B,YAAY,EAAE,UAAU,EACxB,aAAa,EAAE,UAAU,GACxB,SAAS,CAQX;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,CASrF;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,WAAW,CAmBrF"}