@fieldnotes/sync-server 0.17.1 → 0.18.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/README.md +2 -2
- package/dist/index.cjs +142 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -20
- package/dist/index.d.ts +45 -20
- package/dist/index.js +150 -40
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -184,13 +184,13 @@ authorize(ctx) => boolean | Promise<boolean>
|
|
|
184
184
|
userId?: string; // the connection's authenticated user (from authenticate)
|
|
185
185
|
role?: string; // the connection's role (from authenticate)
|
|
186
186
|
room: string;
|
|
187
|
-
op:
|
|
187
|
+
op: WireSyncOp; // the incoming upsert / remove / clear
|
|
188
188
|
currentElement?: OwnedElement; // the STORED element, if this id already exists
|
|
189
189
|
}
|
|
190
190
|
```
|
|
191
191
|
|
|
192
192
|
`currentElement` is the element currently in room state for an `upsert`/`remove` of an
|
|
193
|
-
**existing** id (typed `OwnedElement =
|
|
193
|
+
**existing** id (typed `OwnedElement = WireSyncElement`), and
|
|
194
194
|
`undefined` for a new/absent id.
|
|
195
195
|
|
|
196
196
|
**Ownership is server-stamped and un-forgeable.** A new element's `ownerId` is set to the
|
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
30
30
|
|
|
31
31
|
// src/sync-hub.ts
|
|
32
32
|
var import_sync2 = require("@fieldnotes/sync");
|
|
33
|
+
var import_core = require("@fieldnotes/core");
|
|
33
34
|
|
|
34
35
|
// src/memory-hub-backend.ts
|
|
35
36
|
var import_sync = require("@fieldnotes/sync");
|
|
@@ -98,8 +99,10 @@ var ServerPluginRegistry = class {
|
|
|
98
99
|
byName = /* @__PURE__ */ new Map();
|
|
99
100
|
legacyOwners = /* @__PURE__ */ new Map();
|
|
100
101
|
extensions = /* @__PURE__ */ new Map();
|
|
102
|
+
definitions;
|
|
101
103
|
constructor(plugins) {
|
|
102
104
|
for (const plugin of plugins) this.register(plugin);
|
|
105
|
+
this.definitions = new Map([...this.extensions].map(([name, entry]) => [name, entry.kind]));
|
|
103
106
|
}
|
|
104
107
|
register(plugin) {
|
|
105
108
|
if (this.byName.has(plugin.name))
|
|
@@ -131,6 +134,12 @@ var ServerPluginRegistry = class {
|
|
|
131
134
|
extension(extensionKind) {
|
|
132
135
|
return this.extensions.get(extensionKind);
|
|
133
136
|
}
|
|
137
|
+
get extensionKinds() {
|
|
138
|
+
return [...this.extensions.keys()];
|
|
139
|
+
}
|
|
140
|
+
get extensionDefinitions() {
|
|
141
|
+
return this.definitions;
|
|
142
|
+
}
|
|
134
143
|
};
|
|
135
144
|
|
|
136
145
|
// src/resource-limits.ts
|
|
@@ -193,7 +202,7 @@ function generateInstanceId() {
|
|
|
193
202
|
function isFanoutOp(op) {
|
|
194
203
|
if (typeof op !== "object" || op === null) return false;
|
|
195
204
|
const o = op;
|
|
196
|
-
if (o.kind === "upsert") return (0, import_sync2.
|
|
205
|
+
if (o.kind === "upsert") return (0, import_sync2.isValidWireElement)(o.element);
|
|
197
206
|
if (o.kind === "remove") return typeof o.id === "string";
|
|
198
207
|
return o.kind === "clear";
|
|
199
208
|
}
|
|
@@ -223,6 +232,9 @@ function layerRecordToOp(record) {
|
|
|
223
232
|
editor: record.editor
|
|
224
233
|
} : { kind: "layer-remove", id: record.id, version: record.version, editor: record.editor };
|
|
225
234
|
}
|
|
235
|
+
function capabilityProfile(capabilities) {
|
|
236
|
+
return JSON.stringify([capabilities.elementEnvelope, capabilities.extensionKinds]);
|
|
237
|
+
}
|
|
226
238
|
function isPresenceOp(op) {
|
|
227
239
|
if (typeof op !== "object" || op === null) return false;
|
|
228
240
|
const k = op.kind;
|
|
@@ -242,6 +254,8 @@ var SyncHub = class {
|
|
|
242
254
|
authorize;
|
|
243
255
|
authorizeLayer;
|
|
244
256
|
pluginRegistry;
|
|
257
|
+
elementRegistry;
|
|
258
|
+
peerCapabilities = /* @__PURE__ */ new Map();
|
|
245
259
|
canRead;
|
|
246
260
|
memoryLayers = /* @__PURE__ */ new Map();
|
|
247
261
|
maxJsonDepth;
|
|
@@ -260,6 +274,7 @@ var SyncHub = class {
|
|
|
260
274
|
constructor(options = {}) {
|
|
261
275
|
this.backend = options.backend ?? new MemoryHubBackend();
|
|
262
276
|
this.pluginRegistry = new ServerPluginRegistry(options.plugins ?? []);
|
|
277
|
+
this.elementRegistry = options.elementRegistry ?? (0, import_core.getDefaultElementRegistry)();
|
|
263
278
|
this.instanceId = options.instanceId ?? generateInstanceId();
|
|
264
279
|
this.fanout = options.fanout ?? new InMemoryHubFanout();
|
|
265
280
|
this.authorize = options.authorize;
|
|
@@ -287,6 +302,7 @@ var SyncHub = class {
|
|
|
287
302
|
const conn = this.conns.get(connId);
|
|
288
303
|
if (!conn) return;
|
|
289
304
|
this.conns.delete(connId);
|
|
305
|
+
this.peerCapabilities.delete(connId);
|
|
290
306
|
const room = conn.room;
|
|
291
307
|
const hadPresence = this.presenceConnections.delete(connId);
|
|
292
308
|
this.clearPresenceLanes(connId);
|
|
@@ -320,6 +336,14 @@ var SyncHub = class {
|
|
|
320
336
|
if (!hasJsonDepthAtMost(message, this.maxJsonDepth)) return Promise.resolve();
|
|
321
337
|
const env = (0, import_sync2.parseEnvelope)(message);
|
|
322
338
|
if (!env) return Promise.resolve();
|
|
339
|
+
if (env.op.kind === "capabilities") {
|
|
340
|
+
this.peerCapabilities.set(conn.id, env.op.capabilities);
|
|
341
|
+
this.sendToConnection(conn, HUB_FROM, {
|
|
342
|
+
kind: "capabilities",
|
|
343
|
+
capabilities: (0, import_sync2.createCurrentCapabilities)(this.pluginRegistry.extensionKinds)
|
|
344
|
+
});
|
|
345
|
+
return Promise.resolve();
|
|
346
|
+
}
|
|
323
347
|
if (env.op.kind === "presence") {
|
|
324
348
|
this.schedulePresence(conn, env.op.data);
|
|
325
349
|
return Promise.resolve();
|
|
@@ -335,9 +359,14 @@ var SyncHub = class {
|
|
|
335
359
|
return operation;
|
|
336
360
|
}
|
|
337
361
|
async process(conn, env) {
|
|
338
|
-
|
|
362
|
+
let op = env.op;
|
|
363
|
+
if (op.kind === "upsert") {
|
|
364
|
+
const element = this.normalizeElement(op.element);
|
|
365
|
+
if (!element) return;
|
|
366
|
+
op = { ...op, element };
|
|
367
|
+
}
|
|
339
368
|
if (op.kind === "request-snapshot") {
|
|
340
|
-
const all = await this.backend.snapshot(conn.room);
|
|
369
|
+
const all = this.normalizeElements(await this.backend.snapshot(conn.room));
|
|
341
370
|
const elements = this.canRead ? all.filter((el) => this.mayRead(conn, el.audience)) : all;
|
|
342
371
|
const layers = await this.getLayerRecords(conn.room);
|
|
343
372
|
const snapshotOp = {
|
|
@@ -358,7 +387,7 @@ var SyncHub = class {
|
|
|
358
387
|
else extensions[plugin.name] = snapshot;
|
|
359
388
|
}
|
|
360
389
|
if (Object.keys(extensions).length > 0) snapshotOp["extensions"] = extensions;
|
|
361
|
-
|
|
390
|
+
this.sendToConnection(conn, HUB_FROM, snapshotOp);
|
|
362
391
|
} else if (op.kind === "layer-upsert" || op.kind === "layer-remove") {
|
|
363
392
|
await this.processLayerOp(conn, op);
|
|
364
393
|
} else if (op.kind === "extension") {
|
|
@@ -376,7 +405,8 @@ var SyncHub = class {
|
|
|
376
405
|
} else if (op.kind === "upsert" || op.kind === "remove" || op.kind === "clear") {
|
|
377
406
|
const id = op.kind === "upsert" ? op.element.id : op.kind === "remove" ? op.id : void 0;
|
|
378
407
|
const needCurrent = (this.authorize || this.canRead) && id !== void 0;
|
|
379
|
-
const
|
|
408
|
+
const storedCurrent = needCurrent ? await this.backend.get(conn.room, id) : void 0;
|
|
409
|
+
const current = storedCurrent ? this.normalizeElement(storedCurrent) ?? void 0 : void 0;
|
|
380
410
|
let outboundOp = op;
|
|
381
411
|
if (this.authorize) {
|
|
382
412
|
const allowed = await this.authorize({
|
|
@@ -400,7 +430,7 @@ var SyncHub = class {
|
|
|
400
430
|
const prevAudience = current?.audience;
|
|
401
431
|
const result = await this.runCorePlugins(conn, outboundOp);
|
|
402
432
|
for (const correction of result.corrections) {
|
|
403
|
-
|
|
433
|
+
this.sendToConnection(conn, HUB_FROM, correction);
|
|
404
434
|
}
|
|
405
435
|
const accepted = result.accepted;
|
|
406
436
|
if (accepted && (accepted.kind === "upsert" || accepted.kind === "remove" || accepted.kind === "clear")) {
|
|
@@ -456,7 +486,7 @@ var SyncHub = class {
|
|
|
456
486
|
}
|
|
457
487
|
async deliverPluginResult(conn, result) {
|
|
458
488
|
for (const correction of result.corrections) {
|
|
459
|
-
|
|
489
|
+
this.sendToConnection(conn, HUB_FROM, correction);
|
|
460
490
|
}
|
|
461
491
|
if (result.accepted) await this.publishPluginOp(conn, result.accepted, result.locality);
|
|
462
492
|
for (const broadcast of result.broadcast ?? []) {
|
|
@@ -469,7 +499,7 @@ var SyncHub = class {
|
|
|
469
499
|
JSON.stringify({ o: this.instanceId, room: conn.room, from: conn.id, op })
|
|
470
500
|
);
|
|
471
501
|
}
|
|
472
|
-
this.
|
|
502
|
+
this.relayOpToRoom(conn.room, conn.id, conn.id, op);
|
|
473
503
|
}
|
|
474
504
|
/**
|
|
475
505
|
* Applies a layer-definition edit on the room's serial queue. Convergence is
|
|
@@ -491,19 +521,19 @@ var SyncHub = class {
|
|
|
491
521
|
});
|
|
492
522
|
if (!allowed) {
|
|
493
523
|
const correction = current ?? { id: record.id, version: record.version, editor: HUB_FROM };
|
|
494
|
-
|
|
524
|
+
this.sendToConnection(conn, HUB_FROM, layerRecordToOp(correction));
|
|
495
525
|
return;
|
|
496
526
|
}
|
|
497
527
|
}
|
|
498
528
|
if (current && !(0, import_sync2.isNewerLayerRecord)(record, current)) {
|
|
499
|
-
|
|
529
|
+
this.sendToConnection(conn, HUB_FROM, layerRecordToOp(current));
|
|
500
530
|
return;
|
|
501
531
|
}
|
|
502
532
|
await this.applyLayerRecord(conn.room, record);
|
|
503
533
|
await this.fanout.publish(
|
|
504
534
|
JSON.stringify({ o: this.instanceId, room: conn.room, from: conn.id, op })
|
|
505
535
|
);
|
|
506
|
-
this.
|
|
536
|
+
this.relayOpToRoom(conn.room, conn.id, conn.id, op);
|
|
507
537
|
}
|
|
508
538
|
layerBackend() {
|
|
509
539
|
const { layerRecords, getLayerRecord, applyLayerRecord } = this.backend;
|
|
@@ -564,6 +594,86 @@ var SyncHub = class {
|
|
|
564
594
|
}
|
|
565
595
|
return sent;
|
|
566
596
|
}
|
|
597
|
+
/**
|
|
598
|
+
* Translates `op` for the peer and sends it. Returns false when the op is
|
|
599
|
+
* lossy for this peer (no legacy encoding) or the socket throws; neither
|
|
600
|
+
* may reject the room operation that produced it.
|
|
601
|
+
*/
|
|
602
|
+
sendToConnection(conn, from, op, encoded) {
|
|
603
|
+
const capabilities = this.peerCapabilities.get(conn.id) ?? (0, import_sync2.createLegacyCapabilities)();
|
|
604
|
+
const profile = encoded ? capabilityProfile(capabilities) : void 0;
|
|
605
|
+
let message = profile === void 0 ? void 0 : encoded?.get(profile);
|
|
606
|
+
if (message === void 0) {
|
|
607
|
+
message = this.encodeForPeer(from, op, capabilities);
|
|
608
|
+
if (profile !== void 0) encoded?.set(profile, message);
|
|
609
|
+
}
|
|
610
|
+
if (message === null) return false;
|
|
611
|
+
try {
|
|
612
|
+
conn.send(message);
|
|
613
|
+
return true;
|
|
614
|
+
} catch {
|
|
615
|
+
return false;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
/** Returns the wire frame for `op` translated for `capabilities`, or null when lossy. */
|
|
619
|
+
encodeForPeer(from, op, capabilities) {
|
|
620
|
+
try {
|
|
621
|
+
const translated = (0, import_sync2.translateOpForPeer)(
|
|
622
|
+
op,
|
|
623
|
+
capabilities,
|
|
624
|
+
this.elementRegistry,
|
|
625
|
+
this.pluginRegistry.extensionDefinitions
|
|
626
|
+
);
|
|
627
|
+
return JSON.stringify({ from, op: translated });
|
|
628
|
+
} catch {
|
|
629
|
+
return null;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Normalize registered legacy wire elements before authorization, storage,
|
|
634
|
+
* and relay. A legacy type this hub has no adapter for is forwarded and
|
|
635
|
+
* stored verbatim — the hub is a relay, and the peers decide whether they
|
|
636
|
+
* understand it — so a hub deployed without domain adapters never erases
|
|
637
|
+
* the room's existing elements. Only a malformed registered element is dropped.
|
|
638
|
+
*/
|
|
639
|
+
normalizeElement(element) {
|
|
640
|
+
if ((0, import_sync2.isValidElement)(element)) return element;
|
|
641
|
+
const adapter = this.elementRegistry.getAdapterByLegacyType(element.type);
|
|
642
|
+
if (!adapter) return element;
|
|
643
|
+
try {
|
|
644
|
+
const raw = Object.fromEntries(Object.entries(element));
|
|
645
|
+
const envelope = adapter.decodeLegacy(raw);
|
|
646
|
+
if (!adapter.validateEnvelope(envelope)) return null;
|
|
647
|
+
return {
|
|
648
|
+
...envelope,
|
|
649
|
+
...typeof raw["audience"] === "string" ? { audience: raw["audience"] } : {},
|
|
650
|
+
...typeof raw["ownerId"] === "string" ? { ownerId: raw["ownerId"] } : {}
|
|
651
|
+
};
|
|
652
|
+
} catch {
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
normalizeElements(elements) {
|
|
657
|
+
const normalized = [];
|
|
658
|
+
for (const element of elements) {
|
|
659
|
+
const runtime = this.normalizeElement(element);
|
|
660
|
+
if (runtime) normalized.push(runtime);
|
|
661
|
+
}
|
|
662
|
+
return normalized;
|
|
663
|
+
}
|
|
664
|
+
relayOpToRoom(room, excludeId, from, op) {
|
|
665
|
+
const members = this.rooms.get(room);
|
|
666
|
+
if (!members) return 0;
|
|
667
|
+
let sent = 0;
|
|
668
|
+
const encoded = /* @__PURE__ */ new Map();
|
|
669
|
+
for (const connectionId of members) {
|
|
670
|
+
if (connectionId === excludeId) continue;
|
|
671
|
+
const conn = this.conns.get(connectionId);
|
|
672
|
+
if (!conn) continue;
|
|
673
|
+
if (this.sendToConnection(conn, from, op, encoded)) sent += 1;
|
|
674
|
+
}
|
|
675
|
+
return sent;
|
|
676
|
+
}
|
|
567
677
|
broadcastClientPresence(conn, data) {
|
|
568
678
|
this.presenceConnections.add(conn.id);
|
|
569
679
|
const message = JSON.stringify({ from: conn.id, op: { kind: "presence", data } });
|
|
@@ -645,41 +755,33 @@ var SyncHub = class {
|
|
|
645
755
|
deliverToRoom(room, excludeId, from, op, prevAudience, prevExisted) {
|
|
646
756
|
const members = this.rooms.get(room);
|
|
647
757
|
if (!members) return;
|
|
648
|
-
const
|
|
649
|
-
try {
|
|
650
|
-
conn.send(msg);
|
|
651
|
-
} catch {
|
|
652
|
-
}
|
|
653
|
-
};
|
|
758
|
+
const encoded = /* @__PURE__ */ new Map();
|
|
654
759
|
if (op.kind === "upsert") {
|
|
655
760
|
const audience = op.element.audience;
|
|
656
|
-
const
|
|
657
|
-
const
|
|
658
|
-
from: HUB_FROM,
|
|
659
|
-
op: { kind: "remove", id: op.element.id }
|
|
660
|
-
});
|
|
761
|
+
const removeOp = { kind: "remove", id: op.element.id };
|
|
762
|
+
const encodedRemove = /* @__PURE__ */ new Map();
|
|
661
763
|
for (const cid of members) {
|
|
662
764
|
if (cid === excludeId) continue;
|
|
663
765
|
const conn = this.conns.get(cid);
|
|
664
766
|
if (!conn) continue;
|
|
665
|
-
if (this.mayRead(conn, audience))
|
|
666
|
-
else if (prevExisted && this.mayRead(conn, prevAudience))
|
|
767
|
+
if (this.mayRead(conn, audience)) this.sendToConnection(conn, from, op, encoded);
|
|
768
|
+
else if (prevExisted && this.mayRead(conn, prevAudience)) {
|
|
769
|
+
this.sendToConnection(conn, HUB_FROM, removeOp, encodedRemove);
|
|
770
|
+
}
|
|
667
771
|
}
|
|
668
772
|
} else if (op.kind === "remove") {
|
|
669
|
-
const removeMsg = JSON.stringify({ from, op });
|
|
670
773
|
for (const cid of members) {
|
|
671
774
|
if (cid === excludeId) continue;
|
|
672
775
|
const conn = this.conns.get(cid);
|
|
673
776
|
if (!conn) continue;
|
|
674
777
|
const wasVisible = !this.canRead || prevExisted && this.mayRead(conn, prevAudience);
|
|
675
|
-
if (wasVisible)
|
|
778
|
+
if (wasVisible) this.sendToConnection(conn, from, op, encoded);
|
|
676
779
|
}
|
|
677
780
|
} else if (op.kind === "clear") {
|
|
678
|
-
const clearMsg = JSON.stringify({ from, op });
|
|
679
781
|
for (const cid of members) {
|
|
680
782
|
if (cid === excludeId) continue;
|
|
681
783
|
const conn = this.conns.get(cid);
|
|
682
|
-
if (conn)
|
|
784
|
+
if (conn) this.sendToConnection(conn, from, op, encoded);
|
|
683
785
|
}
|
|
684
786
|
}
|
|
685
787
|
}
|
|
@@ -690,11 +792,11 @@ var SyncHub = class {
|
|
|
690
792
|
} else if (op.kind === "remove") {
|
|
691
793
|
correction = current ? this.mayRead(conn, current.audience) ? { kind: "upsert", element: current } : { kind: "remove", id: current.id } : void 0;
|
|
692
794
|
} else if (op.kind === "clear") {
|
|
693
|
-
const all = await this.backend.snapshot(conn.room);
|
|
795
|
+
const all = this.normalizeElements(await this.backend.snapshot(conn.room));
|
|
694
796
|
const elements = this.canRead ? all.filter((el) => this.mayRead(conn, el.audience)) : all;
|
|
695
797
|
correction = { kind: "snapshot", to: from, elements };
|
|
696
798
|
}
|
|
697
|
-
if (correction)
|
|
799
|
+
if (correction) this.sendToConnection(conn, HUB_FROM, correction);
|
|
698
800
|
}
|
|
699
801
|
onFanout(payload) {
|
|
700
802
|
let env;
|
|
@@ -714,7 +816,7 @@ var SyncHub = class {
|
|
|
714
816
|
if (isLayerOp(op)) {
|
|
715
817
|
void this.applyFanoutLayerOp(env.room, op).catch(() => {
|
|
716
818
|
});
|
|
717
|
-
this.
|
|
819
|
+
this.relayOpToRoom(env.room, void 0, env.from, op);
|
|
718
820
|
return;
|
|
719
821
|
}
|
|
720
822
|
const plugin = typeof op === "object" && op !== null && op.kind === "extension" ? this.pluginRegistry.extension(op.extensionKind ?? "")?.plugin : typeof op === "object" && op !== null && typeof op.kind === "string" ? this.pluginRegistry.ownerOf(op.kind) : void 0;
|
|
@@ -729,11 +831,7 @@ var SyncHub = class {
|
|
|
729
831
|
};
|
|
730
832
|
const accepted = plugin.applyFanout ? await plugin.applyFanout(op, context) : op;
|
|
731
833
|
if (accepted) {
|
|
732
|
-
this.
|
|
733
|
-
env.room,
|
|
734
|
-
void 0,
|
|
735
|
-
JSON.stringify({ from: env.from, op: accepted })
|
|
736
|
-
);
|
|
834
|
+
this.relayOpToRoom(env.room, void 0, env.from, accepted);
|
|
737
835
|
}
|
|
738
836
|
});
|
|
739
837
|
this.roomQueues.set(
|
|
@@ -744,9 +842,14 @@ var SyncHub = class {
|
|
|
744
842
|
return;
|
|
745
843
|
}
|
|
746
844
|
if (!isFanoutOp(op)) return;
|
|
845
|
+
const runtimeOp = op.kind === "upsert" ? (() => {
|
|
846
|
+
const element = this.normalizeElement(op.element);
|
|
847
|
+
return element ? { ...op, element } : null;
|
|
848
|
+
})() : op;
|
|
849
|
+
if (!runtimeOp) return;
|
|
747
850
|
const prevAudience = typeof env.prev === "string" ? env.prev : void 0;
|
|
748
851
|
const prevExisted = env.existed === true;
|
|
749
|
-
this.deliverToRoom(env.room, void 0, env.from,
|
|
852
|
+
this.deliverToRoom(env.room, void 0, env.from, runtimeOp, prevAudience, prevExisted);
|
|
750
853
|
}
|
|
751
854
|
async applyFanoutLayerOp(room, op) {
|
|
752
855
|
const record = layerOpToRecord(op);
|
|
@@ -848,7 +951,8 @@ function createSyncServer(options = {}) {
|
|
|
848
951
|
canRead: options.canRead,
|
|
849
952
|
maxJsonDepth: options.maxJsonDepth ?? DEFAULT_MAX_JSON_DEPTH,
|
|
850
953
|
presenceThrottleMs: options.presenceThrottleMs ?? DEFAULT_PRESENCE_THROTTLE_MS,
|
|
851
|
-
maxPresenceLanes: options.maxPresenceLanes
|
|
954
|
+
maxPresenceLanes: options.maxPresenceLanes,
|
|
955
|
+
elementRegistry: options.elementRegistry
|
|
852
956
|
});
|
|
853
957
|
const maxMessageBytes = options.maxMessageBytes ?? DEFAULT_MAX_MESSAGE_BYTES;
|
|
854
958
|
const wss = options.server ? new import_ws.WebSocketServer({ server: options.server, maxPayload: maxMessageBytes }) : new import_ws.WebSocketServer({ port: options.port ?? 0, maxPayload: maxMessageBytes });
|