syncora 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,591 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ MemoryStore: () => MemoryStore,
24
+ SyncServer: () => SyncServer,
25
+ SyncoraClient: () => SyncoraClient,
26
+ applyEventToDocuments: () => applyEventToDocuments,
27
+ applyOptimisticDelete: () => applyOptimisticDelete,
28
+ applyOptimisticInsert: () => applyOptimisticInsert,
29
+ applyOptimisticUpdate: () => applyOptimisticUpdate,
30
+ matches: () => matches
31
+ });
32
+ module.exports = __toCommonJS(src_exports);
33
+
34
+ // src/server.ts
35
+ var import_node_crypto2 = require("crypto");
36
+ var import_ws = require("ws");
37
+
38
+ // src/filter.ts
39
+ function matches(doc, filter) {
40
+ if (!filter) return true;
41
+ for (const [key, expected] of Object.entries(filter)) {
42
+ if (key === "$or" && Array.isArray(expected)) {
43
+ if (!expected.some((sub) => matches(doc, sub))) return false;
44
+ continue;
45
+ }
46
+ if (key === "$and" && Array.isArray(expected)) {
47
+ if (!expected.every((sub) => matches(doc, sub))) return false;
48
+ continue;
49
+ }
50
+ const actual = lookupPath(doc, key);
51
+ if (!matchValue(actual, expected)) return false;
52
+ }
53
+ return true;
54
+ }
55
+ function matchValue(actual, expected) {
56
+ if (expected && typeof expected === "object" && !Array.isArray(expected)) {
57
+ const exp = expected;
58
+ if (Object.keys(exp).some((k) => k.startsWith("$"))) {
59
+ for (const [op, val] of Object.entries(exp)) {
60
+ switch (op) {
61
+ case "$eq":
62
+ if (actual !== val) return false;
63
+ break;
64
+ case "$ne":
65
+ if (actual === val) return false;
66
+ break;
67
+ case "$in":
68
+ if (!Array.isArray(val) || !val.includes(actual)) return false;
69
+ break;
70
+ case "$nin":
71
+ if (!Array.isArray(val) || val.includes(actual)) return false;
72
+ break;
73
+ case "$gt":
74
+ if (!(typeof actual === "number" && typeof val === "number" && actual > val)) return false;
75
+ break;
76
+ case "$gte":
77
+ if (!(typeof actual === "number" && typeof val === "number" && actual >= val)) return false;
78
+ break;
79
+ case "$lt":
80
+ if (!(typeof actual === "number" && typeof val === "number" && actual < val)) return false;
81
+ break;
82
+ case "$lte":
83
+ if (!(typeof actual === "number" && typeof val === "number" && actual <= val)) return false;
84
+ break;
85
+ case "$exists":
86
+ if (Boolean(val) !== (actual !== void 0)) return false;
87
+ break;
88
+ default:
89
+ return false;
90
+ }
91
+ }
92
+ return true;
93
+ }
94
+ }
95
+ return actual === expected;
96
+ }
97
+ function lookupPath(source, path) {
98
+ if (!path.includes(".")) return source[path];
99
+ let cur = source;
100
+ for (const part of path.split(".")) {
101
+ if (cur && typeof cur === "object" && part in cur) {
102
+ cur = cur[part];
103
+ } else {
104
+ return void 0;
105
+ }
106
+ }
107
+ return cur;
108
+ }
109
+
110
+ // src/store.ts
111
+ var import_node_crypto = require("crypto");
112
+ var MemoryStore = class {
113
+ collections = /* @__PURE__ */ new Map();
114
+ versions = /* @__PURE__ */ new Map();
115
+ watchers = /* @__PURE__ */ new Set();
116
+ insert(collection, doc) {
117
+ const id = doc._id ?? `doc_${(0, import_node_crypto.randomBytes)(8).toString("hex")}`;
118
+ const map = this.ensureCollection(collection);
119
+ const document = { ...doc, _id: id };
120
+ map.set(id, document);
121
+ const version = this.bumpVersion(collection);
122
+ this.emit({ type: "insert", collection, document, version });
123
+ return document;
124
+ }
125
+ update(collection, id, patch) {
126
+ const map = this.collections.get(collection);
127
+ if (!map) return void 0;
128
+ const existing = map.get(id);
129
+ if (!existing) return void 0;
130
+ const updated = { ...existing, ...patch, _id: id };
131
+ map.set(id, updated);
132
+ const version = this.bumpVersion(collection);
133
+ this.emit({ type: "update", collection, documentId: id, patch, version });
134
+ return updated;
135
+ }
136
+ delete(collection, id) {
137
+ const map = this.collections.get(collection);
138
+ if (!map) return false;
139
+ if (!map.delete(id)) return false;
140
+ const version = this.bumpVersion(collection);
141
+ this.emit({ type: "delete", collection, documentId: id, version });
142
+ return true;
143
+ }
144
+ find(collection, filter) {
145
+ const map = this.collections.get(collection);
146
+ if (!map) return [];
147
+ const out = [];
148
+ for (const doc of map.values()) {
149
+ if (matches(doc, filter)) out.push(doc);
150
+ }
151
+ return out;
152
+ }
153
+ findOne(collection, id) {
154
+ return this.collections.get(collection)?.get(id);
155
+ }
156
+ snapshot(collection, filter) {
157
+ return { documents: this.find(collection, filter), version: this.version(collection) };
158
+ }
159
+ watch(handler) {
160
+ this.watchers.add(handler);
161
+ return () => this.watchers.delete(handler);
162
+ }
163
+ version(collection) {
164
+ return this.versions.get(collection) ?? 0;
165
+ }
166
+ reset() {
167
+ this.collections.clear();
168
+ this.versions.clear();
169
+ }
170
+ ensureCollection(collection) {
171
+ let map = this.collections.get(collection);
172
+ if (!map) {
173
+ map = /* @__PURE__ */ new Map();
174
+ this.collections.set(collection, map);
175
+ }
176
+ return map;
177
+ }
178
+ bumpVersion(collection) {
179
+ const next = this.version(collection) + 1;
180
+ this.versions.set(collection, next);
181
+ return next;
182
+ }
183
+ emit(event) {
184
+ for (const w of this.watchers) {
185
+ try {
186
+ w(event);
187
+ } catch {
188
+ }
189
+ }
190
+ }
191
+ };
192
+
193
+ // src/server.ts
194
+ var SyncServer = class {
195
+ store;
196
+ wss;
197
+ clients = /* @__PURE__ */ new Map();
198
+ unwatch;
199
+ serverVersion = 0;
200
+ constructor(options = {}) {
201
+ this.store = options.store ?? new MemoryStore();
202
+ const wssConfig = options.server ? { server: options.server, path: options.path } : { host: options.host ?? "127.0.0.1", port: options.port ?? 0, path: options.path };
203
+ this.wss = new import_ws.WebSocketServer(wssConfig);
204
+ this.wss.on("connection", (socket, req) => this.handleConnection(socket, req, options.authorize, options.permit));
205
+ this.unwatch = this.store.watch((event) => this.fanoutEvent(event));
206
+ }
207
+ address() {
208
+ const a = this.wss.address();
209
+ if (typeof a === "string" || a === null) return null;
210
+ return { host: a.address, port: a.port };
211
+ }
212
+ async close() {
213
+ this.unwatch();
214
+ for (const session of this.clients.values()) {
215
+ try {
216
+ session.socket.close();
217
+ } catch {
218
+ }
219
+ }
220
+ this.clients.clear();
221
+ return new Promise((resolve) => this.wss.close(() => resolve()));
222
+ }
223
+ attachChangeStream(emitter) {
224
+ const handler = (event) => this.fanoutEvent(event);
225
+ emitter.on("change", handler);
226
+ return () => {
227
+ const off = emitter.off;
228
+ if (typeof off === "function") off.call(emitter, "change", handler);
229
+ };
230
+ }
231
+ async handleConnection(socket, req, authorize, permit) {
232
+ if (authorize) {
233
+ try {
234
+ const ok = await authorize({ headers: req.headers, url: req.url });
235
+ if (!ok) {
236
+ socket.close(4401, "unauthorized");
237
+ return;
238
+ }
239
+ } catch {
240
+ socket.close(4401, "unauthorized");
241
+ return;
242
+ }
243
+ }
244
+ const session = {
245
+ id: `c_${(0, import_node_crypto2.randomBytes)(8).toString("hex")}`,
246
+ socket,
247
+ subscriptions: /* @__PURE__ */ new Map()
248
+ };
249
+ this.clients.set(session.id, session);
250
+ socket.on("close", () => this.clients.delete(session.id));
251
+ socket.on("error", () => {
252
+ });
253
+ socket.on("message", (data) => {
254
+ this.handleMessage(session, data.toString(), permit).catch(() => {
255
+ send(socket, { type: "error", message: "internal error" });
256
+ });
257
+ });
258
+ send(socket, { type: "hello", clientId: session.id, serverVersion: this.serverVersion });
259
+ }
260
+ async handleMessage(session, raw, permit) {
261
+ let message;
262
+ try {
263
+ message = JSON.parse(raw);
264
+ } catch {
265
+ send(session.socket, { type: "error", message: "invalid JSON" });
266
+ return;
267
+ }
268
+ if (permit) {
269
+ try {
270
+ const allowed = await permit(session.id, message);
271
+ if (!allowed) {
272
+ send(session.socket, { type: "error", message: "forbidden" });
273
+ return;
274
+ }
275
+ } catch {
276
+ send(session.socket, { type: "error", message: "permission check failed" });
277
+ return;
278
+ }
279
+ }
280
+ switch (message.type) {
281
+ case "subscribe":
282
+ return this.handleSubscribe(session, message);
283
+ case "unsubscribe":
284
+ session.subscriptions.delete(message.subscriptionId);
285
+ return;
286
+ case "mutation":
287
+ return this.handleMutation(session, message);
288
+ default:
289
+ send(session.socket, { type: "error", message: "unknown message type" });
290
+ }
291
+ }
292
+ handleSubscribe(session, message) {
293
+ session.subscriptions.set(message.subscriptionId, { collection: message.collection, filter: message.filter });
294
+ const snapshot = this.store.snapshot(message.collection, message.filter);
295
+ send(session.socket, {
296
+ type: "event",
297
+ subscriptionId: message.subscriptionId,
298
+ event: { type: "snapshot", collection: message.collection, documents: snapshot.documents, version: snapshot.version }
299
+ });
300
+ }
301
+ handleMutation(session, message) {
302
+ try {
303
+ if (message.op === "insert") {
304
+ if (!message.document) throw new Error("document required");
305
+ this.store.insert(message.collection, message.document);
306
+ } else if (message.op === "update") {
307
+ if (!message.documentId || !message.patch) throw new Error("documentId and patch required");
308
+ const result = this.store.update(message.collection, message.documentId, message.patch);
309
+ if (!result) throw new Error("not found");
310
+ } else if (message.op === "delete") {
311
+ if (!message.documentId) throw new Error("documentId required");
312
+ const ok = this.store.delete(message.collection, message.documentId);
313
+ if (!ok) throw new Error("not found");
314
+ }
315
+ send(session.socket, { type: "ack", mutationId: message.mutationId, ok: true });
316
+ } catch (err) {
317
+ send(session.socket, {
318
+ type: "ack",
319
+ mutationId: message.mutationId,
320
+ ok: false,
321
+ error: err instanceof Error ? err.message : String(err)
322
+ });
323
+ }
324
+ }
325
+ fanoutEvent(event) {
326
+ this.serverVersion = Math.max(this.serverVersion, event.version);
327
+ for (const session of this.clients.values()) {
328
+ for (const [subscriptionId, sub] of session.subscriptions) {
329
+ if (sub.collection !== event.collection) continue;
330
+ if (!eventMatchesFilter(event, sub.filter)) continue;
331
+ send(session.socket, { type: "event", subscriptionId, event });
332
+ }
333
+ }
334
+ }
335
+ };
336
+ function eventMatchesFilter(event, filter) {
337
+ if (!filter) return true;
338
+ if (event.type === "snapshot") return true;
339
+ if (event.type === "delete") return true;
340
+ if (event.type === "insert") return matches(event.document, filter);
341
+ if (event.type === "update") return matches(event.patch, filter);
342
+ return true;
343
+ }
344
+ function send(socket, message) {
345
+ if (socket.readyState !== 1) return;
346
+ try {
347
+ socket.send(JSON.stringify(message));
348
+ } catch {
349
+ }
350
+ }
351
+
352
+ // src/apply.ts
353
+ function applyEventToDocuments(documents, version, event, filter) {
354
+ if (event.type === "snapshot") {
355
+ const next = event.documents.filter((d) => matches(d, filter));
356
+ return { data: next, version: event.version };
357
+ }
358
+ if (event.type === "insert") {
359
+ if (!matches(event.document, filter)) return { data: documents, version: event.version };
360
+ const next = [...documents.filter((d) => d._id !== event.document._id), event.document];
361
+ return { data: next, version: event.version };
362
+ }
363
+ if (event.type === "update") {
364
+ const next = documents.map(
365
+ (d) => d._id === event.documentId ? { ...d, ...event.patch, _id: d._id } : d
366
+ );
367
+ if (filter) {
368
+ const filtered = next.filter((d) => matches(d, filter));
369
+ return { data: filtered, version: event.version };
370
+ }
371
+ return { data: next, version: event.version };
372
+ }
373
+ if (event.type === "delete") {
374
+ return { data: documents.filter((d) => d._id !== event.documentId), version: event.version };
375
+ }
376
+ return { data: documents, version };
377
+ }
378
+ function applyOptimisticInsert(documents, document) {
379
+ return [...documents.filter((d) => d._id !== document._id), document];
380
+ }
381
+ function applyOptimisticUpdate(documents, id, patch) {
382
+ return documents.map((d) => d._id === id ? { ...d, ...patch, _id: id } : d);
383
+ }
384
+ function applyOptimisticDelete(documents, id) {
385
+ return documents.filter((d) => d._id !== id);
386
+ }
387
+
388
+ // src/client.ts
389
+ var SyncoraClient = class {
390
+ url;
391
+ WS;
392
+ socket;
393
+ subscriptions = /* @__PURE__ */ new Map();
394
+ pendingMutations = /* @__PURE__ */ new Map();
395
+ reconnectDelay;
396
+ maxReconnectDelay;
397
+ currentDelay;
398
+ intentionalClose = false;
399
+ clientId;
400
+ outbox = [];
401
+ connectedListeners = /* @__PURE__ */ new Set();
402
+ disconnectedListeners = /* @__PURE__ */ new Set();
403
+ onError;
404
+ constructor(options) {
405
+ this.url = options.url;
406
+ this.WS = options.WebSocket ?? globalThis.WebSocket;
407
+ if (!this.WS) throw new Error("No WebSocket implementation. Pass options.WebSocket explicitly.");
408
+ this.reconnectDelay = options.reconnectDelayMs ?? 500;
409
+ this.maxReconnectDelay = options.maxReconnectDelayMs ?? 15e3;
410
+ this.currentDelay = this.reconnectDelay;
411
+ this.onError = options.onError;
412
+ if (options.onConnect) this.connectedListeners.add(options.onConnect);
413
+ if (options.onDisconnect) this.disconnectedListeners.add(options.onDisconnect);
414
+ this.connect();
415
+ }
416
+ isConnected() {
417
+ return this.socket?.readyState === 1;
418
+ }
419
+ close() {
420
+ this.intentionalClose = true;
421
+ this.socket?.close();
422
+ }
423
+ onConnect(handler) {
424
+ this.connectedListeners.add(handler);
425
+ return () => this.connectedListeners.delete(handler);
426
+ }
427
+ onDisconnect(handler) {
428
+ this.disconnectedListeners.add(handler);
429
+ return () => this.disconnectedListeners.delete(handler);
430
+ }
431
+ subscribe(collection, options = {}) {
432
+ const id = `sub_${cryptoRandom()}`;
433
+ const sub = {
434
+ id,
435
+ collection,
436
+ filter: options.filter,
437
+ data: [],
438
+ version: 0,
439
+ listeners: /* @__PURE__ */ new Set()
440
+ };
441
+ this.subscriptions.set(id, sub);
442
+ this.send({ type: "subscribe", subscriptionId: id, collection, filter: options.filter });
443
+ const api = {
444
+ id,
445
+ collection,
446
+ filter: options.filter,
447
+ get data() {
448
+ return sub.data;
449
+ },
450
+ get version() {
451
+ return sub.version;
452
+ },
453
+ unsubscribe: () => {
454
+ this.subscriptions.delete(id);
455
+ this.send({ type: "unsubscribe", subscriptionId: id });
456
+ },
457
+ onChange: (listener) => {
458
+ const bridge = (state) => {
459
+ listener({ data: state.data, version: state.version });
460
+ };
461
+ sub.listeners.add(bridge);
462
+ bridge({ data: sub.data, version: sub.version });
463
+ return () => sub.listeners.delete(bridge);
464
+ }
465
+ };
466
+ return api;
467
+ }
468
+ async mutate(collection, op, payload = {}) {
469
+ const mutationId = `mut_${cryptoRandom()}`;
470
+ const message = {
471
+ type: "mutation",
472
+ mutationId,
473
+ collection,
474
+ op,
475
+ ...payload
476
+ };
477
+ return new Promise((resolve, reject) => {
478
+ this.pendingMutations.set(mutationId, { resolve, reject });
479
+ this.send(message);
480
+ });
481
+ }
482
+ connect() {
483
+ this.intentionalClose = false;
484
+ let socket;
485
+ try {
486
+ socket = new this.WS(this.url);
487
+ } catch (err) {
488
+ this.onError?.(err);
489
+ this.scheduleReconnect();
490
+ return;
491
+ }
492
+ this.socket = socket;
493
+ socket.addEventListener("open", () => {
494
+ this.currentDelay = this.reconnectDelay;
495
+ for (const msg of this.outbox) {
496
+ try {
497
+ socket.send(JSON.stringify(msg));
498
+ } catch {
499
+ }
500
+ }
501
+ this.outbox = [];
502
+ for (const sub of this.subscriptions.values()) {
503
+ try {
504
+ socket.send(JSON.stringify({ type: "subscribe", subscriptionId: sub.id, collection: sub.collection, filter: sub.filter }));
505
+ } catch {
506
+ }
507
+ }
508
+ });
509
+ socket.addEventListener("message", (event) => {
510
+ let parsed;
511
+ try {
512
+ parsed = JSON.parse(typeof event.data === "string" ? event.data : String(event.data));
513
+ } catch {
514
+ return;
515
+ }
516
+ this.handleMessage(parsed);
517
+ });
518
+ socket.addEventListener("error", (err) => this.onError?.(err));
519
+ socket.addEventListener("close", () => {
520
+ for (const listener of this.disconnectedListeners) listener();
521
+ if (!this.intentionalClose) this.scheduleReconnect();
522
+ });
523
+ }
524
+ scheduleReconnect() {
525
+ const delay = this.currentDelay;
526
+ this.currentDelay = Math.min(this.maxReconnectDelay, this.currentDelay * 2);
527
+ setTimeout(() => this.connect(), delay);
528
+ }
529
+ handleMessage(message) {
530
+ switch (message.type) {
531
+ case "hello":
532
+ this.clientId = message.clientId;
533
+ for (const listener of this.connectedListeners) listener(message.clientId);
534
+ break;
535
+ case "event": {
536
+ const sub = this.subscriptions.get(message.subscriptionId);
537
+ if (!sub) return;
538
+ applyEventToSubscription(sub, message.event);
539
+ for (const l of sub.listeners) l({ data: sub.data, version: sub.version });
540
+ break;
541
+ }
542
+ case "ack": {
543
+ const pending = this.pendingMutations.get(message.mutationId);
544
+ if (!pending) return;
545
+ this.pendingMutations.delete(message.mutationId);
546
+ if (message.ok) pending.resolve();
547
+ else pending.reject(new Error(message.error ?? "mutation rejected"));
548
+ break;
549
+ }
550
+ case "error":
551
+ this.onError?.(new Error(message.message));
552
+ break;
553
+ }
554
+ }
555
+ send(message) {
556
+ if (this.socket && this.socket.readyState === 1) {
557
+ try {
558
+ this.socket.send(JSON.stringify(message));
559
+ return;
560
+ } catch {
561
+ }
562
+ }
563
+ this.outbox.push(message);
564
+ }
565
+ };
566
+ function applyEventToSubscription(sub, event) {
567
+ const { data, version } = applyEventToDocuments(sub.data, sub.version, event, sub.filter);
568
+ sub.data = data;
569
+ sub.version = version;
570
+ }
571
+ function cryptoRandom() {
572
+ const bytes = new Uint8Array(8);
573
+ if (typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.getRandomValues === "function") {
574
+ globalThis.crypto.getRandomValues(bytes);
575
+ } else {
576
+ for (let i = 0; i < 8; i++) bytes[i] = Math.floor(Math.random() * 256);
577
+ }
578
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
579
+ }
580
+ // Annotate the CommonJS export names for ESM import in node:
581
+ 0 && (module.exports = {
582
+ MemoryStore,
583
+ SyncServer,
584
+ SyncoraClient,
585
+ applyEventToDocuments,
586
+ applyOptimisticDelete,
587
+ applyOptimisticInsert,
588
+ applyOptimisticUpdate,
589
+ matches
590
+ });
591
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/server.ts","../src/filter.ts","../src/store.ts","../src/apply.ts","../src/client.ts"],"sourcesContent":["export { SyncServer, type SyncServerOptions } from \"./server.js\";\nexport { MemoryStore, type SyncStore } from \"./store.js\";\nexport {\n SyncoraClient,\n type SyncoraClientOptions,\n type Subscription,\n} from \"./client.js\";\nexport {\n applyEventToDocuments,\n applyOptimisticInsert,\n applyOptimisticUpdate,\n applyOptimisticDelete,\n} from \"./apply.js\";\nexport { matches } from \"./filter.js\";\nexport type {\n SyncDocument,\n ChangeEvent,\n ClientMessage,\n ServerMessage,\n Filter,\n StoreSnapshot,\n} from \"./types.js\";\n","import { randomBytes } from \"node:crypto\";\nimport { WebSocketServer, type WebSocket } from \"ws\";\nimport type { Server as HttpServer } from \"node:http\";\nimport { matches } from \"./filter.js\";\nimport { MemoryStore, type SyncStore } from \"./store.js\";\nimport type {\n ChangeEvent,\n ClientMessage,\n Filter,\n ServerMessage,\n SyncDocument,\n} from \"./types.js\";\n\nexport interface SyncServerOptions {\n store?: SyncStore;\n server?: HttpServer;\n port?: number;\n host?: string;\n path?: string;\n authorize?: (handshake: { headers: Record<string, string | string[] | undefined>; url?: string }) => boolean | Promise<boolean>;\n permit?: (clientId: string, message: ClientMessage) => boolean | Promise<boolean>;\n}\n\ninterface ClientSession {\n id: string;\n socket: WebSocket;\n subscriptions: Map<string, { collection: string; filter?: Filter }>;\n}\n\nexport class SyncServer {\n readonly store: SyncStore;\n private wss: WebSocketServer;\n private clients = new Map<string, ClientSession>();\n private unwatch: () => void;\n private serverVersion = 0;\n\n constructor(options: SyncServerOptions = {}) {\n this.store = options.store ?? new MemoryStore();\n const wssConfig: ConstructorParameters<typeof WebSocketServer>[0] = options.server\n ? { server: options.server, path: options.path }\n : { host: options.host ?? \"127.0.0.1\", port: options.port ?? 0, path: options.path };\n this.wss = new WebSocketServer(wssConfig);\n this.wss.on(\"connection\", (socket, req) => this.handleConnection(socket, req, options.authorize, options.permit));\n this.unwatch = this.store.watch((event) => this.fanoutEvent(event));\n }\n\n address(): { host: string; port: number } | null {\n const a = this.wss.address();\n if (typeof a === \"string\" || a === null) return null;\n return { host: a.address, port: a.port };\n }\n\n async close(): Promise<void> {\n this.unwatch();\n for (const session of this.clients.values()) {\n try { session.socket.close(); } catch { /* ignore */ }\n }\n this.clients.clear();\n return new Promise((resolve) => this.wss.close(() => resolve()));\n }\n\n attachChangeStream(emitter: { on: (event: \"change\", handler: (event: ChangeEvent) => void) => unknown }): () => void {\n const handler = (event: ChangeEvent) => this.fanoutEvent(event);\n emitter.on(\"change\", handler);\n return () => {\n const off = (emitter as unknown as { off?: (event: string, handler: unknown) => unknown }).off;\n if (typeof off === \"function\") off.call(emitter, \"change\", handler);\n };\n }\n\n private async handleConnection(\n socket: WebSocket,\n req: { headers: Record<string, string | string[] | undefined>; url?: string },\n authorize?: SyncServerOptions[\"authorize\"],\n permit?: SyncServerOptions[\"permit\"],\n ): Promise<void> {\n if (authorize) {\n try {\n const ok = await authorize({ headers: req.headers, url: req.url });\n if (!ok) {\n socket.close(4401, \"unauthorized\");\n return;\n }\n } catch {\n socket.close(4401, \"unauthorized\");\n return;\n }\n }\n const session: ClientSession = {\n id: `c_${randomBytes(8).toString(\"hex\")}`,\n socket,\n subscriptions: new Map(),\n };\n this.clients.set(session.id, session);\n\n socket.on(\"close\", () => this.clients.delete(session.id));\n socket.on(\"error\", () => { /* socket lifecycle handled by ws */ });\n socket.on(\"message\", (data) => {\n this.handleMessage(session, data.toString(), permit).catch(() => {\n send(socket, { type: \"error\", message: \"internal error\" });\n });\n });\n\n send(socket, { type: \"hello\", clientId: session.id, serverVersion: this.serverVersion });\n }\n\n private async handleMessage(\n session: ClientSession,\n raw: string,\n permit?: SyncServerOptions[\"permit\"],\n ): Promise<void> {\n let message: ClientMessage;\n try { message = JSON.parse(raw) as ClientMessage; } catch {\n send(session.socket, { type: \"error\", message: \"invalid JSON\" });\n return;\n }\n if (permit) {\n try {\n const allowed = await permit(session.id, message);\n if (!allowed) {\n send(session.socket, { type: \"error\", message: \"forbidden\" });\n return;\n }\n } catch {\n send(session.socket, { type: \"error\", message: \"permission check failed\" });\n return;\n }\n }\n switch (message.type) {\n case \"subscribe\":\n return this.handleSubscribe(session, message);\n case \"unsubscribe\":\n session.subscriptions.delete(message.subscriptionId);\n return;\n case \"mutation\":\n return this.handleMutation(session, message);\n default:\n send(session.socket, { type: \"error\", message: \"unknown message type\" });\n }\n }\n\n private handleSubscribe(session: ClientSession, message: Extract<ClientMessage, { type: \"subscribe\" }>): void {\n session.subscriptions.set(message.subscriptionId, { collection: message.collection, filter: message.filter });\n const snapshot = this.store.snapshot(message.collection, message.filter);\n send(session.socket, {\n type: \"event\",\n subscriptionId: message.subscriptionId,\n event: { type: \"snapshot\", collection: message.collection, documents: snapshot.documents, version: snapshot.version },\n });\n }\n\n private handleMutation(session: ClientSession, message: Extract<ClientMessage, { type: \"mutation\" }>): void {\n try {\n if (message.op === \"insert\") {\n if (!message.document) throw new Error(\"document required\");\n this.store.insert(message.collection, message.document);\n } else if (message.op === \"update\") {\n if (!message.documentId || !message.patch) throw new Error(\"documentId and patch required\");\n const result = this.store.update(message.collection, message.documentId, message.patch);\n if (!result) throw new Error(\"not found\");\n } else if (message.op === \"delete\") {\n if (!message.documentId) throw new Error(\"documentId required\");\n const ok = this.store.delete(message.collection, message.documentId);\n if (!ok) throw new Error(\"not found\");\n }\n send(session.socket, { type: \"ack\", mutationId: message.mutationId, ok: true });\n } catch (err) {\n send(session.socket, {\n type: \"ack\",\n mutationId: message.mutationId,\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n private fanoutEvent(event: ChangeEvent): void {\n this.serverVersion = Math.max(this.serverVersion, event.version);\n for (const session of this.clients.values()) {\n for (const [subscriptionId, sub] of session.subscriptions) {\n if (sub.collection !== event.collection) continue;\n if (!eventMatchesFilter(event, sub.filter)) continue;\n send(session.socket, { type: \"event\", subscriptionId, event });\n }\n }\n }\n}\n\nfunction eventMatchesFilter(event: ChangeEvent, filter: Filter | undefined): boolean {\n if (!filter) return true;\n if (event.type === \"snapshot\") return true;\n if (event.type === \"delete\") return true;\n if (event.type === \"insert\") return matches(event.document, filter);\n if (event.type === \"update\") return matches(event.patch as SyncDocument, filter);\n return true;\n}\n\nfunction send(socket: WebSocket, message: ServerMessage): void {\n if (socket.readyState !== 1) return;\n try {\n socket.send(JSON.stringify(message));\n } catch {\n /* socket may have closed mid-send */\n }\n}\n","import type { Filter, SyncDocument } from \"./types.js\";\n\nexport function matches(doc: SyncDocument, filter: Filter | undefined): boolean {\n if (!filter) return true;\n for (const [key, expected] of Object.entries(filter)) {\n if (key === \"$or\" && Array.isArray(expected)) {\n if (!expected.some((sub) => matches(doc, sub as Filter))) return false;\n continue;\n }\n if (key === \"$and\" && Array.isArray(expected)) {\n if (!expected.every((sub) => matches(doc, sub as Filter))) return false;\n continue;\n }\n const actual = lookupPath(doc as Record<string, unknown>, key);\n if (!matchValue(actual, expected)) return false;\n }\n return true;\n}\n\nfunction matchValue(actual: unknown, expected: unknown): boolean {\n if (expected && typeof expected === \"object\" && !Array.isArray(expected)) {\n const exp = expected as Record<string, unknown>;\n if (Object.keys(exp).some((k) => k.startsWith(\"$\"))) {\n for (const [op, val] of Object.entries(exp)) {\n switch (op) {\n case \"$eq\": if (actual !== val) return false; break;\n case \"$ne\": if (actual === val) return false; break;\n case \"$in\":\n if (!Array.isArray(val) || !val.includes(actual)) return false;\n break;\n case \"$nin\":\n if (!Array.isArray(val) || val.includes(actual)) return false;\n break;\n case \"$gt\": if (!(typeof actual === \"number\" && typeof val === \"number\" && actual > val)) return false; break;\n case \"$gte\": if (!(typeof actual === \"number\" && typeof val === \"number\" && actual >= val)) return false; break;\n case \"$lt\": if (!(typeof actual === \"number\" && typeof val === \"number\" && actual < val)) return false; break;\n case \"$lte\": if (!(typeof actual === \"number\" && typeof val === \"number\" && actual <= val)) return false; break;\n case \"$exists\":\n if (Boolean(val) !== (actual !== undefined)) return false;\n break;\n default:\n return false;\n }\n }\n return true;\n }\n }\n return actual === expected;\n}\n\nfunction lookupPath(source: Record<string, unknown>, path: string): unknown {\n if (!path.includes(\".\")) return source[path];\n let cur: unknown = source;\n for (const part of path.split(\".\")) {\n if (cur && typeof cur === \"object\" && part in (cur as Record<string, unknown>)) {\n cur = (cur as Record<string, unknown>)[part];\n } else {\n return undefined;\n }\n }\n return cur;\n}\n","import { randomBytes } from \"node:crypto\";\nimport { matches } from \"./filter.js\";\nimport type { ChangeEvent, Filter, StoreSnapshot, SyncDocument } from \"./types.js\";\n\nexport interface SyncStore {\n insert<T extends SyncDocument>(collection: string, document: Omit<T, \"_id\"> & { _id?: string }): T;\n update<T extends SyncDocument>(collection: string, id: string, patch: Partial<T>): T | undefined;\n delete(collection: string, id: string): boolean;\n find<T extends SyncDocument>(collection: string, filter?: Filter): T[];\n findOne<T extends SyncDocument>(collection: string, id: string): T | undefined;\n snapshot<T extends SyncDocument>(collection: string, filter?: Filter): StoreSnapshot<T>;\n watch(handler: (event: ChangeEvent) => void): () => void;\n version(collection: string): number;\n reset(): void;\n}\n\nexport class MemoryStore implements SyncStore {\n private collections = new Map<string, Map<string, SyncDocument>>();\n private versions = new Map<string, number>();\n private watchers = new Set<(e: ChangeEvent) => void>();\n\n insert<T extends SyncDocument>(collection: string, doc: Omit<T, \"_id\"> & { _id?: string }): T {\n const id = doc._id ?? `doc_${randomBytes(8).toString(\"hex\")}`;\n const map = this.ensureCollection(collection);\n const document = { ...doc, _id: id } as unknown as T;\n map.set(id, document);\n const version = this.bumpVersion(collection);\n this.emit({ type: \"insert\", collection, document, version });\n return document;\n }\n\n update<T extends SyncDocument>(collection: string, id: string, patch: Partial<T>): T | undefined {\n const map = this.collections.get(collection);\n if (!map) return undefined;\n const existing = map.get(id);\n if (!existing) return undefined;\n const updated = { ...existing, ...patch, _id: id } as T;\n map.set(id, updated);\n const version = this.bumpVersion(collection);\n this.emit({ type: \"update\", collection, documentId: id, patch, version });\n return updated;\n }\n\n delete(collection: string, id: string): boolean {\n const map = this.collections.get(collection);\n if (!map) return false;\n if (!map.delete(id)) return false;\n const version = this.bumpVersion(collection);\n this.emit({ type: \"delete\", collection, documentId: id, version });\n return true;\n }\n\n find<T extends SyncDocument>(collection: string, filter?: Filter): T[] {\n const map = this.collections.get(collection);\n if (!map) return [];\n const out: T[] = [];\n for (const doc of map.values()) {\n if (matches(doc, filter)) out.push(doc as T);\n }\n return out;\n }\n\n findOne<T extends SyncDocument>(collection: string, id: string): T | undefined {\n return this.collections.get(collection)?.get(id) as T | undefined;\n }\n\n snapshot<T extends SyncDocument>(collection: string, filter?: Filter): StoreSnapshot<T> {\n return { documents: this.find<T>(collection, filter), version: this.version(collection) };\n }\n\n watch(handler: (event: ChangeEvent) => void): () => void {\n this.watchers.add(handler);\n return () => this.watchers.delete(handler);\n }\n\n version(collection: string): number {\n return this.versions.get(collection) ?? 0;\n }\n\n reset(): void {\n this.collections.clear();\n this.versions.clear();\n }\n\n private ensureCollection(collection: string): Map<string, SyncDocument> {\n let map = this.collections.get(collection);\n if (!map) {\n map = new Map();\n this.collections.set(collection, map);\n }\n return map;\n }\n\n private bumpVersion(collection: string): number {\n const next = this.version(collection) + 1;\n this.versions.set(collection, next);\n return next;\n }\n\n private emit(event: ChangeEvent): void {\n for (const w of this.watchers) {\n try { w(event); } catch { /* swallow individual subscriber errors */ }\n }\n }\n}\n","import { matches } from \"./filter.js\";\nimport type { ChangeEvent, Filter, SyncDocument } from \"./types.js\";\n\nexport function applyEventToDocuments<T extends SyncDocument>(\n documents: T[],\n version: number,\n event: ChangeEvent,\n filter?: Filter,\n): { data: T[]; version: number } {\n if (event.type === \"snapshot\") {\n const next = (event.documents as T[]).filter((d) => matches(d, filter));\n return { data: next, version: event.version };\n }\n if (event.type === \"insert\") {\n if (!matches(event.document, filter)) return { data: documents, version: event.version };\n const next = [...documents.filter((d) => d._id !== event.document._id), event.document as T];\n return { data: next, version: event.version };\n }\n if (event.type === \"update\") {\n const next = documents.map((d) =>\n d._id === event.documentId ? ({ ...d, ...event.patch, _id: d._id } as T) : d,\n );\n if (filter) {\n const filtered = next.filter((d) => matches(d, filter));\n return { data: filtered, version: event.version };\n }\n return { data: next, version: event.version };\n }\n if (event.type === \"delete\") {\n return { data: documents.filter((d) => d._id !== event.documentId), version: event.version };\n }\n return { data: documents, version };\n}\n\nexport function applyOptimisticInsert<T extends SyncDocument>(documents: T[], document: T): T[] {\n return [...documents.filter((d) => d._id !== document._id), document];\n}\n\nexport function applyOptimisticUpdate<T extends SyncDocument>(\n documents: T[],\n id: string,\n patch: Partial<T>,\n): T[] {\n return documents.map((d) => (d._id === id ? ({ ...d, ...patch, _id: id } as T) : d));\n}\n\nexport function applyOptimisticDelete<T extends SyncDocument>(documents: T[], id: string): T[] {\n return documents.filter((d) => d._id !== id);\n}\n","import { applyEventToDocuments } from \"./apply.js\";\nimport type {\n ChangeEvent,\n ClientMessage,\n Filter,\n ServerMessage,\n SyncDocument,\n} from \"./types.js\";\n\ntype WSLike = {\n send(data: string): void;\n close(): void;\n addEventListener(event: \"open\", cb: () => void): void;\n addEventListener(event: \"close\", cb: () => void): void;\n addEventListener(event: \"error\", cb: (event: unknown) => void): void;\n addEventListener(event: \"message\", cb: (event: { data: unknown }) => void): void;\n readyState?: number;\n};\n\ntype WSConstructor = new (url: string) => WSLike;\n\nexport interface SyncoraClientOptions {\n url: string;\n WebSocket?: WSConstructor;\n reconnectDelayMs?: number;\n maxReconnectDelayMs?: number;\n onConnect?: (clientId: string) => void;\n onDisconnect?: () => void;\n onError?: (error: unknown) => void;\n}\n\nexport interface Subscription<T extends SyncDocument = SyncDocument> {\n id: string;\n collection: string;\n filter?: Filter;\n data: T[];\n version: number;\n unsubscribe(): void;\n onChange(listener: (state: { data: T[]; version: number }) => void): () => void;\n}\n\ntype Listener<T extends SyncDocument> = (state: { data: T[]; version: number }) => void;\n\n/** Stored subscriptions are document-shaped only; `subscribe<T>` bridges at the API boundary. */\ninterface InternalSubscription {\n id: string;\n collection: string;\n filter?: Filter;\n data: SyncDocument[];\n version: number;\n listeners: Set<(state: { data: SyncDocument[]; version: number }) => void>;\n}\n\ntype PendingMutation = { resolve: () => void; reject: (err: Error) => void };\n\nexport class SyncoraClient {\n private url: string;\n private WS: WSConstructor;\n private socket?: WSLike;\n private subscriptions = new Map<string, InternalSubscription>();\n private pendingMutations = new Map<string, PendingMutation>();\n private reconnectDelay: number;\n private maxReconnectDelay: number;\n private currentDelay: number;\n private intentionalClose = false;\n private clientId?: string;\n private outbox: ClientMessage[] = [];\n private connectedListeners = new Set<(clientId: string) => void>();\n private disconnectedListeners = new Set<() => void>();\n private onError?: (error: unknown) => void;\n\n constructor(options: SyncoraClientOptions) {\n this.url = options.url;\n this.WS = options.WebSocket ?? (globalThis as { WebSocket?: WSConstructor }).WebSocket as WSConstructor;\n if (!this.WS) throw new Error(\"No WebSocket implementation. Pass options.WebSocket explicitly.\");\n this.reconnectDelay = options.reconnectDelayMs ?? 500;\n this.maxReconnectDelay = options.maxReconnectDelayMs ?? 15_000;\n this.currentDelay = this.reconnectDelay;\n this.onError = options.onError;\n if (options.onConnect) this.connectedListeners.add(options.onConnect);\n if (options.onDisconnect) this.disconnectedListeners.add(options.onDisconnect);\n this.connect();\n }\n\n isConnected(): boolean {\n return this.socket?.readyState === 1;\n }\n\n close(): void {\n this.intentionalClose = true;\n this.socket?.close();\n }\n\n onConnect(handler: (clientId: string) => void): () => void {\n this.connectedListeners.add(handler);\n return () => this.connectedListeners.delete(handler);\n }\n\n onDisconnect(handler: () => void): () => void {\n this.disconnectedListeners.add(handler);\n return () => this.disconnectedListeners.delete(handler);\n }\n\n subscribe<T extends SyncDocument = SyncDocument>(collection: string, options: { filter?: Filter } = {}): Subscription<T> {\n const id = `sub_${cryptoRandom()}`;\n const sub: InternalSubscription = {\n id,\n collection,\n filter: options.filter,\n data: [],\n version: 0,\n listeners: new Set(),\n };\n this.subscriptions.set(id, sub);\n this.send({ type: \"subscribe\", subscriptionId: id, collection, filter: options.filter });\n const api: Subscription<T> = {\n id,\n collection,\n filter: options.filter,\n get data() { return sub.data as T[]; },\n get version() { return sub.version; },\n unsubscribe: () => {\n this.subscriptions.delete(id);\n this.send({ type: \"unsubscribe\", subscriptionId: id });\n },\n onChange: (listener: Listener<T>) => {\n const bridge = (state: { data: SyncDocument[]; version: number }) => {\n listener({ data: state.data as T[], version: state.version });\n };\n sub.listeners.add(bridge);\n bridge({ data: sub.data, version: sub.version });\n return () => sub.listeners.delete(bridge);\n },\n };\n return api;\n }\n\n async mutate(\n collection: string,\n op: \"insert\" | \"update\" | \"delete\",\n payload: { document?: SyncDocument; documentId?: string; patch?: Partial<SyncDocument> } = {},\n ): Promise<void> {\n const mutationId = `mut_${cryptoRandom()}`;\n const message: ClientMessage = {\n type: \"mutation\",\n mutationId,\n collection,\n op,\n ...payload,\n };\n return new Promise<void>((resolve, reject) => {\n this.pendingMutations.set(mutationId, { resolve, reject });\n this.send(message);\n });\n }\n\n private connect(): void {\n this.intentionalClose = false;\n let socket: WSLike;\n try {\n socket = new this.WS(this.url);\n } catch (err) {\n this.onError?.(err);\n this.scheduleReconnect();\n return;\n }\n this.socket = socket;\n socket.addEventListener(\"open\", () => {\n this.currentDelay = this.reconnectDelay;\n for (const msg of this.outbox) {\n try { socket.send(JSON.stringify(msg)); } catch { /* drop */ }\n }\n this.outbox = [];\n for (const sub of this.subscriptions.values()) {\n try {\n socket.send(JSON.stringify({ type: \"subscribe\", subscriptionId: sub.id, collection: sub.collection, filter: sub.filter } satisfies ClientMessage));\n } catch { /* drop */ }\n }\n });\n socket.addEventListener(\"message\", (event) => {\n let parsed: ServerMessage;\n try {\n parsed = JSON.parse(typeof event.data === \"string\" ? event.data : String(event.data)) as ServerMessage;\n } catch {\n return;\n }\n this.handleMessage(parsed);\n });\n socket.addEventListener(\"error\", (err) => this.onError?.(err));\n socket.addEventListener(\"close\", () => {\n for (const listener of this.disconnectedListeners) listener();\n if (!this.intentionalClose) this.scheduleReconnect();\n });\n }\n\n private scheduleReconnect(): void {\n const delay = this.currentDelay;\n this.currentDelay = Math.min(this.maxReconnectDelay, this.currentDelay * 2);\n setTimeout(() => this.connect(), delay);\n }\n\n private handleMessage(message: ServerMessage): void {\n switch (message.type) {\n case \"hello\":\n this.clientId = message.clientId;\n for (const listener of this.connectedListeners) listener(message.clientId);\n break;\n case \"event\": {\n const sub = this.subscriptions.get(message.subscriptionId);\n if (!sub) return;\n applyEventToSubscription(sub, message.event);\n for (const l of sub.listeners) l({ data: sub.data, version: sub.version });\n break;\n }\n case \"ack\": {\n const pending = this.pendingMutations.get(message.mutationId);\n if (!pending) return;\n this.pendingMutations.delete(message.mutationId);\n if (message.ok) pending.resolve();\n else pending.reject(new Error(message.error ?? \"mutation rejected\"));\n break;\n }\n case \"error\":\n this.onError?.(new Error(message.message));\n break;\n }\n }\n\n private send(message: ClientMessage): void {\n if (this.socket && this.socket.readyState === 1) {\n try {\n this.socket.send(JSON.stringify(message));\n return;\n } catch { /* fall through to outbox */ }\n }\n this.outbox.push(message);\n }\n}\n\nfunction applyEventToSubscription(sub: InternalSubscription, event: ChangeEvent): void {\n const { data, version } = applyEventToDocuments<SyncDocument>(sub.data, sub.version, event, sub.filter);\n sub.data = data;\n sub.version = version;\n}\n\nfunction cryptoRandom(): string {\n const bytes = new Uint8Array(8);\n if (typeof globalThis.crypto !== \"undefined\" && typeof globalThis.crypto.getRandomValues === \"function\") {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 8; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n"],"mappings":"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","names":["import_node_crypto"]}