statewire 0.0.0-0 → 0.0.1

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 (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -1
  3. package/dist/client/changes.d.ts +7 -0
  4. package/dist/client/changes.d.ts.map +1 -0
  5. package/dist/client/changes.js +32 -0
  6. package/dist/client/changes.js.map +1 -0
  7. package/dist/client/connection.d.ts +84 -0
  8. package/dist/client/connection.d.ts.map +1 -0
  9. package/dist/client/connection.js +204 -0
  10. package/dist/client/connection.js.map +1 -0
  11. package/dist/client/core.d.ts +18 -0
  12. package/dist/client/core.d.ts.map +1 -0
  13. package/dist/client/core.js +269 -0
  14. package/dist/client/core.js.map +1 -0
  15. package/dist/client/optimistic.d.ts +10 -0
  16. package/dist/client/optimistic.d.ts.map +1 -0
  17. package/dist/client/optimistic.js +128 -0
  18. package/dist/client/optimistic.js.map +1 -0
  19. package/dist/client/session.d.ts +88 -0
  20. package/dist/client/session.d.ts.map +1 -0
  21. package/dist/client/session.js +509 -0
  22. package/dist/client/session.js.map +1 -0
  23. package/dist/client/sessionStore.d.ts +16 -0
  24. package/dist/client/sessionStore.d.ts.map +1 -0
  25. package/dist/client/sessionStore.js +14 -0
  26. package/dist/client/sessionStore.js.map +1 -0
  27. package/dist/client/timing.d.ts +10 -0
  28. package/dist/client/timing.d.ts.map +1 -0
  29. package/dist/client/timing.js +11 -0
  30. package/dist/client/timing.js.map +1 -0
  31. package/dist/host/draft.d.ts +14 -0
  32. package/dist/host/draft.d.ts.map +1 -0
  33. package/dist/host/draft.js +124 -0
  34. package/dist/host/draft.js.map +1 -0
  35. package/dist/host/engine.d.ts +14 -0
  36. package/dist/host/engine.d.ts.map +1 -0
  37. package/dist/host/engine.js +17 -0
  38. package/dist/host/engine.js.map +1 -0
  39. package/dist/host/host.d.ts +79 -0
  40. package/dist/host/host.d.ts.map +1 -0
  41. package/dist/host/host.js +303 -0
  42. package/dist/host/host.js.map +1 -0
  43. package/dist/index.d.ts +28 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +6 -0
  46. package/dist/server.d.ts +15 -0
  47. package/dist/server.d.ts.map +1 -0
  48. package/dist/server.js +3 -0
  49. package/dist/statewire.d.ts +20 -0
  50. package/dist/statewire.d.ts.map +1 -0
  51. package/dist/statewire.js +65 -0
  52. package/dist/statewire.js.map +1 -0
  53. package/dist/transports/remote.d.ts +19 -0
  54. package/dist/transports/remote.d.ts.map +1 -0
  55. package/dist/transports/remote.js +40 -0
  56. package/dist/transports/remote.js.map +1 -0
  57. package/dist/transports/sse-parser.d.ts +5 -0
  58. package/dist/transports/sse-parser.d.ts.map +1 -0
  59. package/dist/transports/sse-parser.js +26 -0
  60. package/dist/transports/sse-parser.js.map +1 -0
  61. package/dist/transports/sse.d.ts +74 -0
  62. package/dist/transports/sse.d.ts.map +1 -0
  63. package/dist/transports/sse.js +136 -0
  64. package/dist/transports/sse.js.map +1 -0
  65. package/dist/transports/testing.d.ts +31 -0
  66. package/dist/transports/testing.d.ts.map +1 -0
  67. package/dist/transports/testing.js +121 -0
  68. package/dist/transports/testing.js.map +1 -0
  69. package/dist/transports/ws.d.ts +18 -0
  70. package/dist/transports/ws.d.ts.map +1 -0
  71. package/dist/transports/ws.js +172 -0
  72. package/dist/transports/ws.js.map +1 -0
  73. package/dist/types.d.ts +107 -0
  74. package/dist/types.d.ts.map +1 -0
  75. package/dist/types.js +24 -0
  76. package/dist/types.js.map +1 -0
  77. package/dist/wire/meta.d.ts +22 -0
  78. package/dist/wire/meta.d.ts.map +1 -0
  79. package/dist/wire/meta.js +73 -0
  80. package/dist/wire/meta.js.map +1 -0
  81. package/dist/wire/ops.d.ts +40 -0
  82. package/dist/wire/ops.d.ts.map +1 -0
  83. package/dist/wire/ops.js +125 -0
  84. package/dist/wire/ops.js.map +1 -0
  85. package/package.json +49 -6
  86. package/src/client/changes.ts +48 -0
  87. package/src/client/connection.ts +327 -0
  88. package/src/client/core.ts +346 -0
  89. package/src/client/optimistic.ts +0 -0
  90. package/src/client/session.ts +679 -0
  91. package/src/client/sessionStore.ts +23 -0
  92. package/src/client/timing.ts +8 -0
  93. package/src/host/draft.ts +155 -0
  94. package/src/host/engine.ts +13 -0
  95. package/src/host/host.ts +481 -0
  96. package/src/index.ts +65 -0
  97. package/src/server.ts +32 -0
  98. package/src/statewire.ts +107 -0
  99. package/src/transports/remote.ts +72 -0
  100. package/src/transports/sse-parser.ts +24 -0
  101. package/src/transports/sse.ts +280 -0
  102. package/src/transports/testing.ts +155 -0
  103. package/src/transports/ws.ts +272 -0
  104. package/src/types.ts +169 -0
  105. package/src/wire/meta.ts +106 -0
  106. package/src/wire/ops.ts +201 -0
  107. package/index.js +0 -1
@@ -0,0 +1,509 @@
1
+ import { applyOps } from "../wire/ops.js";
2
+ import { StatewireSendError } from "../types.js";
3
+ import { bindCommandsHost } from "../host/host.js";
4
+ import { backoff } from "./timing.js";
5
+ import { createMemorySessionStore } from "./sessionStore.js";
6
+ //#region src/client/session.ts
7
+ const isResolved = (state) => state.at === "settled-live" || state.at === "done";
8
+ const isStateSettled = (state) => state.at === "awaiting-result" || state.at === "done";
9
+ const legalTransitions = {
10
+ queued: [
11
+ "queued",
12
+ "trying",
13
+ "awaiting-result",
14
+ "settled-live",
15
+ "done"
16
+ ],
17
+ trying: [
18
+ "queued",
19
+ "trying",
20
+ "posted",
21
+ "awaiting-result",
22
+ "settled-live",
23
+ "done"
24
+ ],
25
+ posted: [
26
+ "posted",
27
+ "trying",
28
+ "awaiting-result",
29
+ "settled-live",
30
+ "done"
31
+ ],
32
+ "awaiting-result": ["awaiting-result", "done"],
33
+ "settled-live": ["settled-live", "done"],
34
+ done: []
35
+ };
36
+ const transition = (s, entry, next, outcome) => {
37
+ const prev = entry.state;
38
+ if (!legalTransitions[prev.at].includes(next.at)) throw new Error(`statewire: illegal pending transition ${prev.at} -> ${next.at}`);
39
+ const settles = !isResolved(prev) && isResolved(next);
40
+ if (settles && outcome === void 0) throw new Error(`statewire: settling transition ${prev.at} -> ${next.at} without an outcome`);
41
+ const covers = !isStateSettled(prev) && isStateSettled(next);
42
+ entry.state = next;
43
+ if (covers) s.lifecycle?.onCovered?.(entry.inv);
44
+ if (settles && outcome !== void 0) if (outcome.ok) {
45
+ entry.resolve(outcome.payload);
46
+ s.lifecycle?.onSettle(entry.inv, {
47
+ type: "accepted",
48
+ payload: outcome.payload
49
+ });
50
+ } else {
51
+ entry.reject(new StatewireSendError(outcome.failure));
52
+ s.lifecycle?.onSettle(entry.inv, {
53
+ type: "rejected",
54
+ error: new StatewireSendError(outcome.failure)
55
+ });
56
+ }
57
+ if (next.at === "done") s.pending = s.pending.filter((p) => p !== entry);
58
+ };
59
+ const carried = (state) => state.at === "queued" ? {
60
+ posted: false,
61
+ failedAttempts: 0
62
+ } : state.at === "trying" || state.at === "posted" ? {
63
+ posted: state.at === "posted",
64
+ failedAttempts: state.failedAttempts
65
+ } : {
66
+ posted: state.posted,
67
+ failedAttempts: state.failedAttempts
68
+ };
69
+ const newClientId = () => `c-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
70
+ const rejectedSend = (failure) => {
71
+ const result = Promise.reject(new StatewireSendError(failure));
72
+ result.catch(() => {});
73
+ return result;
74
+ };
75
+ const createCommandsProxy = (send) => {
76
+ const memo = /* @__PURE__ */ new Map();
77
+ return new Proxy({}, { get: (_target, method) => {
78
+ if (typeof method !== "string") return void 0;
79
+ let fn = memo.get(method);
80
+ if (fn === void 0) {
81
+ fn = (...params) => send({
82
+ method,
83
+ params
84
+ });
85
+ memo.set(method, fn);
86
+ }
87
+ return fn;
88
+ } });
89
+ };
90
+ const createSession = (options) => {
91
+ const store = options.sessionStore ?? createMemorySessionStore();
92
+ const stored = store.load();
93
+ const s = {
94
+ record: stored ?? {
95
+ clientId: newClientId(),
96
+ nextSeq: 1
97
+ },
98
+ recordPersisted: stored !== null,
99
+ store,
100
+ lastAck: -1,
101
+ pending: [],
102
+ canonical: void 0,
103
+ lastPublished: void 0,
104
+ changed: [],
105
+ source: {
106
+ root: () => s.canonical,
107
+ takeChanged: () => {
108
+ const changed = s.changed;
109
+ s.changed = [];
110
+ return changed;
111
+ },
112
+ setOnChange: (listener) => {
113
+ s.notify = listener ?? (() => {});
114
+ }
115
+ },
116
+ attach: "detached",
117
+ attachEpoch: 0,
118
+ running: false,
119
+ pumping: false,
120
+ transport: null,
121
+ waiters: [],
122
+ lifecycle: null,
123
+ notify: () => {},
124
+ emitEvent: () => {},
125
+ send: (command) => sendCommand(s, command),
126
+ commands: createCommandsProxy((command) => s.send(command))
127
+ };
128
+ bindCommandsHost(s.commands, { setListener: (listener) => {
129
+ s.lifecycle = listener;
130
+ } });
131
+ return s;
132
+ };
133
+ const publish = (s) => {
134
+ if (s.canonical === s.lastPublished) return;
135
+ s.lastPublished = s.canonical;
136
+ s.notify();
137
+ };
138
+ const wake = (s) => {
139
+ const waiters = s.waiters;
140
+ s.waiters = [];
141
+ for (const waiter of waiters) waiter();
142
+ };
143
+ const waitForWake = (s) => new Promise((r) => s.waiters.push(r));
144
+ const settleAll = (s, detach, verdict) => {
145
+ const cause = {
146
+ evicted: "session-lost",
147
+ unmount: "unmount",
148
+ gone: "stream-gone",
149
+ superseded: "superseded"
150
+ }[detach];
151
+ const batch = s.pending;
152
+ const detachFailure = (entry) => {
153
+ const state = entry.state;
154
+ if (state.at === "awaiting-result") return {
155
+ fate: "result-unavailable",
156
+ cause
157
+ };
158
+ if (state.at === "queued") return {
159
+ fate: "aborted",
160
+ cause: batch.some((p) => p.seq < entry.seq && p.state.at !== "queued") ? "cascade" : cause
161
+ };
162
+ return {
163
+ fate: "lost",
164
+ cause
165
+ };
166
+ };
167
+ for (const entry of [...batch]) {
168
+ const failure = entry === verdict?.entry ? verdict.failure : detachFailure(entry);
169
+ transition(s, entry, { at: "done" }, {
170
+ ok: false,
171
+ failure
172
+ });
173
+ }
174
+ };
175
+ const evict = (s, verdict) => {
176
+ settleAll(s, "evicted", verdict);
177
+ s.record = {
178
+ clientId: newClientId(),
179
+ nextSeq: 1
180
+ };
181
+ s.store.save(s.record);
182
+ s.attach = "detached";
183
+ publish(s);
184
+ wake(s);
185
+ };
186
+ const noteAcked = (s, seq) => {
187
+ for (const entry of s.pending) {
188
+ if (entry.seq > seq || isStateSettled(entry.state)) continue;
189
+ s.lifecycle?.onAck(entry.inv);
190
+ }
191
+ };
192
+ const spliceAcked = (s, seq, settleVoid) => {
193
+ for (const entry of [...s.pending]) {
194
+ const state = entry.state;
195
+ if (entry.seq > seq || isStateSettled(state)) continue;
196
+ if (state.at === "settled-live") transition(s, entry, { at: "done" });
197
+ else if (settleVoid && !state.pendingMarked) transition(s, entry, { at: "done" }, {
198
+ ok: true,
199
+ payload: void 0
200
+ });
201
+ else transition(s, entry, {
202
+ at: "awaiting-result",
203
+ ...carried(state)
204
+ });
205
+ }
206
+ };
207
+ const protocolError = (message) => {
208
+ throw new Error(`statewire: protocol error: ${message}`);
209
+ };
210
+ const applyResponse = (s, response) => {
211
+ const entry = s.pending.find((p) => p.seq === response.seq);
212
+ if (!entry) return;
213
+ const state = entry.state;
214
+ if (state.at === "done") return;
215
+ switch (response.type) {
216
+ case "pending":
217
+ if (state.at === "queued" || state.at === "trying" || state.at === "posted") transition(s, entry, {
218
+ ...state,
219
+ pendingMarked: true
220
+ });
221
+ break;
222
+ case "accepted":
223
+ if (state.at === "settled-live") break;
224
+ transition(s, entry, state.at === "awaiting-result" ? { at: "done" } : {
225
+ at: "settled-live",
226
+ ...carried(state)
227
+ }, {
228
+ ok: true,
229
+ payload: response.payload
230
+ });
231
+ break;
232
+ case "rejected":
233
+ transition(s, entry, { at: "done" }, {
234
+ ok: false,
235
+ failure: response.code === "unknown-command" ? {
236
+ fate: "unknown-command",
237
+ cause: "server"
238
+ } : response.code === "invalid-params" ? {
239
+ fate: "invalid-params",
240
+ cause: "server",
241
+ message: response.message ?? ""
242
+ } : {
243
+ fate: "rejected",
244
+ cause: "server",
245
+ message: response.message ?? "",
246
+ ...response.payload !== void 0 && { payload: response.payload }
247
+ }
248
+ });
249
+ break;
250
+ case "crashed":
251
+ case "result-unavailable":
252
+ if (state.at === "settled-live") break;
253
+ transition(s, entry, state.at === "awaiting-result" ? { at: "done" } : {
254
+ at: "settled-live",
255
+ ...carried(state)
256
+ }, {
257
+ ok: false,
258
+ failure: {
259
+ fate: response.type,
260
+ cause: "server"
261
+ }
262
+ });
263
+ break;
264
+ }
265
+ };
266
+ const ingestOps = (s, ops) => {
267
+ const applied = applyOps(s.canonical, ops);
268
+ s.canonical = applied.state;
269
+ s.changed.push(...applied.changedPaths);
270
+ return applied.events;
271
+ };
272
+ const publishIngested = (s, events) => {
273
+ publish(s);
274
+ for (const { event } of events) s.emitEvent(event);
275
+ wake(s);
276
+ };
277
+ const handleSnapshot = (s, { ops, lastSeq }) => {
278
+ if (lastSeq === -1 && s.attach !== "detached") {
279
+ evict(s);
280
+ s.transport?.connection.reconnect();
281
+ publishIngested(s, ingestOps(s, ops));
282
+ return;
283
+ }
284
+ const events = ingestOps(s, ops);
285
+ s.attach = "attached";
286
+ s.attachEpoch += 1;
287
+ noteAcked(s, lastSeq);
288
+ spliceAcked(s, lastSeq, false);
289
+ s.lastAck = lastSeq;
290
+ for (const entry of s.pending) {
291
+ const state = entry.state;
292
+ if (entry.seq <= lastSeq) {
293
+ if (state.at === "awaiting-result" && state.posted) transition(s, entry, {
294
+ ...state,
295
+ posted: false
296
+ });
297
+ if (state.at === "awaiting-result") pump(s);
298
+ } else if (state.at === "posted") {
299
+ transition(s, entry, {
300
+ at: "trying",
301
+ pendingMarked: state.pendingMarked,
302
+ failedAttempts: state.failedAttempts
303
+ });
304
+ pump(s);
305
+ } else if (state.at === "settled-live" && state.posted) {
306
+ transition(s, entry, {
307
+ ...state,
308
+ posted: false
309
+ });
310
+ pump(s);
311
+ }
312
+ }
313
+ publishIngested(s, events);
314
+ };
315
+ const handleOps = (s, { ops, res, ack }) => {
316
+ const horizon = ack === void 0 ? s.lastAck : Math.max(s.lastAck, ack);
317
+ if (res !== void 0) {
318
+ for (const response of res) if (response.seq > horizon) protocolError("response seq beyond the ack");
319
+ }
320
+ const events = ingestOps(s, ops);
321
+ if (ack !== void 0) noteAcked(s, ack);
322
+ if (res !== void 0) for (const response of res) applyResponse(s, response);
323
+ if (ack !== void 0) {
324
+ spliceAcked(s, ack, true);
325
+ s.lastAck = Math.max(s.lastAck, ack);
326
+ }
327
+ publishIngested(s, events);
328
+ };
329
+ const handleFinish = (s, { reason }) => {
330
+ if (reason === "ended" || reason === "error") return;
331
+ s.attach = "finished";
332
+ settleAll(s, reason === "superseded" ? "superseded" : "gone");
333
+ publish(s);
334
+ wake(s);
335
+ };
336
+ const isFinished = (s) => s.attach === "finished";
337
+ const sendable = (p) => p.state.at === "queued" || p.state.at === "trying" || (p.state.at === "awaiting-result" || p.state.at === "settled-live") && !p.state.posted;
338
+ const pump = async (s) => {
339
+ if (s.pumping) return;
340
+ s.pumping = true;
341
+ try {
342
+ while (s.running && !isFinished(s)) {
343
+ const entry = s.pending.find(sendable);
344
+ if (!entry) return;
345
+ const transport = s.transport;
346
+ if (s.attach !== "attached" || !transport) {
347
+ await waitForWake(s);
348
+ continue;
349
+ }
350
+ const clientId = s.record.clientId;
351
+ const epoch = s.attachEpoch;
352
+ if (entry.state.at === "queued") transition(s, entry, {
353
+ at: "trying",
354
+ pendingMarked: entry.state.pendingMarked,
355
+ failedAttempts: 0
356
+ });
357
+ let result;
358
+ try {
359
+ result = await transport.send({
360
+ seq: entry.seq,
361
+ command: entry.command
362
+ });
363
+ } catch (error) {
364
+ if (!s.running || isFinished(s)) return;
365
+ if (!s.pending.includes(entry)) continue;
366
+ const state = entry.state;
367
+ if (state.at === "queued" || state.at === "done") continue;
368
+ transition(s, entry, {
369
+ ...state,
370
+ failedAttempts: state.failedAttempts + 1
371
+ });
372
+ const { retryAfterMs } = error;
373
+ const delay = typeof retryAfterMs === "number" ? retryAfterMs : backoff(state.failedAttempts + 1);
374
+ await new Promise((r) => setTimeout(r, delay));
375
+ continue;
376
+ }
377
+ if (!s.running) return;
378
+ if (!s.pending.includes(entry)) continue;
379
+ if (result.type === "receipt") {
380
+ const response = result.response;
381
+ const state = entry.state;
382
+ if (state.at === "trying" || state.at === "posted") transition(s, entry, {
383
+ at: "posted",
384
+ pendingMarked: state.pendingMarked,
385
+ failedAttempts: state.failedAttempts
386
+ });
387
+ else if (state.at === "awaiting-result" || state.at === "settled-live") transition(s, entry, {
388
+ ...state,
389
+ posted: true
390
+ });
391
+ s.lifecycle?.onPosted?.(entry.inv);
392
+ if (response !== void 0) {
393
+ applyResponse(s, response);
394
+ publish(s);
395
+ }
396
+ } else if (result.type === "rejected") {
397
+ const { message, payload } = result;
398
+ transition(s, entry, { at: "done" }, {
399
+ ok: false,
400
+ failure: {
401
+ fate: "rejected",
402
+ cause: "server",
403
+ message,
404
+ ...payload !== void 0 && { payload }
405
+ }
406
+ });
407
+ publish(s);
408
+ } else if (result.type === "stale-lease") {
409
+ if (epoch === s.attachEpoch) await waitForWake(s);
410
+ } else if (result.type === "unknown-client") {
411
+ if (epoch === s.attachEpoch) {
412
+ const state = entry.state;
413
+ if (state.at === "trying" && state.failedAttempts === 0) transition(s, entry, {
414
+ at: "queued",
415
+ pendingMarked: state.pendingMarked
416
+ });
417
+ s.transport?.connection.reconnect();
418
+ while (s.running && !isFinished(s) && epoch === s.attachEpoch && clientId === s.record.clientId) await waitForWake(s);
419
+ }
420
+ } else if (result.type === "seq-gap") {
421
+ if (clientId === s.record.clientId) {
422
+ console.error(`statewire: server reports a seq gap for seq ${entry.seq}; treating the session as corrupt and rotating the client id`);
423
+ const state = entry.state;
424
+ const failure = state.at === "awaiting-result" ? {
425
+ fate: "result-unavailable",
426
+ cause: "session-lost"
427
+ } : state.at === "queued" || state.at === "done" ? {
428
+ fate: "aborted",
429
+ cause: "session-lost"
430
+ } : {
431
+ fate: state.failedAttempts > 0 ? "lost" : "aborted",
432
+ cause: "session-lost"
433
+ };
434
+ evict(s, {
435
+ entry,
436
+ failure
437
+ });
438
+ s.transport?.connection.reconnect();
439
+ }
440
+ }
441
+ }
442
+ } finally {
443
+ s.pumping = false;
444
+ }
445
+ };
446
+ const start = (s) => {
447
+ if (!s.recordPersisted) {
448
+ s.recordPersisted = true;
449
+ s.store.save(s.record);
450
+ }
451
+ s.running = true;
452
+ pump(s);
453
+ };
454
+ const stop = (s) => {
455
+ s.running = false;
456
+ wake(s);
457
+ settleAll(s, "unmount");
458
+ };
459
+ const setTransport = (s, transport) => {
460
+ if (s.transport === transport) return;
461
+ s.transport = transport;
462
+ wake(s);
463
+ };
464
+ const sendCommand = (s, command) => {
465
+ if (!s.running) return rejectedSend({
466
+ fate: "aborted",
467
+ cause: "unmount"
468
+ });
469
+ if (isFinished(s)) return rejectedSend({
470
+ fate: "aborted",
471
+ cause: "stream-gone"
472
+ });
473
+ const seq = s.record.nextSeq;
474
+ s.record = {
475
+ ...s.record,
476
+ nextSeq: seq + 1
477
+ };
478
+ s.store.save(s.record);
479
+ const entry = {
480
+ seq,
481
+ command,
482
+ inv: {
483
+ method: command.method,
484
+ params: command.params,
485
+ ts: Date.now(),
486
+ seq,
487
+ clientId: s.record.clientId
488
+ },
489
+ state: {
490
+ at: "queued",
491
+ pendingMarked: false
492
+ },
493
+ resolve: () => {},
494
+ reject: () => {}
495
+ };
496
+ const result = new Promise((resolve, reject) => {
497
+ entry.resolve = resolve;
498
+ entry.reject = reject;
499
+ });
500
+ result.catch(() => {});
501
+ s.pending.push(entry);
502
+ s.lifecycle?.onStart(entry.inv);
503
+ pump(s);
504
+ return result;
505
+ };
506
+ //#endregion
507
+ export { createSession, handleFinish, handleOps, handleSnapshot, setTransport, start, stop };
508
+
509
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","names":["applyOps","StatewirePath","StatewireResponse","bindCommandsHost","CommandsInvocation","CommandsListener","StatewireStateSource","createMemorySessionStore","StatewireSessionRecord","StatewireSessionStore","backoff","StatewireSendError","SendFailure","StatewireSendFailure","RemoteLink","StatewireSubmitResult","StatewireWireCommand","SessionOptions","sessionStore","PendingState","at","pendingMarked","failedAttempts","posted","Pending","seq","command","inv","state","resolve","payload","reject","error","Outcome","ok","failure","isResolved","isStateSettled","legalTransitions","Record","queued","trying","done","transition","s","Session","entry","next","outcome","prev","includes","Error","settles","undefined","covers","lifecycle","onCovered","onSettle","type","pending","filter","p","carried","Exclude","newClientId","Date","now","toString","Math","random","slice","rejectedSend","Promise","result","catch","AttachState","record","recordPersisted","store","lastAck","canonical","lastPublished","changed","source","attach","attachEpoch","running","pumping","transport","waiters","notify","emitEvent","event","send","commands","params","createCommandsProxy","memo","Map","Proxy","get","_target","method","fn","set","createSession","options","stored","load","clientId","nextSeq","root","takeChanged","setOnChange","listener","sendCommand","setListener","publish","wake","waiter","waitForWake","r","push","settleAll","detach","verdict","cause","evicted","unmount","gone","superseded","const","batch","detachFailure","fate","cascades","some","evict","save","noteAcked","onAck","spliceAcked","settleVoid","protocolError","message","applyResponse","response","find","code","ingestOps","ops","applied","changedPaths","events","publishIngested","handleSnapshot","lastSeq","connection","reconnect","pump","handleOps","res","ack","horizon","max","handleFinish","reason","isFinished","sendable","epoch","retryAfterMs","delay","setTimeout","onPosted","console","start","stop","setTransport","ts","onStart"],"sources":["../../src/client/session.ts"],"sourcesContent":["import { applyOps } from \"../wire/ops\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport type { StatewireResponse } from \"./connection\";\nimport { bindCommandsHost } from \"../host/host\";\nimport type { CommandsInvocation, CommandsListener } from \"../host/host\";\nimport type { StatewireStateSource } from \"../types\";\nimport { createMemorySessionStore } from \"./sessionStore\";\nimport type {\n StatewireSessionRecord,\n StatewireSessionStore,\n} from \"./sessionStore\";\nimport { backoff } from \"./timing\";\nimport { StatewireSendError } from \"../types\";\nimport type { SendFailure as StatewireSendFailure } from \"../types\";\nimport type {\n RemoteLink,\n StatewireSubmitResult,\n StatewireWireCommand,\n} from \"../transports/sse\";\n\nexport type SessionOptions = {\n sessionStore?: StatewireSessionStore | undefined;\n};\n\n/**\n * queued/trying/posted: overlay live, result pending. awaiting-result: acked\n * (overlay gone) but the result rides a late res; `posted: false` re-sends.\n * settled-live: result settled but the overlay stays until the covering ack.\n * done: removed from the queue.\n */\ntype PendingState =\n | { at: \"queued\"; pendingMarked: boolean }\n | { at: \"trying\"; pendingMarked: boolean; failedAttempts: number }\n | { at: \"posted\"; pendingMarked: boolean; failedAttempts: number }\n | { at: \"awaiting-result\"; posted: boolean; failedAttempts: number }\n | { at: \"settled-live\"; posted: boolean; failedAttempts: number }\n | { at: \"done\" };\n\ntype Pending = {\n readonly seq: number;\n readonly command: StatewireWireCommand;\n readonly inv: CommandsInvocation;\n state: PendingState;\n resolve: (payload: unknown) => void;\n reject: (error: StatewireSendError) => void;\n};\n\ntype Outcome =\n | { ok: true; payload: unknown }\n | { ok: false; failure: StatewireSendFailure };\n\nconst isResolved = (state: PendingState) =>\n state.at === \"settled-live\" || state.at === \"done\";\n\nconst isStateSettled = (state: PendingState) =>\n state.at === \"awaiting-result\" || state.at === \"done\";\n\nconst legalTransitions: Record<PendingState[\"at\"], PendingState[\"at\"][]> = {\n queued: [\"queued\", \"trying\", \"awaiting-result\", \"settled-live\", \"done\"],\n // trying -> queued: an answered unknown-client proves the seq was never admitted.\n trying: [\n \"queued\",\n \"trying\",\n \"posted\",\n \"awaiting-result\",\n \"settled-live\",\n \"done\",\n ],\n posted: [\"posted\", \"trying\", \"awaiting-result\", \"settled-live\", \"done\"],\n \"awaiting-result\": [\"awaiting-result\", \"done\"],\n \"settled-live\": [\"settled-live\", \"done\"],\n done: [],\n};\n\nconst transition = (\n s: Session,\n entry: Pending,\n next: PendingState,\n outcome?: Outcome,\n) => {\n const prev = entry.state;\n if (!legalTransitions[prev.at].includes(next.at)) {\n throw new Error(\n `statewire: illegal pending transition ${prev.at} -> ${next.at}`,\n );\n }\n const settles = !isResolved(prev) && isResolved(next);\n if (settles && outcome === undefined) {\n throw new Error(\n `statewire: settling transition ${prev.at} -> ${next.at} without an outcome`,\n );\n }\n const covers = !isStateSettled(prev) && isStateSettled(next);\n entry.state = next;\n if (covers) s.lifecycle?.onCovered?.(entry.inv);\n if (settles && outcome !== undefined) {\n if (outcome.ok) {\n entry.resolve(outcome.payload);\n s.lifecycle?.onSettle(entry.inv, {\n type: \"accepted\",\n payload: outcome.payload,\n });\n } else {\n entry.reject(new StatewireSendError(outcome.failure));\n s.lifecycle?.onSettle(entry.inv, {\n type: \"rejected\",\n error: new StatewireSendError(outcome.failure),\n });\n }\n }\n if (next.at === \"done\") {\n s.pending = s.pending.filter((p) => p !== entry);\n }\n};\n\nconst carried = (\n state: Exclude<PendingState, { at: \"done\" }>,\n): { posted: boolean; failedAttempts: number } =>\n state.at === \"queued\"\n ? { posted: false, failedAttempts: 0 }\n : state.at === \"trying\" || state.at === \"posted\"\n ? { posted: state.at === \"posted\", failedAttempts: state.failedAttempts }\n : { posted: state.posted, failedAttempts: state.failedAttempts };\n\nconst newClientId = () =>\n `c-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n\nconst rejectedSend = (failure: StatewireSendFailure): Promise<unknown> => {\n const result = Promise.reject<unknown>(new StatewireSendError(failure));\n result.catch(() => {});\n return result;\n};\n\ntype AttachState = \"detached\" | \"attached\" | \"finished\";\n\ntype Session = {\n record: StatewireSessionRecord;\n recordPersisted: boolean;\n store: StatewireSessionStore;\n lastAck: number;\n pending: Pending[];\n canonical: unknown;\n lastPublished: unknown;\n changed: StatewirePath[];\n source: StatewireStateSource;\n attach: AttachState;\n attachEpoch: number;\n running: boolean;\n pumping: boolean;\n transport: RemoteLink | null;\n waiters: (() => void)[];\n lifecycle: CommandsListener | null;\n notify: () => void;\n emitEvent: (event: unknown) => void;\n send: (command: StatewireWireCommand) => Promise<unknown>;\n commands: Record<string, (...params: unknown[]) => Promise<unknown>>;\n};\n\nconst createCommandsProxy = (\n send: (command: StatewireWireCommand) => Promise<unknown>,\n): Session[\"commands\"] => {\n const memo = new Map<string, (...params: unknown[]) => Promise<unknown>>();\n return new Proxy({} as Session[\"commands\"], {\n get: (_target, method) => {\n if (typeof method !== \"string\") return undefined;\n let fn = memo.get(method);\n if (fn === undefined) {\n fn = (...params: unknown[]) => send({ method, params });\n memo.set(method, fn);\n }\n return fn;\n },\n });\n};\n\nconst createSession = (options: SessionOptions): Session => {\n const store = options.sessionStore ?? createMemorySessionStore();\n const stored = store.load();\n const record = stored ?? { clientId: newClientId(), nextSeq: 1 };\n const s: Session = {\n record,\n recordPersisted: stored !== null,\n store,\n lastAck: -1,\n pending: [],\n canonical: undefined,\n lastPublished: undefined,\n changed: [],\n source: {\n root: () => s.canonical,\n takeChanged: () => {\n const changed = s.changed;\n s.changed = [];\n return changed;\n },\n setOnChange: (listener) => {\n s.notify = listener ?? (() => {});\n },\n },\n attach: \"detached\",\n attachEpoch: 0,\n running: false,\n pumping: false,\n transport: null,\n waiters: [],\n lifecycle: null,\n notify: () => {},\n emitEvent: () => {},\n send: (command) => sendCommand(s, command),\n commands: createCommandsProxy((command) => s.send(command)),\n };\n bindCommandsHost(s.commands, {\n setListener: (listener) => {\n s.lifecycle = listener;\n },\n });\n return s;\n};\n\nconst publish = (s: Session) => {\n if (s.canonical === s.lastPublished) return;\n s.lastPublished = s.canonical;\n s.notify();\n};\n\nconst wake = (s: Session) => {\n const waiters = s.waiters;\n s.waiters = [];\n for (const waiter of waiters) waiter();\n};\n\nconst waitForWake = (s: Session) => new Promise<void>((r) => s.waiters.push(r));\n\nconst settleAll = (\n s: Session,\n detach: \"evicted\" | \"unmount\" | \"gone\" | \"superseded\",\n verdict?: {\n entry: Pending;\n failure: StatewireSendFailure;\n },\n) => {\n const cause = (\n {\n evicted: \"session-lost\",\n unmount: \"unmount\",\n gone: \"stream-gone\",\n superseded: \"superseded\",\n } as const\n )[detach];\n const batch = s.pending;\n const detachFailure = (entry: Pending): StatewireSendFailure => {\n const state = entry.state;\n if (state.at === \"awaiting-result\")\n return { fate: \"result-unavailable\", cause };\n if (state.at === \"queued\") {\n const cascades = batch.some(\n (p) => p.seq < entry.seq && p.state.at !== \"queued\",\n );\n return { fate: \"aborted\", cause: cascades ? \"cascade\" : cause };\n }\n return { fate: \"lost\", cause };\n };\n for (const entry of [...batch]) {\n const failure =\n entry === verdict?.entry ? verdict.failure : detachFailure(entry);\n transition(s, entry, { at: \"done\" }, { ok: false, failure });\n }\n};\n\nconst evict = (\n s: Session,\n verdict?: {\n entry: Pending;\n failure: StatewireSendFailure;\n },\n) => {\n settleAll(s, \"evicted\", verdict);\n s.record = { clientId: newClientId(), nextSeq: 1 };\n s.store.save(s.record);\n s.attach = \"detached\";\n publish(s);\n wake(s);\n};\n\nconst noteAcked = (s: Session, seq: number) => {\n for (const entry of s.pending) {\n if (entry.seq > seq || isStateSettled(entry.state)) continue;\n s.lifecycle?.onAck(entry.inv);\n }\n};\n\nconst spliceAcked = (s: Session, seq: number, settleVoid: boolean) => {\n for (const entry of [...s.pending]) {\n const state = entry.state;\n if (entry.seq > seq || isStateSettled(state)) continue;\n if (state.at === \"settled-live\") {\n transition(s, entry, { at: \"done\" });\n } else if (settleVoid && !state.pendingMarked) {\n transition(s, entry, { at: \"done\" }, { ok: true, payload: undefined });\n } else {\n transition(s, entry, { at: \"awaiting-result\", ...carried(state) });\n }\n }\n};\n\nconst protocolError = (message: string): never => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\nconst applyResponse = (s: Session, response: StatewireResponse) => {\n const entry = s.pending.find((p) => p.seq === response.seq);\n if (!entry) return;\n const state = entry.state;\n if (state.at === \"done\") return;\n switch (response.type) {\n case \"pending\":\n if (\n state.at === \"queued\" ||\n state.at === \"trying\" ||\n state.at === \"posted\"\n ) {\n transition(s, entry, { ...state, pendingMarked: true });\n }\n break;\n case \"accepted\":\n if (state.at === \"settled-live\") break;\n transition(\n s,\n entry,\n state.at === \"awaiting-result\"\n ? { at: \"done\" }\n : { at: \"settled-live\", ...carried(state) },\n { ok: true, payload: response.payload },\n );\n break;\n case \"rejected\":\n transition(\n s,\n entry,\n { at: \"done\" },\n {\n ok: false,\n failure:\n response.code === \"unknown-command\"\n ? { fate: \"unknown-command\", cause: \"server\" }\n : response.code === \"invalid-params\"\n ? {\n fate: \"invalid-params\",\n cause: \"server\",\n message: response.message ?? \"\",\n }\n : {\n fate: \"rejected\",\n cause: \"server\",\n message: response.message ?? \"\",\n ...(response.payload !== undefined && {\n payload: response.payload,\n }),\n },\n },\n );\n break;\n case \"crashed\":\n case \"result-unavailable\":\n if (state.at === \"settled-live\") break;\n transition(\n s,\n entry,\n state.at === \"awaiting-result\"\n ? { at: \"done\" }\n : { at: \"settled-live\", ...carried(state) },\n { ok: false, failure: { fate: response.type, cause: \"server\" } },\n );\n break;\n }\n};\n\nconst ingestOps = (s: Session, ops: unknown[]) => {\n const applied = applyOps(s.canonical, ops);\n s.canonical = applied.state;\n s.changed.push(...applied.changedPaths);\n return applied.events;\n};\n\nconst publishIngested = (\n s: Session,\n events: { event: unknown; state: unknown }[],\n) => {\n publish(s);\n for (const { event } of events) s.emitEvent(event);\n wake(s);\n};\n\nconst handleSnapshot = (\n s: Session,\n { ops, lastSeq }: { ops: unknown[]; lastSeq: number },\n) => {\n if (lastSeq === -1 && s.attach !== \"detached\") {\n evict(s);\n s.transport?.connection.reconnect();\n publishIngested(s, ingestOps(s, ops));\n return;\n }\n const events = ingestOps(s, ops);\n s.attach = \"attached\";\n s.attachEpoch += 1;\n // The attach snapshot is not the true covering envelope: acked entries\n // stay awaiting their result and re-send under seq dedup.\n noteAcked(s, lastSeq);\n spliceAcked(s, lastSeq, false);\n s.lastAck = lastSeq;\n for (const entry of s.pending) {\n const state = entry.state;\n if (entry.seq <= lastSeq) {\n if (state.at === \"awaiting-result\" && state.posted) {\n transition(s, entry, { ...state, posted: false });\n }\n if (state.at === \"awaiting-result\") void pump(s);\n } else if (state.at === \"posted\") {\n // Above the ack watermark a prior receipt no longer counts.\n transition(s, entry, {\n at: \"trying\",\n pendingMarked: state.pendingMarked,\n failedAttempts: state.failedAttempts,\n });\n void pump(s);\n } else if (state.at === \"settled-live\" && state.posted) {\n transition(s, entry, { ...state, posted: false });\n void pump(s);\n }\n }\n publishIngested(s, events);\n};\n\nconst handleOps = (\n s: Session,\n {\n ops,\n res,\n ack,\n }: { ops: unknown[]; res?: StatewireResponse[]; ack?: number },\n) => {\n const horizon = ack === undefined ? s.lastAck : Math.max(s.lastAck, ack);\n if (res !== undefined) {\n for (const response of res) {\n if (response.seq > horizon) {\n protocolError(\"response seq beyond the ack\");\n }\n }\n }\n const events = ingestOps(s, ops);\n if (ack !== undefined) noteAcked(s, ack);\n if (res !== undefined) for (const response of res) applyResponse(s, response);\n if (ack !== undefined) {\n spliceAcked(s, ack, true);\n s.lastAck = Math.max(s.lastAck, ack);\n }\n publishIngested(s, events);\n};\n\nconst handleFinish = (s: Session, { reason }: { reason: string }) => {\n if (reason === \"ended\" || reason === \"error\") return;\n s.attach = \"finished\";\n settleAll(s, reason === \"superseded\" ? \"superseded\" : \"gone\");\n publish(s);\n wake(s);\n};\n\nconst isFinished = (s: Session) => s.attach === \"finished\";\n\nconst sendable = (p: Pending) =>\n p.state.at === \"queued\" ||\n p.state.at === \"trying\" ||\n ((p.state.at === \"awaiting-result\" || p.state.at === \"settled-live\") &&\n !p.state.posted);\n\nconst pump = async (s: Session) => {\n if (s.pumping) return;\n s.pumping = true;\n try {\n while (s.running && !isFinished(s)) {\n const entry = s.pending.find(sendable);\n if (!entry) return;\n const transport = s.transport;\n if (s.attach !== \"attached\" || !transport) {\n await waitForWake(s);\n continue;\n }\n const clientId = s.record.clientId;\n const epoch = s.attachEpoch;\n if (entry.state.at === \"queued\") {\n transition(s, entry, {\n at: \"trying\",\n pendingMarked: entry.state.pendingMarked,\n failedAttempts: 0,\n });\n }\n let result: StatewireSubmitResult;\n try {\n result = await transport.send({\n seq: entry.seq,\n command: entry.command,\n });\n } catch (error) {\n if (!s.running || isFinished(s)) return;\n if (!s.pending.includes(entry)) continue;\n const state = entry.state;\n if (state.at === \"queued\" || state.at === \"done\") continue;\n transition(s, entry, {\n ...state,\n failedAttempts: state.failedAttempts + 1,\n });\n const { retryAfterMs } = error as { retryAfterMs?: unknown };\n const delay =\n typeof retryAfterMs === \"number\"\n ? retryAfterMs\n : backoff(state.failedAttempts + 1);\n await new Promise((r) => setTimeout(r, delay));\n continue;\n }\n if (!s.running) return;\n if (!s.pending.includes(entry)) continue;\n if (result.type === \"receipt\") {\n const response = result.response;\n const state = entry.state;\n if (state.at === \"trying\" || state.at === \"posted\") {\n transition(s, entry, {\n at: \"posted\",\n pendingMarked: state.pendingMarked,\n failedAttempts: state.failedAttempts,\n });\n } else if (\n state.at === \"awaiting-result\" ||\n state.at === \"settled-live\"\n ) {\n transition(s, entry, { ...state, posted: true });\n }\n s.lifecycle?.onPosted?.(entry.inv);\n if (response !== undefined) {\n applyResponse(s, response);\n publish(s);\n }\n } else if (result.type === \"rejected\") {\n const { message, payload } = result;\n transition(\n s,\n entry,\n { at: \"done\" },\n {\n ok: false,\n failure: {\n fate: \"rejected\",\n cause: \"server\",\n message,\n ...(payload !== undefined && { payload }),\n },\n },\n );\n publish(s);\n } else if (result.type === \"stale-lease\") {\n if (epoch === s.attachEpoch) await waitForWake(s);\n } else if (result.type === \"unknown-client\") {\n // Eviction is never decided on the POST leg: re-attach first and let\n // the snapshot's lastSeq deliver the verdict. An answered attempt\n // proves the server never admitted this seq, so a clean entry requeues.\n if (epoch === s.attachEpoch) {\n const state = entry.state;\n if (state.at === \"trying\" && state.failedAttempts === 0) {\n transition(s, entry, {\n at: \"queued\",\n pendingMarked: state.pendingMarked,\n });\n }\n s.transport?.connection.reconnect();\n while (\n s.running &&\n !isFinished(s) &&\n epoch === s.attachEpoch &&\n clientId === s.record.clientId\n ) {\n await waitForWake(s);\n }\n }\n } else if (result.type === \"seq-gap\") {\n if (clientId === s.record.clientId) {\n console.error(\n `statewire: server reports a seq gap for seq ${entry.seq}; ` +\n \"treating the session as corrupt and rotating the client id\",\n );\n // Every attempt answered means the server never saw it; a thrown\n // attempt may have left the machine unanswered, so the verdict is \"lost\".\n const state = entry.state;\n const failure: StatewireSendFailure =\n state.at === \"awaiting-result\"\n ? { fate: \"result-unavailable\", cause: \"session-lost\" }\n : state.at === \"queued\" || state.at === \"done\"\n ? { fate: \"aborted\", cause: \"session-lost\" }\n : {\n fate: state.failedAttempts > 0 ? \"lost\" : \"aborted\",\n cause: \"session-lost\",\n };\n evict(s, { entry, failure });\n s.transport?.connection.reconnect();\n }\n }\n }\n } finally {\n s.pumping = false;\n }\n};\n\nconst start = (s: Session) => {\n if (!s.recordPersisted) {\n s.recordPersisted = true;\n s.store.save(s.record);\n }\n s.running = true;\n void pump(s);\n};\n\nconst stop = (s: Session) => {\n s.running = false;\n wake(s);\n settleAll(s, \"unmount\");\n};\n\nconst setTransport = (s: Session, transport: RemoteLink) => {\n if (s.transport === transport) return;\n s.transport = transport;\n wake(s);\n};\n\nconst sendCommand = (\n s: Session,\n command: StatewireWireCommand,\n): Promise<unknown> => {\n if (!s.running) {\n return rejectedSend({ fate: \"aborted\", cause: \"unmount\" });\n }\n if (isFinished(s)) {\n return rejectedSend({ fate: \"aborted\", cause: \"stream-gone\" });\n }\n const seq = s.record.nextSeq;\n s.record = { ...s.record, nextSeq: seq + 1 };\n s.store.save(s.record);\n const entry: Pending = {\n seq,\n command,\n inv: {\n method: command.method,\n params: command.params,\n ts: Date.now(),\n seq,\n clientId: s.record.clientId,\n },\n state: { at: \"queued\", pendingMarked: false },\n resolve: () => {},\n reject: () => {},\n };\n const result = new Promise<unknown>((resolve, reject) => {\n entry.resolve = resolve;\n entry.reject = reject;\n });\n result.catch(() => {});\n s.pending.push(entry);\n s.lifecycle?.onStart(entry.inv);\n void pump(s);\n return result;\n};\n\nexport {\n createSession,\n handleSnapshot,\n handleFinish,\n handleOps,\n setTransport,\n start,\n stop,\n};\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ //#region src/client/sessionStore.d.ts
2
+ type StatewireSessionRecord = {
3
+ clientId: string;
4
+ nextSeq: number;
5
+ };
6
+ type StatewireSessionStore = {
7
+ load: () => StatewireSessionRecord | null;
8
+ save: (record: StatewireSessionRecord) => void;
9
+ };
10
+ type StatewireSessionStoreOptions = {
11
+ sessionStore?: StatewireSessionStore;
12
+ };
13
+ declare const createMemorySessionStore: () => StatewireSessionStore;
14
+ //#endregion
15
+ export { StatewireSessionRecord, StatewireSessionStore, StatewireSessionStoreOptions, createMemorySessionStore };
16
+ //# sourceMappingURL=sessionStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionStore.d.ts","names":[],"sources":["../../src/client/sessionStore.ts"],"mappings":";KAAY;EACV;EACA;;KAGU;EACV,YAAY;EACZ,OAAO,QAAQ;;KAGL;EACV,eAAe;;cAGJ,gCAA+B"}
@@ -0,0 +1,14 @@
1
+ //#region src/client/sessionStore.ts
2
+ const createMemorySessionStore = () => {
3
+ let record = null;
4
+ return {
5
+ load: () => record,
6
+ save: (next) => {
7
+ record = next;
8
+ }
9
+ };
10
+ };
11
+ //#endregion
12
+ export { createMemorySessionStore };
13
+
14
+ //# sourceMappingURL=sessionStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionStore.js","names":["StatewireSessionRecord","clientId","nextSeq","StatewireSessionStore","load","save","record","StatewireSessionStoreOptions","sessionStore","createMemorySessionStore","next"],"sources":["../../src/client/sessionStore.ts"],"sourcesContent":["export type StatewireSessionRecord = {\n clientId: string;\n nextSeq: number;\n};\n\nexport type StatewireSessionStore = {\n load: () => StatewireSessionRecord | null;\n save: (record: StatewireSessionRecord) => void;\n};\n\nexport type StatewireSessionStoreOptions = {\n sessionStore?: StatewireSessionStore;\n};\n\nexport const createMemorySessionStore = (): StatewireSessionStore => {\n let record: StatewireSessionRecord | null = null;\n return {\n load: () => record,\n save: (next) => {\n record = next;\n },\n };\n};\n"],"mappings":";AAcA,MAAaS,iCAAwD;CACnE,IAAIH,SAAwC;CAC5C,OAAO;EACLF,YAAYE;EACZD,OAAOK,SAAS;GACdJ,SAASI;EACX;CACF;AACF"}
@@ -0,0 +1,10 @@
1
+ //#region src/client/timing.d.ts
2
+ declare const timing: {
3
+ backoffBaseMs: number;
4
+ backoffMaxMs: number;
5
+ heartbeatTimeoutMs: number;
6
+ };
7
+ declare const backoff: (attempt: number) => number;
8
+ //#endregion
9
+ export { backoff, timing };
10
+ //# sourceMappingURL=timing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.d.ts","names":[],"sources":["../../src/client/timing.ts"],"mappings":";cAAa;;;;;cAMA,UAAW"}
@@ -0,0 +1,11 @@
1
+ //#region src/client/timing.ts
2
+ const timing = {
3
+ backoffBaseMs: 250,
4
+ backoffMaxMs: 3e4,
5
+ heartbeatTimeoutMs: 3e4
6
+ };
7
+ const backoff = (attempt) => Math.min(timing.backoffBaseMs * 2 ** (attempt - 1), timing.backoffMaxMs);
8
+ //#endregion
9
+ export { backoff, timing };
10
+
11
+ //# sourceMappingURL=timing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.js","names":["timing","backoffBaseMs","backoffMaxMs","heartbeatTimeoutMs","backoff","attempt","Math","min"],"sources":["../../src/client/timing.ts"],"sourcesContent":["export const timing = {\n backoffBaseMs: 250,\n backoffMaxMs: 30_000,\n heartbeatTimeoutMs: 30_000,\n};\n\nexport const backoff = (attempt: number) =>\n Math.min(timing.backoffBaseMs * 2 ** (attempt - 1), timing.backoffMaxMs);\n"],"mappings":";AAAA,MAAaA,SAAS;CACpBC,eAAe;CACfC,cAAc;CACdC,oBAAoB;AACtB;AAEA,MAAaC,WAAWC,YACtBC,KAAKC,IAAIP,OAAOC,gBAAgB,MAAMI,UAAU,IAAIL,OAAOE,YAAY"}
@@ -0,0 +1,14 @@
1
+ import { StatewireOp, StatewirePath } from "../wire/ops.js";
2
+ //#region src/host/draft.d.ts
3
+ type ServerOp = Exclude<StatewireOp, {
4
+ op: "event";
5
+ }>;
6
+ type DraftHost = {
7
+ root: () => unknown;
8
+ record: (op: ServerOp) => void;
9
+ };
10
+ declare const frozen: (value: unknown) => unknown;
11
+ declare const createStateDraft: <T>(host: DraftHost, path?: StatewirePath) => T;
12
+ //#endregion
13
+ export { DraftHost, ServerOp, createStateDraft, frozen };
14
+ //# sourceMappingURL=draft.d.ts.map