statewire 0.18.1 → 0.18.2
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/client/session.d.ts +1 -1
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/session.js +48 -188
- package/dist/client/session.js.map +1 -1
- package/dist/host/http.d.ts.map +1 -1
- package/dist/host/http.js +2 -3
- package/dist/host/http.js.map +1 -1
- package/dist/host/socket.d.ts +4 -5
- package/dist/host/socket.d.ts.map +1 -1
- package/dist/host/socket.js +33 -44
- package/dist/host/socket.js.map +1 -1
- package/dist/host-internal.d.ts +0 -4
- package/dist/host-internal.d.ts.map +1 -1
- package/dist/host.d.ts +1 -1
- package/dist/statewire.d.ts +1 -11
- package/dist/statewire.d.ts.map +1 -1
- package/dist/statewire.js.map +1 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +6 -55
- package/dist/storage.js.map +1 -1
- package/dist/transports/sse.d.ts +1 -1
- package/dist/transports/sse.js.map +1 -1
- package/dist/transports/testing.js +2 -1
- package/dist/transports/testing.js.map +1 -1
- package/package.json +1 -1
- package/src/client/session.ts +67 -211
- package/src/host/http.ts +2 -9
- package/src/host/socket.ts +38 -46
- package/src/host-internal.ts +0 -4
- package/src/host.ts +1 -1
- package/src/statewire.ts +1 -8
- package/src/storage.ts +8 -92
- package/src/transports/sse.ts +1 -1
- package/src/transports/testing.ts +2 -1
package/dist/host/socket.d.ts
CHANGED
|
@@ -31,10 +31,7 @@ type Admission = {
|
|
|
31
31
|
type ClientRec = {
|
|
32
32
|
id: string;
|
|
33
33
|
lastSeq: number;
|
|
34
|
-
ctxSeq: number;
|
|
35
34
|
touched: number;
|
|
36
|
-
context: Record<string, unknown> | null;
|
|
37
|
-
contextDocuments: StatewireDocuments.State;
|
|
38
35
|
results: Map<number, {
|
|
39
36
|
ts: number;
|
|
40
37
|
cmd: StatewireCmd;
|
|
@@ -53,6 +50,9 @@ type Conn = {
|
|
|
53
50
|
lease: string | null;
|
|
54
51
|
/** The awaited `authorize` return captured at this attach's authorization. */
|
|
55
52
|
auth: unknown;
|
|
53
|
+
ctxSeq: number;
|
|
54
|
+
context: Record<string, unknown> | null;
|
|
55
|
+
contextDocuments: StatewireDocuments.State;
|
|
56
56
|
};
|
|
57
57
|
type PendingConn = {
|
|
58
58
|
socket: StatewireHostInternal.Socket;
|
|
@@ -128,9 +128,8 @@ type FrameAdmission = {
|
|
|
128
128
|
};
|
|
129
129
|
};
|
|
130
130
|
};
|
|
131
|
-
declare const admitFrame: (h: SocketHostState,
|
|
131
|
+
declare const admitFrame: (h: SocketHostState, conn: Conn, frame: ParsedFrame) => FrameAdmission;
|
|
132
132
|
type Registration = {
|
|
133
|
-
rec: ClientRec;
|
|
134
133
|
conn: Conn;
|
|
135
134
|
connection: StatewireHostInternal.SocketConnection;
|
|
136
135
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket.d.ts","names":[],"sources":["../../src/host/socket.ts"],"mappings":";;;;;;;;;;;cAiCa,cAAY;cACZ;;;cAKA,aAAc,YAAY;cAoC1B;KAGR;EACH;EACA,OAAO;EACP;EACA,OAAO,kBAAkB;;KAGtB;EACH;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA;EACA;EACA
|
|
1
|
+
{"version":3,"file":"socket.d.ts","names":[],"sources":["../../src/host/socket.ts"],"mappings":";;;;;;;;;;;cAiCa,cAAY;cACZ;;;cAKA,aAAc,YAAY;cAoC1B;KAGR;EACH;EACA,OAAO;EACP;EACA,OAAO,kBAAkB;;KAGtB;EACH;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA;EACA;EACA,SAAS;IAAc;IAAY,KAAK;;EACxC,UAAU,YAAY;;EAEtB;;KAKU;EACV,WAAW,kBAAkB;EAC7B;EACA,QAAQ,sBAAsB;EAC9B;EACA;EACA;EACA;;EAEA;EACA;EACA,SAAS;EACT,kBAAkB,mBAAmB;;KAGlC;EACH,QAAQ,sBAAsB;EAC9B;EACA;EACA;EACA,OAAO,kBAAkB;EACzB,YAAY,sBAAsB;;KAc/B;EAAiB;EAAa;;KAC9B;EACH;EACA;EACA;EACA;EACA;;KAGU;EACV,KAAK;EACL,KAAK;;cA0BM,kBAAmB,mBAAiB;cAoDpC,aAAc,gBAAc;KAiG7B;EACV,UAAU,kBAAkB;EAC5B,aAAa,kBAAkB;EAC/B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,WAAW,sBAAsB;EACjC,SAAS,YAAY;EACrB,OAAO,IAAI;EACX,cAAc,IAAI;EAClB,YAAY;EACZ,gBAAgB;EAChB,aAAa,YAAY;EACzB;EACA,UAAU,cAAc;EACxB;EACA;EACA,gBAAgB,kBAAkB;EAClC,WAAW,cAAc;EACzB,cAAc;EACd,SAAS;EACT,aAAa,sBAAsB;EACnC;EACA,UACE,kBACA,QAAQ,sBAAsB,QAC9B,UAAU,sBAAsB,yBAC7B,sBAAsB;EAC3B,SAAS,KAAK,cAAc;EAC5B,SAAS,SAAS,YAAY,QAAQ;EACtC,SAAS,SAAS,YAAY,QAAQ;;cA+C3B,YACX,GAAG,iBACH,MAAM,MACN,eACA;cAgBW,SAAU,GAAG,iBAAiB,MAAM,MAAM;cAU1C,oBAAqB,GAAG;cAkCxB,QAAS,GAAG,iBAAiB,MAAM,cAAc;KAmRlD;EACN;;EAEA;EACA;IACE;MAAO;MAAa;MAAgB;;;;cAI/B,aACX,GAAG,iBACH,MAAM,MACN,OAAO,gBACN;KAsbS;EACV,MAAM;EACN,YAAY,sBAAsB;;cAGvB,WACX,GAAG,iBACH,kBACA,QAAQ,sBAAsB,QAC9B,oBACA,gBACA,YAAW,kBAAkB,cAI5B;;;;;;;;;cAyQU,sBACX,WAAW,gBAAgB,YAC3B,UAAU,sBAAsB,mBAChC,cAAc,sBAAsB,0BACnC,sBAAsB"}
|
package/dist/host/socket.js
CHANGED
|
@@ -301,10 +301,7 @@ const notifyClientRecords = (h) => {
|
|
|
301
301
|
h.persistence?.onClientRecordsChange?.([...h.clients.values()].map((rec) => ({
|
|
302
302
|
id: rec.id,
|
|
303
303
|
lastSeq: admittedThrough(rec),
|
|
304
|
-
ctxSeq: rec.ctxSeq,
|
|
305
304
|
touched: rec.touched,
|
|
306
|
-
context: rec.context,
|
|
307
|
-
contextDocuments: [...rec.contextDocuments.documents],
|
|
308
305
|
results: [...rec.results].map(([seq, entry]) => ({
|
|
309
306
|
seq,
|
|
310
307
|
ts: entry.ts,
|
|
@@ -356,11 +353,11 @@ const settleCmd = (h, rec, adm, cmd) => {
|
|
|
356
353
|
notifyClientRecords(h);
|
|
357
354
|
};
|
|
358
355
|
const settleWire = (h, rec, adm, outcome) => settleCmd(h, rec, adm, cmdOf(adm, outcome));
|
|
359
|
-
const callerOf = (h, rec,
|
|
356
|
+
const callerOf = (h, rec, conn) => ({
|
|
360
357
|
clientId: rec.id,
|
|
361
|
-
auth,
|
|
358
|
+
auth: conn.auth,
|
|
362
359
|
get context() {
|
|
363
|
-
return
|
|
360
|
+
return conn.context;
|
|
364
361
|
},
|
|
365
362
|
get isConnected() {
|
|
366
363
|
if (h.clients.get(rec.id) !== rec) return false;
|
|
@@ -374,7 +371,7 @@ const rejectStatement = (h, rec, adm, message) => settleCmd(h, rec, adm, {
|
|
|
374
371
|
code: "invalid-params",
|
|
375
372
|
message
|
|
376
373
|
});
|
|
377
|
-
const admitCmd = (h, rec,
|
|
374
|
+
const admitCmd = (h, rec, conn, statement) => {
|
|
378
375
|
const adm = {
|
|
379
376
|
seq: statement.seq,
|
|
380
377
|
method: statement.method,
|
|
@@ -384,7 +381,7 @@ const admitCmd = (h, rec, statement, auth, selection) => {
|
|
|
384
381
|
};
|
|
385
382
|
rec.inflight.set(statement.seq, adm);
|
|
386
383
|
notifyClientRecords(h);
|
|
387
|
-
if (statement.protocol !== h.protocol.name || !selection.protocols.some((p) => p.name === statement.protocol)) {
|
|
384
|
+
if (statement.protocol !== h.protocol.name || !conn.selection.protocols.some((p) => p.name === statement.protocol)) {
|
|
388
385
|
settleCmd(h, rec, adm, {
|
|
389
386
|
seq: adm.seq,
|
|
390
387
|
type: "rejected",
|
|
@@ -421,7 +418,7 @@ const admitCmd = (h, rec, statement, auth, selection) => {
|
|
|
421
418
|
method: statement.method,
|
|
422
419
|
params,
|
|
423
420
|
clientId: rec.id,
|
|
424
|
-
caller: callerOf(h, rec,
|
|
421
|
+
caller: callerOf(h, rec, conn),
|
|
425
422
|
onApplied: () => {
|
|
426
423
|
if (adm.settled || adm.applied) return;
|
|
427
424
|
adm.applied = true;
|
|
@@ -437,25 +434,20 @@ const admitCmd = (h, rec, statement, auth, selection) => {
|
|
|
437
434
|
});
|
|
438
435
|
});
|
|
439
436
|
};
|
|
440
|
-
const admitFrame = (h,
|
|
441
|
-
|
|
442
|
-
protocols: [{
|
|
443
|
-
name: h.protocol.name,
|
|
444
|
-
version: h.protocol.version
|
|
445
|
-
}]
|
|
446
|
-
}) => {
|
|
437
|
+
const admitFrame = (h, conn, frame) => {
|
|
438
|
+
const rec = h.clients.get(conn.clientId);
|
|
447
439
|
rec.touched = Date.now();
|
|
448
440
|
const through = admittedThrough(rec);
|
|
449
441
|
for (const statement of frame.cmd) if (statement.seq <= through) reemit(h, rec, statement.seq);
|
|
450
|
-
const ctxNew = frame.ctx.filter((s) => s.seq >
|
|
442
|
+
const ctxNew = frame.ctx.filter((s) => s.seq > conn.ctxSeq);
|
|
451
443
|
const cmdNew = frame.cmd.filter((s) => s.seq > through);
|
|
452
|
-
if (ctxNew.length > 0 && ctxNew[0].seq !==
|
|
444
|
+
if (ctxNew.length > 0 && ctxNew[0].seq !== conn.ctxSeq + 1 || cmdNew.length > 0 && cmdNew[0].seq !== through + 1) {
|
|
453
445
|
notifyClientRecords(h);
|
|
454
446
|
return {
|
|
455
447
|
type: "refused",
|
|
456
448
|
syn: { syn: {
|
|
457
449
|
seq: through,
|
|
458
|
-
ctxSeq:
|
|
450
|
+
ctxSeq: conn.ctxSeq
|
|
459
451
|
} }
|
|
460
452
|
};
|
|
461
453
|
}
|
|
@@ -466,7 +458,7 @@ const admitFrame = (h, rec, frame, auth, selection = {
|
|
|
466
458
|
type: "refused",
|
|
467
459
|
syn: { syn: {
|
|
468
460
|
seq: through,
|
|
469
|
-
ctxSeq:
|
|
461
|
+
ctxSeq: conn.ctxSeq,
|
|
470
462
|
retry: COMMAND_CAPACITY_RETRY_MS
|
|
471
463
|
} }
|
|
472
464
|
};
|
|
@@ -479,23 +471,23 @@ const admitFrame = (h, rec, frame, auth, selection = {
|
|
|
479
471
|
type: "refused",
|
|
480
472
|
syn: { syn: {
|
|
481
473
|
seq: through,
|
|
482
|
-
ctxSeq:
|
|
474
|
+
ctxSeq: conn.ctxSeq,
|
|
483
475
|
retry
|
|
484
476
|
} }
|
|
485
477
|
};
|
|
486
478
|
}
|
|
487
479
|
}
|
|
488
|
-
let contextDocuments =
|
|
480
|
+
let contextDocuments = conn.contextDocuments;
|
|
489
481
|
try {
|
|
490
|
-
for (const statement of ctxNew) contextDocuments = applyDocumentOps(contextDocuments, statement.ops, selection.protocols, true);
|
|
482
|
+
for (const statement of ctxNew) contextDocuments = applyDocumentOps(contextDocuments, statement.ops, conn.selection.protocols, true);
|
|
491
483
|
if (frameEncoder.encode(JSON.stringify([...contextDocuments.documents])).byteLength > 65536) return violation("oversized-context");
|
|
492
484
|
} catch {
|
|
493
485
|
return violation("invalid-context");
|
|
494
486
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
if (ctxNew.length)
|
|
498
|
-
for (const statement of cmdNew) admitCmd(h, rec,
|
|
487
|
+
conn.contextDocuments = contextDocuments;
|
|
488
|
+
conn.context = mainDocument(contextDocuments, h.protocol.name)?.value ?? null;
|
|
489
|
+
if (ctxNew.length) conn.ctxSeq = ctxNew.at(-1).seq;
|
|
490
|
+
for (const statement of cmdNew) admitCmd(h, rec, conn, statement);
|
|
499
491
|
if (cmdNew.length > 0) queueCmd(h, rec.id, {
|
|
500
492
|
seq: cmdNew.at(-1).seq,
|
|
501
493
|
dur: true
|
|
@@ -530,10 +522,9 @@ const message = (h, conn, data) => {
|
|
|
530
522
|
return;
|
|
531
523
|
}
|
|
532
524
|
if (frame.ctx.length === 0 && frame.cmd.length === 0) return;
|
|
533
|
-
const rec = h.clients.get(conn.clientId);
|
|
534
525
|
let admission;
|
|
535
526
|
try {
|
|
536
|
-
admission = admitFrame(h,
|
|
527
|
+
admission = admitFrame(h, conn, frame);
|
|
537
528
|
} catch (error) {
|
|
538
529
|
const reason = violationReason(error);
|
|
539
530
|
if (reason === null) throw error;
|
|
@@ -773,13 +764,7 @@ const register = (h, clientId, socket, sawFrame = false, auth = void 0, selectio
|
|
|
773
764
|
const created = {
|
|
774
765
|
id: clientId,
|
|
775
766
|
lastSeq: 0,
|
|
776
|
-
ctxSeq: 0,
|
|
777
767
|
touched: Date.now(),
|
|
778
|
-
context: null,
|
|
779
|
-
contextDocuments: {
|
|
780
|
-
mode: "mounted",
|
|
781
|
-
documents: /* @__PURE__ */ new Map()
|
|
782
|
-
},
|
|
783
768
|
results: /* @__PURE__ */ new Map(),
|
|
784
769
|
inflight: /* @__PURE__ */ new Map(),
|
|
785
770
|
principal: auth
|
|
@@ -796,7 +781,13 @@ const register = (h, clientId, socket, sawFrame = false, auth = void 0, selectio
|
|
|
796
781
|
sawFrame,
|
|
797
782
|
lastSentAt: 0,
|
|
798
783
|
lease: null,
|
|
799
|
-
auth
|
|
784
|
+
auth,
|
|
785
|
+
ctxSeq: 0,
|
|
786
|
+
context: null,
|
|
787
|
+
contextDocuments: {
|
|
788
|
+
mode: "mounted",
|
|
789
|
+
documents: /* @__PURE__ */ new Map()
|
|
790
|
+
}
|
|
800
791
|
};
|
|
801
792
|
h.conns.add(conn);
|
|
802
793
|
gcClients(h);
|
|
@@ -814,14 +805,13 @@ const register = (h, clientId, socket, sawFrame = false, auth = void 0, selectio
|
|
|
814
805
|
syn: {
|
|
815
806
|
...selection,
|
|
816
807
|
seq: admittedThrough(rec),
|
|
817
|
-
ctxSeq:
|
|
808
|
+
ctxSeq: 0,
|
|
818
809
|
...h.idleWire && { idle: true }
|
|
819
810
|
}
|
|
820
811
|
};
|
|
821
812
|
if (!selection.protocols.some((p) => p.name === h.protocol.name)) hello.ops = [];
|
|
822
813
|
sendTo(h, conn, JSON.stringify(hello));
|
|
823
814
|
return {
|
|
824
|
-
rec,
|
|
825
815
|
conn,
|
|
826
816
|
connection: {
|
|
827
817
|
clientId,
|
|
@@ -857,16 +847,15 @@ const suspend = (h) => {
|
|
|
857
847
|
h.stateHost?.setOnOp(null);
|
|
858
848
|
};
|
|
859
849
|
const restoreClientRecords = (records = []) => new Map(records.map((record) => [record.id, {
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
documents: new Map(record.contextDocuments ?? [])
|
|
864
|
-
},
|
|
850
|
+
id: record.id,
|
|
851
|
+
lastSeq: record.lastSeq,
|
|
852
|
+
touched: record.touched,
|
|
865
853
|
results: new Map(record.results.map(({ seq, ts, cmd }) => [seq, {
|
|
866
854
|
ts,
|
|
867
855
|
cmd
|
|
868
856
|
}])),
|
|
869
|
-
inflight: /* @__PURE__ */ new Map()
|
|
857
|
+
inflight: /* @__PURE__ */ new Map(),
|
|
858
|
+
principal: record.principal
|
|
870
859
|
}]));
|
|
871
860
|
const useSocketHost = (transport, options, persistence) => {
|
|
872
861
|
const [h] = useState(() => {
|