@derivation/rpc 0.5.1 → 0.6.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.
Files changed (47) hide show
  1. package/dist/index.cjs +0 -209
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +0 -2
  4. package/dist/index.d.ts +0 -2
  5. package/dist/index.js +0 -208
  6. package/dist/index.js.map +1 -1
  7. package/dist/{shared-worker-server.cjs → shared-worker.cjs} +185 -47
  8. package/dist/shared-worker.cjs.map +1 -0
  9. package/dist/shared-worker.d.cts +68 -0
  10. package/dist/shared-worker.d.ts +68 -0
  11. package/dist/{shared-worker-server.js → shared-worker.js} +179 -43
  12. package/dist/shared-worker.js.map +1 -0
  13. package/dist/{shared-worker-client.cjs → websocket-client.cjs} +21 -55
  14. package/dist/websocket-client.cjs.map +1 -0
  15. package/dist/{client-DJZfuakf.d.cts → websocket-client.d.cts} +4 -5
  16. package/dist/{client-TPsVZH_B.d.ts → websocket-client.d.ts} +4 -5
  17. package/dist/{shared-worker-client.js → websocket-client.js} +16 -50
  18. package/dist/websocket-client.js.map +1 -0
  19. package/dist/{web-socket-server.cjs → websocket-server.cjs} +19 -49
  20. package/dist/websocket-server.cjs.map +1 -0
  21. package/dist/{web-socket-server.js → websocket-server.js} +19 -49
  22. package/dist/websocket-server.js.map +1 -0
  23. package/package.json +18 -28
  24. package/dist/shared-worker-client.cjs.map +0 -1
  25. package/dist/shared-worker-client.d.cts +0 -26
  26. package/dist/shared-worker-client.d.ts +0 -26
  27. package/dist/shared-worker-client.js.map +0 -1
  28. package/dist/shared-worker-server.cjs.map +0 -1
  29. package/dist/shared-worker-server.d.cts +0 -31
  30. package/dist/shared-worker-server.d.ts +0 -31
  31. package/dist/shared-worker-server.js.map +0 -1
  32. package/dist/transport.cjs +0 -19
  33. package/dist/transport.cjs.map +0 -1
  34. package/dist/transport.d.cts +0 -29
  35. package/dist/transport.d.ts +0 -29
  36. package/dist/transport.js +0 -1
  37. package/dist/transport.js.map +0 -1
  38. package/dist/web-socket-server.cjs.map +0 -1
  39. package/dist/web-socket-server.js.map +0 -1
  40. package/dist/web-socket-transport.cjs +0 -52
  41. package/dist/web-socket-transport.cjs.map +0 -1
  42. package/dist/web-socket-transport.d.cts +0 -16
  43. package/dist/web-socket-transport.d.ts +0 -16
  44. package/dist/web-socket-transport.js +0 -27
  45. package/dist/web-socket-transport.js.map +0 -1
  46. /package/dist/{web-socket-server.d.cts → websocket-server.d.cts} +0 -0
  47. /package/dist/{web-socket-server.d.ts → websocket-server.d.ts} +0 -0
@@ -56,7 +56,7 @@ var ClientMessage = {
56
56
  })
57
57
  };
58
58
 
59
- // src/client.ts
59
+ // src/websocket/web-socket-client.ts
60
60
  function changer(sink, input) {
61
61
  return (change) => {
62
62
  const i = input.deref();
@@ -65,9 +65,9 @@ function changer(sink, input) {
65
65
  }
66
66
  };
67
67
  }
68
- var Client = class {
69
- constructor(transport, sinks, graph) {
70
- this.transport = transport;
68
+ var WebSocketClient = class {
69
+ constructor(ws, sinks, graph) {
70
+ this.ws = ws;
71
71
  this.sinks = sinks;
72
72
  this.graph = graph;
73
73
  this.nextId = 1;
@@ -81,10 +81,10 @@ var Client = class {
81
81
  this.activeStreams.delete(id);
82
82
  }
83
83
  );
84
- this.transport.onMessage((data) => {
85
- const message = JSON.parse(data);
84
+ this.ws.onmessage = (event) => {
85
+ const message = JSON.parse(event.data);
86
86
  this.handleMessage(message);
87
- });
87
+ };
88
88
  this.resetHeartbeat();
89
89
  this.resetInactivity();
90
90
  }
@@ -108,7 +108,7 @@ var Client = class {
108
108
  this.resetInactivity();
109
109
  switch (message.type) {
110
110
  case "snapshot": {
111
- console.log(`[Client] Received snapshot for stream ${message.id}`);
111
+ console.log(`[WebSocketClient] Received snapshot for stream ${message.id}`);
112
112
  const resolve = this.pendingStreams.get(message.id);
113
113
  if (resolve) {
114
114
  resolve(message.snapshot);
@@ -118,7 +118,7 @@ var Client = class {
118
118
  }
119
119
  case "delta": {
120
120
  const changeCount = Object.keys(message.changes).length;
121
- console.log(`[Client] Received delta with ${changeCount} changes for streams: ${Object.keys(message.changes).join(", ")}`);
121
+ console.log(`[WebSocketClient] Received delta with ${changeCount} changes for streams: ${Object.keys(message.changes).join(", ")}`);
122
122
  for (const [idStr, change] of Object.entries(message.changes)) {
123
123
  const id = Number(idStr);
124
124
  const sink = this.activeStreams.get(id);
@@ -130,12 +130,12 @@ var Client = class {
130
130
  this.activeStreams.delete(id);
131
131
  }
132
132
  }
133
- console.log("[Client] Stepping graph");
133
+ console.log("[WebSocketClient] Stepping graph");
134
134
  this.graph.step();
135
135
  break;
136
136
  }
137
137
  case "result": {
138
- console.log(`[Client] Received mutation result for call ${message.id}:`, message.success ? "success" : "error");
138
+ console.log(`[WebSocketClient] Received mutation result for call ${message.id}:`, message.success ? "success" : "error");
139
139
  const resolve = this.pendingMutations.get(message.id);
140
140
  if (resolve) {
141
141
  if (message.success) {
@@ -151,13 +151,13 @@ var Client = class {
151
151
  break;
152
152
  }
153
153
  case "heartbeat":
154
- console.log("[Client] Received heartbeat");
154
+ console.log("[WebSocketClient] Received heartbeat");
155
155
  break;
156
156
  }
157
157
  }
158
158
  sendMessage(message) {
159
159
  this.resetHeartbeat();
160
- this.transport.send(JSON.stringify(message));
160
+ this.ws.send(JSON.stringify(message));
161
161
  }
162
162
  async run(key, args) {
163
163
  console.log(
@@ -196,7 +196,7 @@ var Client = class {
196
196
  clearTimeout(this.heartbeatTimeout);
197
197
  clearTimeout(this.inactivityTimeout);
198
198
  try {
199
- this.transport.close();
199
+ this.ws.close();
200
200
  } catch (e) {
201
201
  }
202
202
  }
@@ -204,41 +204,7 @@ var Client = class {
204
204
  this.sendMessage(ClientMessage.presence(value));
205
205
  }
206
206
  };
207
-
208
- // src/messageport-transport.ts
209
- var MessagePortTransport = class {
210
- constructor(port) {
211
- this.port = port;
212
- }
213
- send(data) {
214
- console.log("[MessagePortTransport] Sending:", data.substring(0, 100) + (data.length > 100 ? "..." : ""));
215
- this.port.postMessage(data);
216
- }
217
- onMessage(handler) {
218
- this.port.onmessage = (event) => {
219
- console.log("[MessagePortTransport] Received:", event.data.substring(0, 100) + (event.data.length > 100 ? "..." : ""));
220
- handler(event.data);
221
- };
222
- }
223
- onClose(handler) {
224
- this.port.onmessageerror = handler;
225
- }
226
- close() {
227
- this.port.close();
228
- }
229
- // MessagePort doesn't provide bufferedAmount
230
- get bufferedAmount() {
231
- return void 0;
232
- }
233
- };
234
-
235
- // src/shared-worker-client.ts
236
- function createSharedWorkerClient(port, sinks, graph) {
237
- const transport = new MessagePortTransport(port);
238
- port.start();
239
- return new Client(transport, sinks, graph);
240
- }
241
207
  export {
242
- createSharedWorkerClient
208
+ WebSocketClient
243
209
  };
244
- //# sourceMappingURL=shared-worker-client.js.map
210
+ //# sourceMappingURL=websocket-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client-message.ts","../src/websocket/web-socket-client.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const SubscribeMessageSchema = z.object({\n type: z.literal(\"subscribe\"),\n id: z.number(),\n name: z.string(),\n args: z.looseObject({}),\n});\nexport type SubscribeMessage = z.infer<typeof SubscribeMessageSchema>;\n\nexport const UnsubscribeMessageSchema = z.object({\n type: z.literal(\"unsubscribe\"),\n id: z.number(),\n});\nexport type UnsubscribeMessage = z.infer<typeof UnsubscribeMessageSchema>;\n\nexport const HeartbeatMessageSchema = z.object({\n type: z.literal(\"heartbeat\"),\n});\nexport type HeartbeatMessage = z.infer<typeof HeartbeatMessageSchema>;\n\nexport const CallMessageSchema = z.object({\n type: z.literal(\"call\"),\n id: z.number(),\n name: z.string(),\n args: z.looseObject({}),\n});\nexport type CallMessage = z.infer<typeof CallMessageSchema>;\n\nexport const PresenceMessageSchema = z.object({\n type: z.literal(\"presence\"),\n data: z.looseObject({}),\n});\nexport type PresenceMessage = z.infer<typeof PresenceMessageSchema>;\n\nexport const ClientMessageSchema = z.discriminatedUnion(\"type\", [\n SubscribeMessageSchema,\n UnsubscribeMessageSchema,\n HeartbeatMessageSchema,\n CallMessageSchema,\n PresenceMessageSchema,\n]);\nexport type ClientMessage = z.infer<typeof ClientMessageSchema>;\n\nexport function parseClientMessage(data: unknown): ClientMessage {\n return ClientMessageSchema.parse(data);\n}\n\nexport const ClientMessage = {\n subscribe: (\n id: number,\n name: string,\n args: object,\n ): SubscribeMessage => ({\n type: \"subscribe\",\n id,\n name,\n args: args as Record<string, unknown>,\n }),\n unsubscribe: (id: number): UnsubscribeMessage => ({\n type: \"unsubscribe\",\n id,\n }),\n call: (\n id: number,\n name: string,\n args: object,\n ): CallMessage => ({\n type: \"call\",\n id,\n name,\n args: args as Record<string, unknown>,\n }),\n heartbeat: (): HeartbeatMessage => ({\n type: \"heartbeat\",\n }),\n presence: (data: object): PresenceMessage => ({\n type: \"presence\",\n data: data as Record<string, unknown>,\n }),\n};\n","import { ClientMessage } from \"../client-message.js\";\nimport { ServerMessage } from \"../server-message.js\";\nimport type { Graph } from \"derivation\";\nimport type {\n Sink,\n StreamSinks,\n RPCDefinition,\n MutationResult,\n} from \"../stream-types.js\";\n\nfunction changer<T extends object, I extends object>(\n sink: Sink<T, I>,\n input: WeakRef<I>,\n): (change: object) => void {\n return (change) => {\n const i = input.deref();\n if (i) {\n sink.apply(change, i);\n }\n };\n}\n\nexport class WebSocketClient<Defs extends RPCDefinition> {\n private nextId = 1;\n private pendingStreams = new Map<number, (snapshot: object) => void>();\n private pendingMutations = new Map<\n number,\n (result: MutationResult<unknown>) => void\n >();\n private activeStreams = new Map<number, (change: object) => void>();\n private heartbeatTimeout: NodeJS.Timeout | undefined;\n private inactivityTimeout: NodeJS.Timeout | undefined;\n\n private registry = new FinalizationRegistry<[number, string]>(\n ([id, name]) => {\n console.log(`🧹 Stream ${id} (${name}) collected — unsubscribing`);\n this.sendMessage(ClientMessage.unsubscribe(id));\n this.activeStreams.delete(id);\n },\n );\n\n private resetHeartbeat() {\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n }\n\n this.heartbeatTimeout = setTimeout(() => {\n this.sendMessage(ClientMessage.heartbeat());\n }, 10_000);\n }\n\n private resetInactivity() {\n if (this.inactivityTimeout) {\n clearTimeout(this.inactivityTimeout);\n }\n\n this.inactivityTimeout = setTimeout(() => {\n this.close();\n }, 30_000);\n }\n\n constructor(\n private ws: globalThis.WebSocket,\n private sinks: StreamSinks<Defs[\"streams\"]>,\n private graph: Graph,\n ) {\n this.ws.onmessage = (event: MessageEvent) => {\n const message = JSON.parse(event.data as string) as ServerMessage;\n this.handleMessage(message);\n };\n this.resetHeartbeat();\n this.resetInactivity();\n }\n\n private handleMessage(message: ServerMessage) {\n this.resetInactivity();\n\n switch (message.type) {\n case \"snapshot\": {\n console.log(`[WebSocketClient] Received snapshot for stream ${message.id}`);\n const resolve = this.pendingStreams.get(message.id);\n if (resolve) {\n resolve(message.snapshot as object);\n this.pendingStreams.delete(message.id);\n }\n break;\n }\n case \"delta\": {\n const changeCount = Object.keys(message.changes).length;\n console.log(`[WebSocketClient] Received delta with ${changeCount} changes for streams: ${Object.keys(message.changes).join(\", \")}`);\n for (const [idStr, change] of Object.entries(message.changes)) {\n const id = Number(idStr);\n const sink = this.activeStreams.get(id);\n\n if (sink && change && typeof change === \"object\") {\n sink(change);\n } else if (!sink) {\n console.log(`🧹 Sink ${id} GC'd — auto-unsubscribing`);\n this.sendMessage(ClientMessage.unsubscribe(id));\n this.activeStreams.delete(id);\n }\n }\n console.log(\"[WebSocketClient] Stepping graph\");\n this.graph.step();\n break;\n }\n case \"result\": {\n console.log(`[WebSocketClient] Received mutation result for call ${message.id}:`, message.success ? \"success\" : \"error\");\n const resolve = this.pendingMutations.get(message.id);\n if (resolve) {\n if (message.success) {\n resolve({ success: true, value: message.value });\n } else {\n resolve({\n success: false,\n error: message.error || \"Unknown error\",\n });\n }\n this.pendingMutations.delete(message.id);\n }\n break;\n }\n case \"heartbeat\":\n console.log(\"[WebSocketClient] Received heartbeat\");\n break;\n }\n }\n\n private sendMessage(message: ClientMessage) {\n this.resetHeartbeat();\n this.ws.send(JSON.stringify(message));\n }\n\n async run<Key extends keyof Defs[\"streams\"]>(\n key: Key,\n args: Defs[\"streams\"][Key][\"args\"],\n ): Promise<Defs[\"streams\"][Key][\"returnType\"]> {\n console.log(\n `Running stream ${String(key)} with args ${JSON.stringify(args)}`,\n );\n const id = this.nextId++;\n\n this.sendMessage(ClientMessage.subscribe(id, String(key), args));\n\n const snapshot = await new Promise<object>((resolve) => {\n this.pendingStreams.set(id, resolve);\n });\n\n const endpoint = this.sinks[key];\n const sinkAdapter = endpoint(snapshot);\n const { stream, input } = sinkAdapter.build();\n const inputRef = new WeakRef(input);\n this.activeStreams.set(id, changer(sinkAdapter, inputRef));\n this.registry.register(input, [id, String(key)]);\n\n return stream;\n }\n\n async call<Key extends keyof Defs[\"mutations\"]>(\n key: Key,\n args: Defs[\"mutations\"][Key][\"args\"],\n ): Promise<MutationResult<Defs[\"mutations\"][Key][\"result\"]>> {\n console.log(\n `Calling mutation ${String(key)} with args ${JSON.stringify(args)}`,\n );\n const id = this.nextId++;\n\n this.sendMessage(\n ClientMessage.call(id, String(key), args as Record<string, unknown>),\n );\n\n const result = await new Promise<\n MutationResult<Defs[\"mutations\"][Key][\"result\"]>\n >((resolve) => {\n this.pendingMutations.set(\n id,\n resolve as (result: MutationResult<unknown>) => void,\n );\n });\n\n return result;\n }\n\n close() {\n clearTimeout(this.heartbeatTimeout);\n clearTimeout(this.inactivityTimeout);\n try {\n this.ws.close();\n } catch {}\n }\n\n setPresence(value: Record<string, unknown>): void {\n this.sendMessage(ClientMessage.presence(value));\n }\n}\n"],"mappings":"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","names":[]}
@@ -17,7 +17,7 @@ var __copyProps = (to, from, except, desc) => {
17
17
  };
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
- // src/web-socket-server.ts
20
+ // src/websocket/web-socket-server.ts
21
21
  var web_socket_server_exports = {};
22
22
  __export(web_socket_server_exports, {
23
23
  setupWebSocketServer: () => setupWebSocketServer
@@ -116,7 +116,7 @@ var ServerMessage = {
116
116
  })
117
117
  };
118
118
 
119
- // src/queue.ts
119
+ // src/websocket/queue.ts
120
120
  var Queue = class {
121
121
  constructor() {
122
122
  this.front = [];
@@ -149,7 +149,7 @@ var Queue = class {
149
149
  }
150
150
  };
151
151
 
152
- // src/rate-limiter.ts
152
+ // src/websocket/rate-limiter.ts
153
153
  var RateLimiter = class {
154
154
  constructor(maxOccurrences, windowSeconds) {
155
155
  this.timestamps = new Queue();
@@ -174,20 +174,23 @@ var RateLimiter = class {
174
174
  }
175
175
  };
176
176
 
177
- // src/client-handler.ts
178
- var ClientHandler = class {
179
- constructor(transport, context, streamEndpoints, mutationEndpoints, presenceHandler) {
177
+ // src/websocket/web-socket-client-handler.ts
178
+ var WebSocketClientHandler = class {
179
+ constructor(ws, context, streamEndpoints, mutationEndpoints, presenceHandler) {
180
180
  this.closed = false;
181
181
  this.streams = /* @__PURE__ */ new Map();
182
- this.transport = transport;
182
+ this.ws = ws;
183
183
  this.context = context;
184
184
  this.streamEndpoints = streamEndpoints;
185
185
  this.mutationEndpoints = mutationEndpoints;
186
186
  this.presenceHandler = presenceHandler;
187
187
  this.rateLimiter = new RateLimiter(100, 300);
188
188
  console.log("new client connected");
189
- this.transport.onMessage((data) => this.handleMessage(data));
190
- this.transport.onClose(() => this.handleDisconnect());
189
+ this.ws.on(
190
+ "message",
191
+ (data) => this.handleMessage(data.toString())
192
+ );
193
+ this.ws.on("close", () => this.handleDisconnect());
191
194
  this.resetHeartbeat();
192
195
  this.resetInactivity();
193
196
  }
@@ -326,13 +329,13 @@ var ClientHandler = class {
326
329
  sendMessage(message) {
327
330
  this.resetHeartbeat();
328
331
  if (!this.closed) {
329
- if (this.transport.bufferedAmount !== void 0 && this.transport.bufferedAmount > 100 * 1024) {
332
+ if (this.ws.bufferedAmount > 100 * 1024) {
330
333
  console.log("Send buffer exceeded 100KB, closing connection");
331
334
  this.close();
332
335
  return;
333
336
  }
334
337
  try {
335
- this.transport.send(JSON.stringify(message));
338
+ this.ws.send(JSON.stringify(message));
336
339
  } catch (err) {
337
340
  console.error("Failed to send message:", err);
338
341
  this.close();
@@ -352,7 +355,7 @@ var ClientHandler = class {
352
355
  this.presenceHandler.remove(this.currentPresence);
353
356
  }
354
357
  try {
355
- this.transport.close();
358
+ this.ws.close();
356
359
  } catch (e) {
357
360
  }
358
361
  }
@@ -379,39 +382,7 @@ var WeakList = class {
379
382
  }
380
383
  };
381
384
 
382
- // src/node-web-socket-transport.ts
383
- var NodeWebSocketTransport = class {
384
- constructor(ws) {
385
- this.ws = ws;
386
- this.messageHandlerSet = false;
387
- this.closeHandlerSet = false;
388
- }
389
- send(data) {
390
- this.ws.send(data);
391
- }
392
- onMessage(handler) {
393
- if (!this.messageHandlerSet) {
394
- this.ws.on("message", (data) => {
395
- handler(data.toString());
396
- });
397
- this.messageHandlerSet = true;
398
- }
399
- }
400
- onClose(handler) {
401
- if (!this.closeHandlerSet) {
402
- this.ws.on("close", handler);
403
- this.closeHandlerSet = true;
404
- }
405
- }
406
- close() {
407
- this.ws.close();
408
- }
409
- get bufferedAmount() {
410
- return this.ws.bufferedAmount;
411
- }
412
- };
413
-
414
- // src/web-socket-server.ts
385
+ // src/websocket/web-socket-server.ts
415
386
  function setupWebSocketServer(graph, server, streamEndpoints, mutationEndpoints, options) {
416
387
  const { createContext, presenceHandler, path = "/api/ws" } = options;
417
388
  const clients = new WeakList();
@@ -432,9 +403,8 @@ function setupWebSocketServer(graph, server, streamEndpoints, mutationEndpoints,
432
403
  ws.on("message", tempMessageHandler);
433
404
  Promise.resolve(createContext(ws, req)).then((context) => {
434
405
  ws.removeListener("message", tempMessageHandler);
435
- const transport = new NodeWebSocketTransport(ws);
436
- client = new ClientHandler(
437
- transport,
406
+ client = new WebSocketClientHandler(
407
+ ws,
438
408
  context,
439
409
  streamEndpoints,
440
410
  mutationEndpoints,
@@ -466,4 +436,4 @@ function setupWebSocketServer(graph, server, streamEndpoints, mutationEndpoints,
466
436
  0 && (module.exports = {
467
437
  setupWebSocketServer
468
438
  });
469
- //# sourceMappingURL=web-socket-server.cjs.map
439
+ //# sourceMappingURL=websocket-server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/websocket/web-socket-server.ts","../src/client-message.ts","../src/server-message.ts","../src/websocket/queue.ts","../src/websocket/rate-limiter.ts","../src/websocket/web-socket-client-handler.ts","../src/weak-list.ts"],"sourcesContent":["import { parse } from \"url\";\nimport { Server, IncomingMessage } from \"http\";\nimport { WebSocketServer, WebSocket, RawData } from \"ws\";\nimport { WebSocketClientHandler } from \"./web-socket-client-handler.js\";\nimport WeakList from \"../weak-list.js\";\nimport {\n StreamEndpoints,\n MutationEndpoints,\n RPCDefinition,\n} from \"../stream-types.js\";\nimport { Graph } from \"derivation\";\nimport { PresenceHandler } from \"../presence-manager.js\";\n\nexport type WebSocketServerOptions<Ctx> = {\n createContext: (ws: WebSocket, req: IncomingMessage) => Ctx | Promise<Ctx>;\n presenceHandler?: PresenceHandler;\n path?: string;\n};\n\nexport function setupWebSocketServer<Defs extends RPCDefinition, Ctx = void>(\n graph: Graph,\n server: Server,\n streamEndpoints: StreamEndpoints<Defs[\"streams\"], Ctx>,\n mutationEndpoints: MutationEndpoints<Defs[\"mutations\"], Ctx>,\n options: WebSocketServerOptions<Ctx>,\n) {\n const { createContext, presenceHandler, path = \"/api/ws\" } = options;\n const clients = new WeakList<WebSocketClientHandler<Defs, Ctx>>();\n\n graph.afterStep(() => {\n for (const client of clients) {\n client.handleStep();\n }\n });\n\n const wss = new WebSocketServer({ noServer: true, maxPayload: 100 * 1024 });\n\n // Handle WebSocket connections for reactive streams\n wss.on(\"connection\", (ws, req) => {\n const { pathname } = parse(req.url || \"/\", true);\n if (pathname === path) {\n const messageBuffer: RawData[] = [];\n let client: WebSocketClientHandler<Defs, Ctx> | null = null;\n\n // Set up temporary message handler to buffer messages\n const tempMessageHandler = (msg: RawData) => {\n messageBuffer.push(msg);\n };\n ws.on(\"message\", tempMessageHandler);\n\n // Create context (handle both sync and async)\n Promise.resolve(createContext(ws, req))\n .then((context) => {\n // Remove temporary handler\n ws.removeListener(\"message\", tempMessageHandler);\n\n // Create client handler\n client = new WebSocketClientHandler<Defs, Ctx>(\n ws,\n context,\n streamEndpoints,\n mutationEndpoints,\n presenceHandler,\n );\n clients.add(client);\n\n // Process buffered messages\n for (const msg of messageBuffer) {\n client.handleMessage(msg.toString());\n }\n messageBuffer.length = 0;\n })\n .catch((err) => {\n console.error(\"Error creating context:\", err);\n ws.close();\n });\n }\n });\n\n // Handle HTTP upgrade (for /api/ws)\n server.on(\"upgrade\", (req, socket, head) => {\n const { pathname } = parse(req.url || \"/\", true);\n\n if (pathname === \"/api/ws\") {\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit(\"connection\", ws, req);\n });\n } else {\n socket.destroy();\n }\n });\n}\n","import { z } from \"zod\";\n\nexport const SubscribeMessageSchema = z.object({\n type: z.literal(\"subscribe\"),\n id: z.number(),\n name: z.string(),\n args: z.looseObject({}),\n});\nexport type SubscribeMessage = z.infer<typeof SubscribeMessageSchema>;\n\nexport const UnsubscribeMessageSchema = z.object({\n type: z.literal(\"unsubscribe\"),\n id: z.number(),\n});\nexport type UnsubscribeMessage = z.infer<typeof UnsubscribeMessageSchema>;\n\nexport const HeartbeatMessageSchema = z.object({\n type: z.literal(\"heartbeat\"),\n});\nexport type HeartbeatMessage = z.infer<typeof HeartbeatMessageSchema>;\n\nexport const CallMessageSchema = z.object({\n type: z.literal(\"call\"),\n id: z.number(),\n name: z.string(),\n args: z.looseObject({}),\n});\nexport type CallMessage = z.infer<typeof CallMessageSchema>;\n\nexport const PresenceMessageSchema = z.object({\n type: z.literal(\"presence\"),\n data: z.looseObject({}),\n});\nexport type PresenceMessage = z.infer<typeof PresenceMessageSchema>;\n\nexport const ClientMessageSchema = z.discriminatedUnion(\"type\", [\n SubscribeMessageSchema,\n UnsubscribeMessageSchema,\n HeartbeatMessageSchema,\n CallMessageSchema,\n PresenceMessageSchema,\n]);\nexport type ClientMessage = z.infer<typeof ClientMessageSchema>;\n\nexport function parseClientMessage(data: unknown): ClientMessage {\n return ClientMessageSchema.parse(data);\n}\n\nexport const ClientMessage = {\n subscribe: (\n id: number,\n name: string,\n args: object,\n ): SubscribeMessage => ({\n type: \"subscribe\",\n id,\n name,\n args: args as Record<string, unknown>,\n }),\n unsubscribe: (id: number): UnsubscribeMessage => ({\n type: \"unsubscribe\",\n id,\n }),\n call: (\n id: number,\n name: string,\n args: object,\n ): CallMessage => ({\n type: \"call\",\n id,\n name,\n args: args as Record<string, unknown>,\n }),\n heartbeat: (): HeartbeatMessage => ({\n type: \"heartbeat\",\n }),\n presence: (data: object): PresenceMessage => ({\n type: \"presence\",\n data: data as Record<string, unknown>,\n }),\n};\n","import { z } from \"zod\";\n\nexport const HeartbeatMessageSchema = z.object({\n type: z.literal(\"heartbeat\"),\n});\nexport type HeartbeatMessage = z.infer<typeof HeartbeatMessageSchema>;\n\nexport const SubscribedSchema = z.object({\n type: z.literal(\"snapshot\"),\n id: z.number(),\n snapshot: z.unknown(),\n});\nexport type SubscribedMessage = z.infer<typeof SubscribedSchema>;\n\nexport const DeltaMessageSchema = z.object({\n type: z.literal(\"delta\"),\n changes: z.record(z.number(), z.unknown()),\n});\nexport type DeltaMessage = z.infer<typeof DeltaMessageSchema>;\n\nexport const ResultMessageSchema = z.object({\n type: z.literal(\"result\"),\n id: z.number(),\n success: z.boolean(),\n value: z.unknown().optional(),\n error: z.string().optional(),\n});\nexport type ResultMessage = z.infer<typeof ResultMessageSchema>;\n\nexport const ServerMessageSchema = z.discriminatedUnion(\"type\", [\n HeartbeatMessageSchema,\n SubscribedSchema,\n DeltaMessageSchema,\n ResultMessageSchema,\n]);\nexport type ServerMessage = z.infer<typeof ServerMessageSchema>;\n\nexport const ServerMessage = {\n heartbeat: (): HeartbeatMessage => ({\n type: \"heartbeat\",\n }),\n subscribed: (id: number, snapshot: unknown): SubscribedMessage => ({\n type: \"snapshot\",\n id,\n snapshot,\n }),\n delta: (changes: Record<string, unknown>): DeltaMessage => ({\n type: \"delta\",\n changes: changes,\n }),\n resultSuccess: (id: number, value: unknown): ResultMessage => ({\n type: \"result\",\n id,\n success: true,\n value,\n }),\n resultError: (id: number, error: string): ResultMessage => ({\n type: \"result\",\n id,\n success: false,\n error,\n }),\n};\n","export class Queue<T> {\n private front: T[] = [];\n private back: T[] = [];\n\n get length(): number {\n return this.front.length + this.back.length;\n }\n\n isEmpty(): boolean {\n return this.front.length === 0 && this.back.length === 0;\n }\n\n push(item: T): void {\n this.front.push(item);\n }\n\n peek(): T | undefined {\n if (this.back.length === 0) {\n if (this.front.length === 0) {\n return undefined;\n }\n return this.front[0];\n }\n return this.back[this.back.length - 1];\n }\n\n pop(): T | undefined {\n if (this.back.length === 0) {\n // Reverse front and swap to back\n this.back = this.front.reverse();\n this.front = [];\n }\n return this.back.pop();\n }\n}\n","import { Queue } from \"./queue.js\";\n\nexport class RateLimiter {\n private readonly timestamps = new Queue<bigint>();\n private readonly maxOccurrences: number;\n private readonly windowNanos: bigint;\n\n constructor(maxOccurrences: number, windowSeconds: number) {\n this.maxOccurrences = maxOccurrences;\n this.windowNanos = BigInt(windowSeconds) * BigInt(1_000_000_000);\n }\n\n trigger(): boolean {\n const now = process.hrtime.bigint();\n\n const cutoff = now - this.windowNanos;\n while (!this.timestamps.isEmpty()) {\n const oldest = this.timestamps.peek();\n if (oldest === undefined || oldest >= cutoff) {\n break;\n }\n this.timestamps.pop();\n }\n\n if (this.timestamps.length >= this.maxOccurrences) {\n return true;\n }\n\n this.timestamps.push(now);\n\n return false;\n }\n}\n","import { parseClientMessage, ClientMessage } from \"../client-message.js\";\nimport { ServerMessage } from \"../server-message.js\";\nimport {\n Source,\n StreamEndpoints,\n MutationEndpoints,\n RPCDefinition,\n} from \"../stream-types.js\";\nimport { RateLimiter } from \"./rate-limiter.js\";\nimport { PresenceHandler } from \"../presence-manager.js\";\nimport { WebSocket, RawData } from \"ws\";\n\nexport class WebSocketClientHandler<Defs extends RPCDefinition, Ctx = void> {\n private readonly ws: WebSocket;\n private readonly context: Ctx;\n private readonly streamEndpoints: StreamEndpoints<Defs[\"streams\"], Ctx>;\n private readonly mutationEndpoints: MutationEndpoints<Defs[\"mutations\"], Ctx>;\n private readonly presenceHandler?: PresenceHandler;\n private currentPresence?: Record<string, unknown>;\n private closed = false;\n private readonly streams = new Map<number, Source<unknown>>();\n private heartbeatTimeout: NodeJS.Timeout | undefined;\n private inactivityTimeout: NodeJS.Timeout | undefined;\n private readonly rateLimiter: RateLimiter;\n\n constructor(\n ws: WebSocket,\n context: Ctx,\n streamEndpoints: StreamEndpoints<Defs[\"streams\"], Ctx>,\n mutationEndpoints: MutationEndpoints<Defs[\"mutations\"], Ctx>,\n presenceHandler?: PresenceHandler,\n ) {\n this.ws = ws;\n this.context = context;\n this.streamEndpoints = streamEndpoints;\n this.mutationEndpoints = mutationEndpoints;\n this.presenceHandler = presenceHandler;\n this.rateLimiter = new RateLimiter(100, 300); // 100 messages over 5 minutes\n\n console.log(\"new client connected\");\n\n // Set up transport handlers\n this.ws.on(\"message\", (data: RawData) =>\n this.handleMessage(data.toString()),\n );\n this.ws.on(\"close\", () => this.handleDisconnect());\n\n this.resetHeartbeat();\n this.resetInactivity();\n }\n\n private resetHeartbeat() {\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n }\n\n this.heartbeatTimeout = setTimeout(() => {\n this.sendMessage(ServerMessage.heartbeat());\n }, 10_000);\n }\n\n private resetInactivity() {\n if (this.inactivityTimeout) {\n clearTimeout(this.inactivityTimeout);\n }\n\n this.inactivityTimeout = setTimeout(() => {\n this.close();\n }, 30_000);\n }\n\n handleMessage(message: string) {\n this.resetInactivity();\n\n // Check rate limit\n if (this.rateLimiter.trigger()) {\n console.log(\"Rate limit exceeded, closing connection\");\n this.close();\n return;\n }\n\n let data: object;\n try {\n data = JSON.parse(message);\n } catch {\n console.error(\"Invalid JSON received:\", message);\n return this.close();\n }\n\n let parsed: ClientMessage;\n try {\n parsed = parseClientMessage(data);\n } catch (err) {\n console.error(\"Invalid client message:\", err);\n return this.close();\n }\n\n this.handleClientMessage(parsed);\n }\n\n async handleClientMessage(message: ClientMessage) {\n switch (message.type) {\n case \"subscribe\": {\n const { id, name, args } = message;\n\n if (!(name in this.streamEndpoints)) {\n console.error(`Unknown stream: ${name}`);\n this.close();\n return;\n }\n\n const endpoint = this.streamEndpoints[name as keyof Defs[\"streams\"]];\n\n try {\n const source = await endpoint(\n args as Defs[\"streams\"][keyof Defs[\"streams\"]][\"args\"],\n this.context,\n );\n this.streams.set(id, source);\n this.sendMessage(ServerMessage.subscribed(id, source.Snapshot));\n console.log(`Client subscribed to \\\"${name}\\\" (${id})`);\n } catch (err) {\n console.error(`Error building stream ${name}:`, err);\n this.close();\n }\n break;\n }\n\n case \"unsubscribe\": {\n const { id } = message;\n this.streams.delete(id);\n console.log(`Client unsubscribed from ${id}`);\n break;\n }\n\n case \"call\": {\n const { id, name, args } = message;\n\n if (!(name in this.mutationEndpoints)) {\n console.error(`Unknown mutation: ${name}`);\n this.close();\n return;\n }\n\n const endpoint =\n this.mutationEndpoints[name as keyof Defs[\"mutations\"]];\n\n endpoint(\n args as Defs[\"mutations\"][keyof Defs[\"mutations\"]][\"args\"],\n this.context,\n )\n .then((result) => {\n if (result.success) {\n this.sendMessage(ServerMessage.resultSuccess(id, result.value));\n console.log(\n `Mutation \\\"${name}\\\" (${id}) completed successfully`,\n );\n } else {\n this.sendMessage(ServerMessage.resultError(id, result.error));\n console.log(\n `Mutation \\\"${name}\\\" (${id}) returned error: ${result.error}`,\n );\n }\n })\n .catch((err) => {\n console.error(\n `Unhandled exception in mutation \\\"${name}\\\" (${id}):`,\n err,\n );\n this.close();\n });\n break;\n }\n\n case \"heartbeat\":\n break;\n\n case \"presence\": {\n if (!this.presenceHandler) {\n console.error(\"Presence not configured\");\n this.close();\n return;\n }\n\n const { data } = message;\n\n if (this.currentPresence !== undefined) {\n this.presenceHandler.update(this.currentPresence, data);\n } else {\n this.presenceHandler.add(data);\n }\n\n this.currentPresence = data;\n break;\n }\n }\n }\n\n handleStep() {\n if (this.closed) return;\n const changes: Record<number, unknown> = {};\n\n for (const [id, source] of this.streams) {\n const change = source.LastChange;\n if (change === null) continue;\n changes[id] = change;\n }\n\n if (Object.keys(changes).length > 0) {\n this.sendMessage(ServerMessage.delta(changes));\n }\n }\n\n sendMessage(message: ServerMessage) {\n this.resetHeartbeat();\n\n if (!this.closed) {\n // Check buffer if available (WebSocket provides this, MessagePort doesn't)\n if (this.ws.bufferedAmount > 100 * 1024) {\n console.log(\"Send buffer exceeded 100KB, closing connection\");\n this.close();\n return;\n }\n\n try {\n this.ws.send(JSON.stringify(message));\n } catch (err) {\n console.error(\"Failed to send message:\", err);\n this.close();\n }\n }\n }\n\n private handleDisconnect() {\n console.log(\"client disconnected\");\n this.close();\n }\n\n close() {\n if (this.closed) return;\n this.closed = true;\n clearTimeout(this.heartbeatTimeout);\n clearTimeout(this.inactivityTimeout);\n\n if (this.presenceHandler && this.currentPresence !== undefined) {\n this.presenceHandler.remove(this.currentPresence);\n }\n\n try {\n this.ws.close();\n } catch {}\n }\n}\n","export default class WeakList<T extends object> implements Iterable<T> {\n private items: WeakRef<T>[] = [];\n\n add(value: T): void {\n this.items.push(new WeakRef(value));\n }\n\n *[Symbol.iterator](): Iterator<T> {\n const newItems: WeakRef<T>[] = [];\n\n for (const ref of this.items) {\n const value = ref.deref();\n if (value !== undefined) {\n yield value;\n newItems.push(ref);\n }\n }\n\n this.items = newItems;\n }\n}\n"],"mappings":"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","names":["import_zod","HeartbeatMessageSchema"]}
@@ -1,4 +1,4 @@
1
- // src/web-socket-server.ts
1
+ // src/websocket/web-socket-server.ts
2
2
  import { parse } from "url";
3
3
  import { WebSocketServer } from "ws";
4
4
 
@@ -92,7 +92,7 @@ var ServerMessage = {
92
92
  })
93
93
  };
94
94
 
95
- // src/queue.ts
95
+ // src/websocket/queue.ts
96
96
  var Queue = class {
97
97
  constructor() {
98
98
  this.front = [];
@@ -125,7 +125,7 @@ var Queue = class {
125
125
  }
126
126
  };
127
127
 
128
- // src/rate-limiter.ts
128
+ // src/websocket/rate-limiter.ts
129
129
  var RateLimiter = class {
130
130
  constructor(maxOccurrences, windowSeconds) {
131
131
  this.timestamps = new Queue();
@@ -150,20 +150,23 @@ var RateLimiter = class {
150
150
  }
151
151
  };
152
152
 
153
- // src/client-handler.ts
154
- var ClientHandler = class {
155
- constructor(transport, context, streamEndpoints, mutationEndpoints, presenceHandler) {
153
+ // src/websocket/web-socket-client-handler.ts
154
+ var WebSocketClientHandler = class {
155
+ constructor(ws, context, streamEndpoints, mutationEndpoints, presenceHandler) {
156
156
  this.closed = false;
157
157
  this.streams = /* @__PURE__ */ new Map();
158
- this.transport = transport;
158
+ this.ws = ws;
159
159
  this.context = context;
160
160
  this.streamEndpoints = streamEndpoints;
161
161
  this.mutationEndpoints = mutationEndpoints;
162
162
  this.presenceHandler = presenceHandler;
163
163
  this.rateLimiter = new RateLimiter(100, 300);
164
164
  console.log("new client connected");
165
- this.transport.onMessage((data) => this.handleMessage(data));
166
- this.transport.onClose(() => this.handleDisconnect());
165
+ this.ws.on(
166
+ "message",
167
+ (data) => this.handleMessage(data.toString())
168
+ );
169
+ this.ws.on("close", () => this.handleDisconnect());
167
170
  this.resetHeartbeat();
168
171
  this.resetInactivity();
169
172
  }
@@ -302,13 +305,13 @@ var ClientHandler = class {
302
305
  sendMessage(message) {
303
306
  this.resetHeartbeat();
304
307
  if (!this.closed) {
305
- if (this.transport.bufferedAmount !== void 0 && this.transport.bufferedAmount > 100 * 1024) {
308
+ if (this.ws.bufferedAmount > 100 * 1024) {
306
309
  console.log("Send buffer exceeded 100KB, closing connection");
307
310
  this.close();
308
311
  return;
309
312
  }
310
313
  try {
311
- this.transport.send(JSON.stringify(message));
314
+ this.ws.send(JSON.stringify(message));
312
315
  } catch (err) {
313
316
  console.error("Failed to send message:", err);
314
317
  this.close();
@@ -328,7 +331,7 @@ var ClientHandler = class {
328
331
  this.presenceHandler.remove(this.currentPresence);
329
332
  }
330
333
  try {
331
- this.transport.close();
334
+ this.ws.close();
332
335
  } catch (e) {
333
336
  }
334
337
  }
@@ -355,39 +358,7 @@ var WeakList = class {
355
358
  }
356
359
  };
357
360
 
358
- // src/node-web-socket-transport.ts
359
- var NodeWebSocketTransport = class {
360
- constructor(ws) {
361
- this.ws = ws;
362
- this.messageHandlerSet = false;
363
- this.closeHandlerSet = false;
364
- }
365
- send(data) {
366
- this.ws.send(data);
367
- }
368
- onMessage(handler) {
369
- if (!this.messageHandlerSet) {
370
- this.ws.on("message", (data) => {
371
- handler(data.toString());
372
- });
373
- this.messageHandlerSet = true;
374
- }
375
- }
376
- onClose(handler) {
377
- if (!this.closeHandlerSet) {
378
- this.ws.on("close", handler);
379
- this.closeHandlerSet = true;
380
- }
381
- }
382
- close() {
383
- this.ws.close();
384
- }
385
- get bufferedAmount() {
386
- return this.ws.bufferedAmount;
387
- }
388
- };
389
-
390
- // src/web-socket-server.ts
361
+ // src/websocket/web-socket-server.ts
391
362
  function setupWebSocketServer(graph, server, streamEndpoints, mutationEndpoints, options) {
392
363
  const { createContext, presenceHandler, path = "/api/ws" } = options;
393
364
  const clients = new WeakList();
@@ -408,9 +379,8 @@ function setupWebSocketServer(graph, server, streamEndpoints, mutationEndpoints,
408
379
  ws.on("message", tempMessageHandler);
409
380
  Promise.resolve(createContext(ws, req)).then((context) => {
410
381
  ws.removeListener("message", tempMessageHandler);
411
- const transport = new NodeWebSocketTransport(ws);
412
- client = new ClientHandler(
413
- transport,
382
+ client = new WebSocketClientHandler(
383
+ ws,
414
384
  context,
415
385
  streamEndpoints,
416
386
  mutationEndpoints,
@@ -441,4 +411,4 @@ function setupWebSocketServer(graph, server, streamEndpoints, mutationEndpoints,
441
411
  export {
442
412
  setupWebSocketServer
443
413
  };
444
- //# sourceMappingURL=web-socket-server.js.map
414
+ //# sourceMappingURL=websocket-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/websocket/web-socket-server.ts","../src/client-message.ts","../src/server-message.ts","../src/websocket/queue.ts","../src/websocket/rate-limiter.ts","../src/websocket/web-socket-client-handler.ts","../src/weak-list.ts"],"sourcesContent":["import { parse } from \"url\";\nimport { Server, IncomingMessage } from \"http\";\nimport { WebSocketServer, WebSocket, RawData } from \"ws\";\nimport { WebSocketClientHandler } from \"./web-socket-client-handler.js\";\nimport WeakList from \"../weak-list.js\";\nimport {\n StreamEndpoints,\n MutationEndpoints,\n RPCDefinition,\n} from \"../stream-types.js\";\nimport { Graph } from \"derivation\";\nimport { PresenceHandler } from \"../presence-manager.js\";\n\nexport type WebSocketServerOptions<Ctx> = {\n createContext: (ws: WebSocket, req: IncomingMessage) => Ctx | Promise<Ctx>;\n presenceHandler?: PresenceHandler;\n path?: string;\n};\n\nexport function setupWebSocketServer<Defs extends RPCDefinition, Ctx = void>(\n graph: Graph,\n server: Server,\n streamEndpoints: StreamEndpoints<Defs[\"streams\"], Ctx>,\n mutationEndpoints: MutationEndpoints<Defs[\"mutations\"], Ctx>,\n options: WebSocketServerOptions<Ctx>,\n) {\n const { createContext, presenceHandler, path = \"/api/ws\" } = options;\n const clients = new WeakList<WebSocketClientHandler<Defs, Ctx>>();\n\n graph.afterStep(() => {\n for (const client of clients) {\n client.handleStep();\n }\n });\n\n const wss = new WebSocketServer({ noServer: true, maxPayload: 100 * 1024 });\n\n // Handle WebSocket connections for reactive streams\n wss.on(\"connection\", (ws, req) => {\n const { pathname } = parse(req.url || \"/\", true);\n if (pathname === path) {\n const messageBuffer: RawData[] = [];\n let client: WebSocketClientHandler<Defs, Ctx> | null = null;\n\n // Set up temporary message handler to buffer messages\n const tempMessageHandler = (msg: RawData) => {\n messageBuffer.push(msg);\n };\n ws.on(\"message\", tempMessageHandler);\n\n // Create context (handle both sync and async)\n Promise.resolve(createContext(ws, req))\n .then((context) => {\n // Remove temporary handler\n ws.removeListener(\"message\", tempMessageHandler);\n\n // Create client handler\n client = new WebSocketClientHandler<Defs, Ctx>(\n ws,\n context,\n streamEndpoints,\n mutationEndpoints,\n presenceHandler,\n );\n clients.add(client);\n\n // Process buffered messages\n for (const msg of messageBuffer) {\n client.handleMessage(msg.toString());\n }\n messageBuffer.length = 0;\n })\n .catch((err) => {\n console.error(\"Error creating context:\", err);\n ws.close();\n });\n }\n });\n\n // Handle HTTP upgrade (for /api/ws)\n server.on(\"upgrade\", (req, socket, head) => {\n const { pathname } = parse(req.url || \"/\", true);\n\n if (pathname === \"/api/ws\") {\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit(\"connection\", ws, req);\n });\n } else {\n socket.destroy();\n }\n });\n}\n","import { z } from \"zod\";\n\nexport const SubscribeMessageSchema = z.object({\n type: z.literal(\"subscribe\"),\n id: z.number(),\n name: z.string(),\n args: z.looseObject({}),\n});\nexport type SubscribeMessage = z.infer<typeof SubscribeMessageSchema>;\n\nexport const UnsubscribeMessageSchema = z.object({\n type: z.literal(\"unsubscribe\"),\n id: z.number(),\n});\nexport type UnsubscribeMessage = z.infer<typeof UnsubscribeMessageSchema>;\n\nexport const HeartbeatMessageSchema = z.object({\n type: z.literal(\"heartbeat\"),\n});\nexport type HeartbeatMessage = z.infer<typeof HeartbeatMessageSchema>;\n\nexport const CallMessageSchema = z.object({\n type: z.literal(\"call\"),\n id: z.number(),\n name: z.string(),\n args: z.looseObject({}),\n});\nexport type CallMessage = z.infer<typeof CallMessageSchema>;\n\nexport const PresenceMessageSchema = z.object({\n type: z.literal(\"presence\"),\n data: z.looseObject({}),\n});\nexport type PresenceMessage = z.infer<typeof PresenceMessageSchema>;\n\nexport const ClientMessageSchema = z.discriminatedUnion(\"type\", [\n SubscribeMessageSchema,\n UnsubscribeMessageSchema,\n HeartbeatMessageSchema,\n CallMessageSchema,\n PresenceMessageSchema,\n]);\nexport type ClientMessage = z.infer<typeof ClientMessageSchema>;\n\nexport function parseClientMessage(data: unknown): ClientMessage {\n return ClientMessageSchema.parse(data);\n}\n\nexport const ClientMessage = {\n subscribe: (\n id: number,\n name: string,\n args: object,\n ): SubscribeMessage => ({\n type: \"subscribe\",\n id,\n name,\n args: args as Record<string, unknown>,\n }),\n unsubscribe: (id: number): UnsubscribeMessage => ({\n type: \"unsubscribe\",\n id,\n }),\n call: (\n id: number,\n name: string,\n args: object,\n ): CallMessage => ({\n type: \"call\",\n id,\n name,\n args: args as Record<string, unknown>,\n }),\n heartbeat: (): HeartbeatMessage => ({\n type: \"heartbeat\",\n }),\n presence: (data: object): PresenceMessage => ({\n type: \"presence\",\n data: data as Record<string, unknown>,\n }),\n};\n","import { z } from \"zod\";\n\nexport const HeartbeatMessageSchema = z.object({\n type: z.literal(\"heartbeat\"),\n});\nexport type HeartbeatMessage = z.infer<typeof HeartbeatMessageSchema>;\n\nexport const SubscribedSchema = z.object({\n type: z.literal(\"snapshot\"),\n id: z.number(),\n snapshot: z.unknown(),\n});\nexport type SubscribedMessage = z.infer<typeof SubscribedSchema>;\n\nexport const DeltaMessageSchema = z.object({\n type: z.literal(\"delta\"),\n changes: z.record(z.number(), z.unknown()),\n});\nexport type DeltaMessage = z.infer<typeof DeltaMessageSchema>;\n\nexport const ResultMessageSchema = z.object({\n type: z.literal(\"result\"),\n id: z.number(),\n success: z.boolean(),\n value: z.unknown().optional(),\n error: z.string().optional(),\n});\nexport type ResultMessage = z.infer<typeof ResultMessageSchema>;\n\nexport const ServerMessageSchema = z.discriminatedUnion(\"type\", [\n HeartbeatMessageSchema,\n SubscribedSchema,\n DeltaMessageSchema,\n ResultMessageSchema,\n]);\nexport type ServerMessage = z.infer<typeof ServerMessageSchema>;\n\nexport const ServerMessage = {\n heartbeat: (): HeartbeatMessage => ({\n type: \"heartbeat\",\n }),\n subscribed: (id: number, snapshot: unknown): SubscribedMessage => ({\n type: \"snapshot\",\n id,\n snapshot,\n }),\n delta: (changes: Record<string, unknown>): DeltaMessage => ({\n type: \"delta\",\n changes: changes,\n }),\n resultSuccess: (id: number, value: unknown): ResultMessage => ({\n type: \"result\",\n id,\n success: true,\n value,\n }),\n resultError: (id: number, error: string): ResultMessage => ({\n type: \"result\",\n id,\n success: false,\n error,\n }),\n};\n","export class Queue<T> {\n private front: T[] = [];\n private back: T[] = [];\n\n get length(): number {\n return this.front.length + this.back.length;\n }\n\n isEmpty(): boolean {\n return this.front.length === 0 && this.back.length === 0;\n }\n\n push(item: T): void {\n this.front.push(item);\n }\n\n peek(): T | undefined {\n if (this.back.length === 0) {\n if (this.front.length === 0) {\n return undefined;\n }\n return this.front[0];\n }\n return this.back[this.back.length - 1];\n }\n\n pop(): T | undefined {\n if (this.back.length === 0) {\n // Reverse front and swap to back\n this.back = this.front.reverse();\n this.front = [];\n }\n return this.back.pop();\n }\n}\n","import { Queue } from \"./queue.js\";\n\nexport class RateLimiter {\n private readonly timestamps = new Queue<bigint>();\n private readonly maxOccurrences: number;\n private readonly windowNanos: bigint;\n\n constructor(maxOccurrences: number, windowSeconds: number) {\n this.maxOccurrences = maxOccurrences;\n this.windowNanos = BigInt(windowSeconds) * BigInt(1_000_000_000);\n }\n\n trigger(): boolean {\n const now = process.hrtime.bigint();\n\n const cutoff = now - this.windowNanos;\n while (!this.timestamps.isEmpty()) {\n const oldest = this.timestamps.peek();\n if (oldest === undefined || oldest >= cutoff) {\n break;\n }\n this.timestamps.pop();\n }\n\n if (this.timestamps.length >= this.maxOccurrences) {\n return true;\n }\n\n this.timestamps.push(now);\n\n return false;\n }\n}\n","import { parseClientMessage, ClientMessage } from \"../client-message.js\";\nimport { ServerMessage } from \"../server-message.js\";\nimport {\n Source,\n StreamEndpoints,\n MutationEndpoints,\n RPCDefinition,\n} from \"../stream-types.js\";\nimport { RateLimiter } from \"./rate-limiter.js\";\nimport { PresenceHandler } from \"../presence-manager.js\";\nimport { WebSocket, RawData } from \"ws\";\n\nexport class WebSocketClientHandler<Defs extends RPCDefinition, Ctx = void> {\n private readonly ws: WebSocket;\n private readonly context: Ctx;\n private readonly streamEndpoints: StreamEndpoints<Defs[\"streams\"], Ctx>;\n private readonly mutationEndpoints: MutationEndpoints<Defs[\"mutations\"], Ctx>;\n private readonly presenceHandler?: PresenceHandler;\n private currentPresence?: Record<string, unknown>;\n private closed = false;\n private readonly streams = new Map<number, Source<unknown>>();\n private heartbeatTimeout: NodeJS.Timeout | undefined;\n private inactivityTimeout: NodeJS.Timeout | undefined;\n private readonly rateLimiter: RateLimiter;\n\n constructor(\n ws: WebSocket,\n context: Ctx,\n streamEndpoints: StreamEndpoints<Defs[\"streams\"], Ctx>,\n mutationEndpoints: MutationEndpoints<Defs[\"mutations\"], Ctx>,\n presenceHandler?: PresenceHandler,\n ) {\n this.ws = ws;\n this.context = context;\n this.streamEndpoints = streamEndpoints;\n this.mutationEndpoints = mutationEndpoints;\n this.presenceHandler = presenceHandler;\n this.rateLimiter = new RateLimiter(100, 300); // 100 messages over 5 minutes\n\n console.log(\"new client connected\");\n\n // Set up transport handlers\n this.ws.on(\"message\", (data: RawData) =>\n this.handleMessage(data.toString()),\n );\n this.ws.on(\"close\", () => this.handleDisconnect());\n\n this.resetHeartbeat();\n this.resetInactivity();\n }\n\n private resetHeartbeat() {\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n }\n\n this.heartbeatTimeout = setTimeout(() => {\n this.sendMessage(ServerMessage.heartbeat());\n }, 10_000);\n }\n\n private resetInactivity() {\n if (this.inactivityTimeout) {\n clearTimeout(this.inactivityTimeout);\n }\n\n this.inactivityTimeout = setTimeout(() => {\n this.close();\n }, 30_000);\n }\n\n handleMessage(message: string) {\n this.resetInactivity();\n\n // Check rate limit\n if (this.rateLimiter.trigger()) {\n console.log(\"Rate limit exceeded, closing connection\");\n this.close();\n return;\n }\n\n let data: object;\n try {\n data = JSON.parse(message);\n } catch {\n console.error(\"Invalid JSON received:\", message);\n return this.close();\n }\n\n let parsed: ClientMessage;\n try {\n parsed = parseClientMessage(data);\n } catch (err) {\n console.error(\"Invalid client message:\", err);\n return this.close();\n }\n\n this.handleClientMessage(parsed);\n }\n\n async handleClientMessage(message: ClientMessage) {\n switch (message.type) {\n case \"subscribe\": {\n const { id, name, args } = message;\n\n if (!(name in this.streamEndpoints)) {\n console.error(`Unknown stream: ${name}`);\n this.close();\n return;\n }\n\n const endpoint = this.streamEndpoints[name as keyof Defs[\"streams\"]];\n\n try {\n const source = await endpoint(\n args as Defs[\"streams\"][keyof Defs[\"streams\"]][\"args\"],\n this.context,\n );\n this.streams.set(id, source);\n this.sendMessage(ServerMessage.subscribed(id, source.Snapshot));\n console.log(`Client subscribed to \\\"${name}\\\" (${id})`);\n } catch (err) {\n console.error(`Error building stream ${name}:`, err);\n this.close();\n }\n break;\n }\n\n case \"unsubscribe\": {\n const { id } = message;\n this.streams.delete(id);\n console.log(`Client unsubscribed from ${id}`);\n break;\n }\n\n case \"call\": {\n const { id, name, args } = message;\n\n if (!(name in this.mutationEndpoints)) {\n console.error(`Unknown mutation: ${name}`);\n this.close();\n return;\n }\n\n const endpoint =\n this.mutationEndpoints[name as keyof Defs[\"mutations\"]];\n\n endpoint(\n args as Defs[\"mutations\"][keyof Defs[\"mutations\"]][\"args\"],\n this.context,\n )\n .then((result) => {\n if (result.success) {\n this.sendMessage(ServerMessage.resultSuccess(id, result.value));\n console.log(\n `Mutation \\\"${name}\\\" (${id}) completed successfully`,\n );\n } else {\n this.sendMessage(ServerMessage.resultError(id, result.error));\n console.log(\n `Mutation \\\"${name}\\\" (${id}) returned error: ${result.error}`,\n );\n }\n })\n .catch((err) => {\n console.error(\n `Unhandled exception in mutation \\\"${name}\\\" (${id}):`,\n err,\n );\n this.close();\n });\n break;\n }\n\n case \"heartbeat\":\n break;\n\n case \"presence\": {\n if (!this.presenceHandler) {\n console.error(\"Presence not configured\");\n this.close();\n return;\n }\n\n const { data } = message;\n\n if (this.currentPresence !== undefined) {\n this.presenceHandler.update(this.currentPresence, data);\n } else {\n this.presenceHandler.add(data);\n }\n\n this.currentPresence = data;\n break;\n }\n }\n }\n\n handleStep() {\n if (this.closed) return;\n const changes: Record<number, unknown> = {};\n\n for (const [id, source] of this.streams) {\n const change = source.LastChange;\n if (change === null) continue;\n changes[id] = change;\n }\n\n if (Object.keys(changes).length > 0) {\n this.sendMessage(ServerMessage.delta(changes));\n }\n }\n\n sendMessage(message: ServerMessage) {\n this.resetHeartbeat();\n\n if (!this.closed) {\n // Check buffer if available (WebSocket provides this, MessagePort doesn't)\n if (this.ws.bufferedAmount > 100 * 1024) {\n console.log(\"Send buffer exceeded 100KB, closing connection\");\n this.close();\n return;\n }\n\n try {\n this.ws.send(JSON.stringify(message));\n } catch (err) {\n console.error(\"Failed to send message:\", err);\n this.close();\n }\n }\n }\n\n private handleDisconnect() {\n console.log(\"client disconnected\");\n this.close();\n }\n\n close() {\n if (this.closed) return;\n this.closed = true;\n clearTimeout(this.heartbeatTimeout);\n clearTimeout(this.inactivityTimeout);\n\n if (this.presenceHandler && this.currentPresence !== undefined) {\n this.presenceHandler.remove(this.currentPresence);\n }\n\n try {\n this.ws.close();\n } catch {}\n }\n}\n","export default class WeakList<T extends object> implements Iterable<T> {\n private items: WeakRef<T>[] = [];\n\n add(value: T): void {\n this.items.push(new WeakRef(value));\n }\n\n *[Symbol.iterator](): Iterator<T> {\n const newItems: WeakRef<T>[] = [];\n\n for (const ref of this.items) {\n const value = ref.deref();\n if (value !== undefined) {\n yield value;\n newItems.push(ref);\n }\n }\n\n this.items = newItems;\n }\n}\n"],"mappings":"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","names":["z","HeartbeatMessageSchema"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@derivation/rpc",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "homepage": "https://github.com/derivationjs/rpc",
5
5
  "repository": {
6
6
  "type": "git",
@@ -19,35 +19,25 @@
19
19
  "import": "./dist/index.js",
20
20
  "require": "./dist/index.cjs"
21
21
  },
22
+ "./websocket/server": {
23
+ "types": "./dist/websocket-server.d.ts",
24
+ "import": "./dist/websocket-server.js",
25
+ "require": "./dist/websocket-server.cjs"
26
+ },
27
+ "./websocket/client": {
28
+ "types": "./dist/websocket-client.d.ts",
29
+ "import": "./dist/websocket-client.js",
30
+ "require": "./dist/websocket-client.cjs"
31
+ },
32
+ "./shared-worker": {
33
+ "types": "./dist/shared-worker.d.ts",
34
+ "import": "./dist/shared-worker.js",
35
+ "require": "./dist/shared-worker.cjs"
36
+ },
22
37
  "./iso": {
23
38
  "types": "./dist/iso.d.ts",
24
39
  "import": "./dist/iso.js",
25
40
  "require": "./dist/iso.cjs"
26
- },
27
- "./worker": {
28
- "types": "./dist/shared-worker-server.d.ts",
29
- "import": "./dist/shared-worker-server.js",
30
- "require": "./dist/shared-worker-server.cjs"
31
- },
32
- "./client": {
33
- "types": "./dist/shared-worker-client.d.ts",
34
- "import": "./dist/shared-worker-client.js",
35
- "require": "./dist/shared-worker-client.cjs"
36
- },
37
- "./transport": {
38
- "types": "./dist/transport.d.ts",
39
- "import": "./dist/transport.js",
40
- "require": "./dist/transport.cjs"
41
- },
42
- "./browser": {
43
- "types": "./dist/web-socket-transport.d.ts",
44
- "import": "./dist/web-socket-transport.js",
45
- "require": "./dist/web-socket-transport.cjs"
46
- },
47
- "./server": {
48
- "types": "./dist/web-socket-server.d.ts",
49
- "import": "./dist/web-socket-server.js",
50
- "require": "./dist/web-socket-server.cjs"
51
41
  }
52
42
  },
53
43
  "files": [
@@ -63,10 +53,10 @@
63
53
  "prepack": "rm -rf dist && npm run lint && npm run typecheck && npm run test"
64
54
  },
65
55
  "dependencies": {
66
- "derivation": "^0.5.1",
67
- "@derivation/composable": "^0.5.1",
56
+ "@derivation/composable": "^0.6.0",
68
57
  "@types/node": "^25.2.3",
69
58
  "@types/ws": "^8.18.1",
59
+ "derivation": "^0.6.0",
70
60
  "immutable": "^5.1.4",
71
61
  "ws": "^8.19.0",
72
62
  "zod": "^4.3.6"