@deepfates/lync 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +374 -0
  3. package/bin/lync.js +2 -0
  4. package/dist/cli/bin.d.ts +3 -0
  5. package/dist/cli/bin.d.ts.map +1 -0
  6. package/dist/cli/bin.js +5 -0
  7. package/dist/cli/bin.js.map +1 -0
  8. package/dist/cli/index.d.ts +11 -0
  9. package/dist/cli/index.d.ts.map +1 -0
  10. package/dist/cli/index.js +404 -0
  11. package/dist/cli/index.js.map +1 -0
  12. package/dist/cli/sync.d.ts +42 -0
  13. package/dist/cli/sync.d.ts.map +1 -0
  14. package/dist/cli/sync.js +232 -0
  15. package/dist/cli/sync.js.map +1 -0
  16. package/dist/client/create.d.ts +10 -0
  17. package/dist/client/create.d.ts.map +1 -0
  18. package/dist/client/create.js +50 -0
  19. package/dist/client/create.js.map +1 -0
  20. package/dist/client/index.d.ts +3 -0
  21. package/dist/client/index.d.ts.map +1 -0
  22. package/dist/client/index.js +3 -0
  23. package/dist/client/index.js.map +1 -0
  24. package/dist/client/testing.d.ts +14 -0
  25. package/dist/client/testing.d.ts.map +1 -0
  26. package/dist/client/testing.js +19 -0
  27. package/dist/client/testing.js.map +1 -0
  28. package/dist/client/types.d.ts +49 -0
  29. package/dist/client/types.d.ts.map +1 -0
  30. package/dist/client/types.js +2 -0
  31. package/dist/client/types.js.map +1 -0
  32. package/dist/errors.d.ts +16 -0
  33. package/dist/errors.d.ts.map +1 -0
  34. package/dist/errors.js +39 -0
  35. package/dist/errors.js.map +1 -0
  36. package/dist/events.d.ts +119 -0
  37. package/dist/events.d.ts.map +1 -0
  38. package/dist/events.js +686 -0
  39. package/dist/events.js.map +1 -0
  40. package/dist/file-log.d.ts +25 -0
  41. package/dist/file-log.d.ts.map +1 -0
  42. package/dist/file-log.js +97 -0
  43. package/dist/file-log.js.map +1 -0
  44. package/dist/idb-log.d.ts +21 -0
  45. package/dist/idb-log.d.ts.map +1 -0
  46. package/dist/idb-log.js +114 -0
  47. package/dist/idb-log.js.map +1 -0
  48. package/dist/index.d.ts +9 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +11 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/indexes/entries.d.ts +6 -0
  53. package/dist/indexes/entries.d.ts.map +1 -0
  54. package/dist/indexes/entries.js +7 -0
  55. package/dist/indexes/entries.js.map +1 -0
  56. package/dist/indexes/index.d.ts +3 -0
  57. package/dist/indexes/index.d.ts.map +1 -0
  58. package/dist/indexes/index.js +3 -0
  59. package/dist/indexes/index.js.map +1 -0
  60. package/dist/indexes/memory.d.ts +4 -0
  61. package/dist/indexes/memory.d.ts.map +1 -0
  62. package/dist/indexes/memory.js +193 -0
  63. package/dist/indexes/memory.js.map +1 -0
  64. package/dist/indexes/types.d.ts +70 -0
  65. package/dist/indexes/types.d.ts.map +1 -0
  66. package/dist/indexes/types.js +2 -0
  67. package/dist/indexes/types.js.map +1 -0
  68. package/dist/json.d.ts +3 -0
  69. package/dist/json.d.ts.map +1 -0
  70. package/dist/json.js +15 -0
  71. package/dist/json.js.map +1 -0
  72. package/dist/looms.d.ts +25 -0
  73. package/dist/looms.d.ts.map +1 -0
  74. package/dist/looms.js +359 -0
  75. package/dist/looms.js.map +1 -0
  76. package/dist/memory-log.d.ts +5 -0
  77. package/dist/memory-log.d.ts.map +1 -0
  78. package/dist/memory-log.js +7 -0
  79. package/dist/memory-log.js.map +1 -0
  80. package/dist/memory.d.ts +4 -0
  81. package/dist/memory.d.ts.map +1 -0
  82. package/dist/memory.js +255 -0
  83. package/dist/memory.js.map +1 -0
  84. package/dist/profiles/text-story.d.ts +26 -0
  85. package/dist/profiles/text-story.d.ts.map +1 -0
  86. package/dist/profiles/text-story.js +55 -0
  87. package/dist/profiles/text-story.js.map +1 -0
  88. package/dist/references.d.ts +14 -0
  89. package/dist/references.d.ts.map +1 -0
  90. package/dist/references.js +109 -0
  91. package/dist/references.js.map +1 -0
  92. package/dist/relay/attach.d.ts +24 -0
  93. package/dist/relay/attach.d.ts.map +1 -0
  94. package/dist/relay/attach.js +54 -0
  95. package/dist/relay/attach.js.map +1 -0
  96. package/dist/relay/index.d.ts +4 -0
  97. package/dist/relay/index.d.ts.map +1 -0
  98. package/dist/relay/index.js +4 -0
  99. package/dist/relay/index.js.map +1 -0
  100. package/dist/relay/relay.d.ts +80 -0
  101. package/dist/relay/relay.d.ts.map +1 -0
  102. package/dist/relay/relay.js +329 -0
  103. package/dist/relay/relay.js.map +1 -0
  104. package/dist/relay/serve.d.ts +18 -0
  105. package/dist/relay/serve.d.ts.map +1 -0
  106. package/dist/relay/serve.js +37 -0
  107. package/dist/relay/serve.js.map +1 -0
  108. package/dist/sha256.d.ts +2 -0
  109. package/dist/sha256.d.ts.map +1 -0
  110. package/dist/sha256.js +84 -0
  111. package/dist/sha256.js.map +1 -0
  112. package/dist/store.d.ts +97 -0
  113. package/dist/store.d.ts.map +1 -0
  114. package/dist/store.js +250 -0
  115. package/dist/store.js.map +1 -0
  116. package/dist/sync-protocol.d.ts +80 -0
  117. package/dist/sync-protocol.d.ts.map +1 -0
  118. package/dist/sync-protocol.js +135 -0
  119. package/dist/sync-protocol.js.map +1 -0
  120. package/dist/synced-store.d.ts +68 -0
  121. package/dist/synced-store.d.ts.map +1 -0
  122. package/dist/synced-store.js +340 -0
  123. package/dist/synced-store.js.map +1 -0
  124. package/dist/types.d.ts +78 -0
  125. package/dist/types.d.ts.map +1 -0
  126. package/dist/types.js +2 -0
  127. package/dist/types.js.map +1 -0
  128. package/dist/uuid.d.ts +9 -0
  129. package/dist/uuid.d.ts.map +1 -0
  130. package/dist/uuid.js +25 -0
  131. package/dist/uuid.js.map +1 -0
  132. package/dist/views.d.ts +78 -0
  133. package/dist/views.d.ts.map +1 -0
  134. package/dist/views.js +192 -0
  135. package/dist/views.js.map +1 -0
  136. package/package.json +183 -0
@@ -0,0 +1,97 @@
1
+ import type { LyncEventBody } from "./events.js";
2
+ export interface StoredEvent {
3
+ body: LyncEventBody;
4
+ bytes: string;
5
+ root: string;
6
+ }
7
+ export type AppendResult = {
8
+ status: "added";
9
+ event: StoredEvent;
10
+ } | {
11
+ status: "duplicate";
12
+ event: StoredEvent;
13
+ } | {
14
+ status: "buffered";
15
+ missingParent: string;
16
+ bytes: string;
17
+ } | {
18
+ status: "conflict";
19
+ event: StoredEvent;
20
+ conflictWith: StoredEvent;
21
+ } | {
22
+ status: "garbage";
23
+ reason: string;
24
+ bytes: string;
25
+ };
26
+ export interface EventStore {
27
+ append(ev: LyncEventBody): Promise<AppendResult>;
28
+ union(line: string): Promise<AppendResult>;
29
+ byId(id: string): Promise<StoredEvent | null>;
30
+ byRoot(rootId: string): Promise<StoredEvent[]>;
31
+ subscribe(rootId: string, listener: (ev: StoredEvent) => void): () => void;
32
+ roots(kind?: "lync/loom" | "lync/index"): Promise<StoredEvent[]>;
33
+ exportRootBytes?(rootId: string): Promise<string>;
34
+ diagnostics?(): Promise<EventStoreDiagnostics>;
35
+ }
36
+ export interface EventStoreDiagnostics {
37
+ events: number;
38
+ conflicts: number;
39
+ pending: number;
40
+ garbage: number;
41
+ }
42
+ export interface StoreRecord {
43
+ id: string;
44
+ root: string;
45
+ kind: string;
46
+ at: string;
47
+ bytes: string;
48
+ }
49
+ export interface ConflictRecord {
50
+ id: string;
51
+ digest: string;
52
+ root: string;
53
+ bytes: string;
54
+ }
55
+ export interface PendingRecord {
56
+ missingParent: string;
57
+ digest: string;
58
+ bytes: string;
59
+ }
60
+ export interface GarbageRecord {
61
+ reason: string;
62
+ bytes: string;
63
+ }
64
+ export declare abstract class BaseEventStore implements EventStore {
65
+ protected readonly events: Map<string, StoredEvent>;
66
+ protected readonly conflicts: Map<string, ConflictRecord>;
67
+ protected readonly pending: Map<string, PendingRecord>;
68
+ protected readonly garbage: GarbageRecord[];
69
+ private readonly listeners;
70
+ append(ev: LyncEventBody): Promise<AppendResult>;
71
+ union(line: string): Promise<AppendResult>;
72
+ byId(id: string): Promise<StoredEvent | null>;
73
+ byRoot(rootId: string): Promise<StoredEvent[]>;
74
+ subscribe(rootId: string, listener: (ev: StoredEvent) => void): () => void;
75
+ roots(kind?: "lync/loom" | "lync/index"): Promise<StoredEvent[]>;
76
+ exportRootBytes(rootId: string): Promise<string>;
77
+ diagnostics(): Promise<EventStoreDiagnostics>;
78
+ protected loadRecords(records: {
79
+ events?: StoreRecord[];
80
+ conflicts?: ConflictRecord[];
81
+ pending?: PendingRecord[];
82
+ garbage?: GarbageRecord[];
83
+ }): Promise<void>;
84
+ protected dumpRecords(): {
85
+ events: StoreRecord[];
86
+ conflicts: ConflictRecord[];
87
+ pending: PendingRecord[];
88
+ garbage: GarbageRecord[];
89
+ };
90
+ protected persist(): Promise<void>;
91
+ private ingest;
92
+ private drain;
93
+ private emit;
94
+ private isConflicted;
95
+ }
96
+ export declare function serializeLyncEvent(ev: LyncEventBody): string;
97
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
package/dist/store.js ADDED
@@ -0,0 +1,250 @@
1
+ import { parseLyncFiles } from "./events.js";
2
+ import { sha256Hex } from "./sha256.js";
3
+ export class BaseEventStore {
4
+ events = new Map();
5
+ conflicts = new Map();
6
+ pending = new Map();
7
+ garbage = [];
8
+ listeners = new Map();
9
+ async append(ev) {
10
+ return this.ingest(serializeLyncEvent(ev), false);
11
+ }
12
+ async union(line) {
13
+ return this.ingest(line, true);
14
+ }
15
+ async byId(id) {
16
+ return this.isConflicted(id) ? null : (this.events.get(id) ?? null);
17
+ }
18
+ async byRoot(rootId) {
19
+ return [...this.events.values()]
20
+ .filter((event) => event.root === rootId && !this.isConflicted(event.body.id))
21
+ .sort(compareStored);
22
+ }
23
+ subscribe(rootId, listener) {
24
+ const set = this.listeners.get(rootId) ?? new Set();
25
+ set.add(listener);
26
+ this.listeners.set(rootId, set);
27
+ return () => set.delete(listener);
28
+ }
29
+ async roots(kind) {
30
+ return [...this.events.values()]
31
+ .filter((event) => !this.isConflicted(event.body.id))
32
+ .filter((event) => event.body.id === event.root)
33
+ .filter((event) => event.body.kind === "lync/loom" || event.body.kind === "lync/index")
34
+ .filter((event) => kind === undefined || event.body.kind === kind)
35
+ .sort(compareStored);
36
+ }
37
+ async exportRootBytes(rootId) {
38
+ const events = await this.byRoot(rootId);
39
+ return events.map((event) => event.bytes).join("\n") + (events.length ? "\n" : "");
40
+ }
41
+ async diagnostics() {
42
+ return {
43
+ events: this.events.size,
44
+ conflicts: this.conflicts.size,
45
+ pending: this.pending.size,
46
+ garbage: this.garbage.length,
47
+ };
48
+ }
49
+ async loadRecords(records) {
50
+ for (const record of records.events ?? []) {
51
+ const parsed = parseStoredLine(record.bytes);
52
+ if (parsed.ok)
53
+ this.events.set(parsed.event.body.id, { ...parsed.event, root: record.root });
54
+ }
55
+ for (const record of records.conflicts ?? []) {
56
+ this.conflicts.set(conflictKey(record.id, record.digest), record);
57
+ }
58
+ for (const record of records.pending ?? []) {
59
+ this.pending.set(pendingKey(record.missingParent, record.digest), record);
60
+ }
61
+ this.garbage.push(...(records.garbage ?? []));
62
+ }
63
+ dumpRecords() {
64
+ return {
65
+ events: [...this.events.values()].map((event) => ({
66
+ id: event.body.id,
67
+ root: event.root,
68
+ kind: event.body.kind,
69
+ at: event.body.at,
70
+ bytes: event.bytes,
71
+ })),
72
+ conflicts: [...this.conflicts.values()],
73
+ pending: [...this.pending.values()],
74
+ garbage: [...this.garbage],
75
+ };
76
+ }
77
+ async persist() { }
78
+ async ingest(line, allowBuffer) {
79
+ const parsed = parseStoredLine(line);
80
+ if (!parsed.ok) {
81
+ const result = { status: "garbage", reason: parsed.reason, bytes: line };
82
+ this.garbage.push({ reason: parsed.reason, bytes: line });
83
+ await this.persist();
84
+ return result;
85
+ }
86
+ const body = parsed.event.body;
87
+ const known = validateKnownLyncEvent(body);
88
+ if (known !== null) {
89
+ const result = { status: "garbage", reason: known, bytes: line };
90
+ this.garbage.push({ reason: known, bytes: line });
91
+ await this.persist();
92
+ return result;
93
+ }
94
+ const parent = body.parents[0];
95
+ const root = body.parents.length === 0
96
+ ? body.id
97
+ : this.events.get(parent)?.root;
98
+ if (root === undefined) {
99
+ if (!allowBuffer) {
100
+ const result = { status: "garbage", reason: `missing parent: ${parent}`, bytes: line };
101
+ this.garbage.push({ reason: result.reason, bytes: line });
102
+ await this.persist();
103
+ return result;
104
+ }
105
+ const record = { missingParent: parent, digest: bodyDigest(parsed.bodyBytes), bytes: line };
106
+ this.pending.set(pendingKey(record.missingParent, record.digest), record);
107
+ await this.persist();
108
+ return { status: "buffered", missingParent: parent, bytes: line };
109
+ }
110
+ const event = { ...parsed.event, root };
111
+ const existing = this.events.get(body.id);
112
+ if (existing) {
113
+ if (stripSplice(existing.bytes) === stripSplice(line)) {
114
+ if (isRicherLine(line, existing.bytes)) {
115
+ this.events.set(body.id, event);
116
+ await this.persist();
117
+ }
118
+ return { status: "duplicate", event: this.events.get(body.id) };
119
+ }
120
+ const digest = bodyDigest(parsed.bodyBytes);
121
+ const existingDigest = bodyDigest(new TextEncoder().encode(stripSplice(existing.bytes)));
122
+ this.conflicts.set(conflictKey(existing.body.id, existingDigest), {
123
+ id: existing.body.id,
124
+ digest: existingDigest,
125
+ root: existing.root,
126
+ bytes: existing.bytes,
127
+ });
128
+ this.conflicts.set(conflictKey(body.id, digest), { id: body.id, digest, root, bytes: line });
129
+ await this.persist();
130
+ return { status: "conflict", event, conflictWith: existing };
131
+ }
132
+ this.events.set(body.id, event);
133
+ await this.persist();
134
+ this.emit(event);
135
+ await this.drain(body.id);
136
+ return { status: "added", event };
137
+ }
138
+ async drain(parentId) {
139
+ let progressed = true;
140
+ while (progressed) {
141
+ progressed = false;
142
+ for (const record of [...this.pending.values()].filter((item) => item.missingParent === parentId)) {
143
+ this.pending.delete(pendingKey(record.missingParent, record.digest));
144
+ await this.ingest(record.bytes, true);
145
+ progressed = true;
146
+ }
147
+ }
148
+ }
149
+ emit(event) {
150
+ for (const listener of this.listeners.get(event.root) ?? [])
151
+ listener(event);
152
+ }
153
+ isConflicted(id) {
154
+ for (const conflict of this.conflicts.values())
155
+ if (conflict.id === id)
156
+ return true;
157
+ return false;
158
+ }
159
+ }
160
+ export function serializeLyncEvent(ev) {
161
+ const fields = [
162
+ ["v", ev.v],
163
+ ["id", ev.id],
164
+ ["kind", ev.kind],
165
+ ["at", ev.at],
166
+ ["author", ev.author],
167
+ ["parents", ev.parents],
168
+ ["payload", ev.payload],
169
+ ];
170
+ if (ev.marked !== undefined)
171
+ fields.push(["marked", ev.marked]);
172
+ if (ev.critical !== undefined)
173
+ fields.push(["critical", ev.critical]);
174
+ return `{${fields.map(([key, value]) => `${JSON.stringify(key)}:${JSON.stringify(value)}`).join(",")}}`;
175
+ }
176
+ function parseStoredLine(line) {
177
+ const normalized = line.endsWith("\n") ? line.slice(0, -1) : line;
178
+ const parsed = parseLyncFiles([{ file: "<store>", bytes: `${normalized}\n` }]);
179
+ const diagnostic = parsed.lines[0];
180
+ if (!diagnostic?.event || (diagnostic.class !== "accepted" && diagnostic.class !== "nonconforming")) {
181
+ return { ok: false, reason: diagnostic?.reason ?? "unparseable lync line" };
182
+ }
183
+ return {
184
+ ok: true,
185
+ event: { body: diagnostic.event, bytes: normalized, root: diagnostic.event.id },
186
+ bodyBytes: diagnostic.bodyBytes ?? new TextEncoder().encode(stripSplice(normalized)),
187
+ };
188
+ }
189
+ function validateKnownLyncEvent(body) {
190
+ if (!body.kind.startsWith("lync/"))
191
+ return null;
192
+ if (body.kind === "lync/loom" || body.kind === "lync/index") {
193
+ return body.parents.length === 0 ? null : `${body.kind} must not have parents`;
194
+ }
195
+ if (body.kind === "lync/turn") {
196
+ if (body.parents.length !== 1)
197
+ return "lync/turn must have exactly one parent";
198
+ if (!Number.isInteger(body.payload.ordinal) || body.payload.ordinal < 0) {
199
+ return "lync/turn payload.ordinal must be a non-negative integer";
200
+ }
201
+ if (!("payload" in body.payload))
202
+ return "lync/turn payload.payload is required";
203
+ return null;
204
+ }
205
+ if (body.kind === "lync/loom-meta") {
206
+ if (body.parents.length !== 1)
207
+ return "lync/loom-meta must have exactly one parent";
208
+ if (!("meta" in body.payload))
209
+ return "lync/loom-meta payload.meta is required";
210
+ return null;
211
+ }
212
+ if (body.kind === "lync/index-meta") {
213
+ if (body.parents.length !== 1)
214
+ return "lync/index-meta must have exactly one parent";
215
+ if (!("meta" in body.payload))
216
+ return "lync/index-meta payload.meta is required";
217
+ return null;
218
+ }
219
+ if (body.kind === "lync/index-entry") {
220
+ if (body.parents.length !== 1)
221
+ return "lync/index-entry must have exactly one parent";
222
+ if (typeof body.payload.loomId !== "string")
223
+ return "lync/index-entry payload.loomId is required";
224
+ if ("ordinal" in body.payload && (!Number.isInteger(body.payload.ordinal) || body.payload.ordinal < 0)) {
225
+ return "lync/index-entry payload.ordinal must be a non-negative integer";
226
+ }
227
+ return null;
228
+ }
229
+ return null;
230
+ }
231
+ function compareStored(a, b) {
232
+ return a.body.at.localeCompare(b.body.at) || a.body.id.localeCompare(b.body.id);
233
+ }
234
+ function stripSplice(line) {
235
+ return line.replace(/,"digest":"sha256:[0-9a-f]{64}"(?:,"sig":"[A-Za-z0-9+/]+={0,2}")?}$/, "}");
236
+ }
237
+ function bodyDigest(bytes) {
238
+ return sha256Hex(bytes);
239
+ }
240
+ function conflictKey(id, digest) {
241
+ return `${id}\0${digest}`;
242
+ }
243
+ function pendingKey(missingParent, digest) {
244
+ return `${missingParent}\0${digest}`;
245
+ }
246
+ function isRicherLine(candidate, current) {
247
+ const score = (line) => (line.includes(',"digest"') ? 1 : 0) + (line.includes(',"sig"') ? 1 : 0);
248
+ return score(candidate) > score(current);
249
+ }
250
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The lync line-sync protocol: a dumb event-union relay.
3
+ *
4
+ * Events are immutable and merge is union by id, so the protocol has no
5
+ * merge logic at all — it moves canonical line bytes between peers and lets
6
+ * union make redundancy harmless. Five frame kinds:
7
+ *
8
+ * client → server {"t":"sub", "root": string, "since": number}
9
+ * server → client {"t":"ev", "root": string, "seq": number, "line": string, "gen"?: string}
10
+ * server → client {"t":"live", "root": string, "seq": number, "gen"?: string}
11
+ * client → server {"t":"ev", "root": string, "line": string}
12
+ * either direction {"t":"presence", "root": string, "data"?: unknown}
13
+ * either direction {"t":"err", "root"?: string, "reason": string, "detail"?: string}
14
+ *
15
+ * `seq` is the server's own per-root arrival counter — a resume cursor, not
16
+ * event order. The server echoes accepted events to every subscriber of the
17
+ * root, sender included; echoes are duplicate no-ops under union and still
18
+ * advance the cursor. This module is pure: frame codecs and guards only.
19
+ *
20
+ * `gen` is the server's log GENERATION: a random id minted every time a room
21
+ * is recovered from disk (so every server restart is a new generation). A
22
+ * cursor is only meaningful inside the generation that issued it — a broadcast
23
+ * whose disk write failed still consumes a seq, so after a restart the
24
+ * recovered log can sit BEHIND a client's saved cursor and the client would
25
+ * silently skip the next persisted event forever. A client that sees `gen`
26
+ * change from what its cursor was saved under must reset to 0 and resync from
27
+ * scratch; union makes the re-download a harmless set of duplicate no-ops.
28
+ * The field is additive: frames without it (old servers) decode fine, and old
29
+ * clients ignore it.
30
+ */
31
+ export interface SubFrame {
32
+ t: "sub";
33
+ root: string;
34
+ since: number;
35
+ }
36
+ export interface EvFrame {
37
+ t: "ev";
38
+ root: string;
39
+ line: string;
40
+ seq?: number;
41
+ /** Server log generation (see module doc). Absent from old servers and client→server frames. */
42
+ gen?: string;
43
+ }
44
+ export interface LiveFrame {
45
+ t: "live";
46
+ root: string;
47
+ seq: number;
48
+ /** Server log generation (see module doc). Absent from old servers. */
49
+ gen?: string;
50
+ }
51
+ export interface PresenceFrame {
52
+ t: "presence";
53
+ root: string;
54
+ data?: unknown;
55
+ }
56
+ export interface ErrFrame {
57
+ t: "err";
58
+ root?: string;
59
+ reason: string;
60
+ detail?: string;
61
+ }
62
+ export type SyncFrame = SubFrame | EvFrame | LiveFrame | PresenceFrame | ErrFrame;
63
+ /**
64
+ * A resume cursor / sequence number: a nonnegative integer. Fractional or
65
+ * non-finite values must never pass — they index into backlogs downstream.
66
+ */
67
+ export declare function isCursor(value: unknown): value is number;
68
+ export declare function encodeFrame(frame: SyncFrame): string;
69
+ /**
70
+ * Decode one frame. Returns an ErrFrame (never throws) on anything
71
+ * malformed, so transport code stays loud without try/catch pyramids.
72
+ */
73
+ export declare function decodeFrame(raw: string | Uint8Array): SyncFrame;
74
+ /**
75
+ * Extract the event id from a canonical line without trusting anything else
76
+ * in it. The relay never parses beyond this. Returns undefined when no id
77
+ * can be extracted — callers surface that loudly, never drop it silently.
78
+ */
79
+ export declare function extractLineId(line: string): string | undefined;
80
+ //# sourceMappingURL=sync-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-protocol.d.ts","sourceRoot":"","sources":["../src/sync-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,KAAK,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,CAAC,EAAE,IAAI,CAAC;IACR,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,UAAU,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,KAAK,CAAC;IACT,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,aAAa,GAAG,QAAQ,CAAC;AAIlF;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAsE/D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAU9D"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * The lync line-sync protocol: a dumb event-union relay.
3
+ *
4
+ * Events are immutable and merge is union by id, so the protocol has no
5
+ * merge logic at all — it moves canonical line bytes between peers and lets
6
+ * union make redundancy harmless. Five frame kinds:
7
+ *
8
+ * client → server {"t":"sub", "root": string, "since": number}
9
+ * server → client {"t":"ev", "root": string, "seq": number, "line": string, "gen"?: string}
10
+ * server → client {"t":"live", "root": string, "seq": number, "gen"?: string}
11
+ * client → server {"t":"ev", "root": string, "line": string}
12
+ * either direction {"t":"presence", "root": string, "data"?: unknown}
13
+ * either direction {"t":"err", "root"?: string, "reason": string, "detail"?: string}
14
+ *
15
+ * `seq` is the server's own per-root arrival counter — a resume cursor, not
16
+ * event order. The server echoes accepted events to every subscriber of the
17
+ * root, sender included; echoes are duplicate no-ops under union and still
18
+ * advance the cursor. This module is pure: frame codecs and guards only.
19
+ *
20
+ * `gen` is the server's log GENERATION: a random id minted every time a room
21
+ * is recovered from disk (so every server restart is a new generation). A
22
+ * cursor is only meaningful inside the generation that issued it — a broadcast
23
+ * whose disk write failed still consumes a seq, so after a restart the
24
+ * recovered log can sit BEHIND a client's saved cursor and the client would
25
+ * silently skip the next persisted event forever. A client that sees `gen`
26
+ * change from what its cursor was saved under must reset to 0 and resync from
27
+ * scratch; union makes the re-download a harmless set of duplicate no-ops.
28
+ * The field is additive: frames without it (old servers) decode fine, and old
29
+ * clients ignore it.
30
+ */
31
+ const FRAME_KINDS = new Set(["sub", "ev", "live", "presence", "err"]);
32
+ /**
33
+ * A resume cursor / sequence number: a nonnegative integer. Fractional or
34
+ * non-finite values must never pass — they index into backlogs downstream.
35
+ */
36
+ export function isCursor(value) {
37
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
38
+ }
39
+ export function encodeFrame(frame) {
40
+ return JSON.stringify(frame);
41
+ }
42
+ /**
43
+ * Decode one frame. Returns an ErrFrame (never throws) on anything
44
+ * malformed, so transport code stays loud without try/catch pyramids.
45
+ */
46
+ export function decodeFrame(raw) {
47
+ const text = typeof raw === "string" ? raw : new TextDecoder().decode(raw);
48
+ let value;
49
+ try {
50
+ value = JSON.parse(text);
51
+ }
52
+ catch (error) {
53
+ return { t: "err", reason: "malformed-frame", detail: String(error) };
54
+ }
55
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
56
+ return { t: "err", reason: "malformed-frame", detail: "frame is not an object" };
57
+ }
58
+ const frame = value;
59
+ if (typeof frame.t !== "string" || !FRAME_KINDS.has(frame.t)) {
60
+ return { t: "err", reason: "unknown-frame-kind", detail: String(frame.t) };
61
+ }
62
+ switch (frame.t) {
63
+ case "sub":
64
+ // Cursors are array indices and resume positions: a fractional or
65
+ // non-finite `since` silently skips the backlog downstream (lines[0.5]
66
+ // is undefined), so anything but a nonnegative integer is malformed.
67
+ if (typeof frame.root !== "string" || !isCursor(frame.since)) {
68
+ return { t: "err", reason: "malformed-sub" };
69
+ }
70
+ return { t: "sub", root: frame.root, since: frame.since };
71
+ case "ev":
72
+ if (typeof frame.root !== "string" || typeof frame.line !== "string") {
73
+ return { t: "err", reason: "malformed-ev" };
74
+ }
75
+ if (frame.seq !== undefined && !isCursor(frame.seq)) {
76
+ return { t: "err", reason: "malformed-ev", detail: "seq must be a nonnegative integer" };
77
+ }
78
+ // gen is additive: absence is fine (old peers). Present-but-not-a-string
79
+ // is malformed — a client resetting its cursor over garbage would be
80
+ // acting on noise.
81
+ if (frame.gen !== undefined && typeof frame.gen !== "string") {
82
+ return { t: "err", reason: "malformed-ev", detail: "gen must be a string" };
83
+ }
84
+ return {
85
+ t: "ev",
86
+ root: frame.root,
87
+ line: frame.line,
88
+ ...(frame.seq !== undefined ? { seq: frame.seq } : {}),
89
+ ...(frame.gen !== undefined ? { gen: frame.gen } : {}),
90
+ };
91
+ case "live":
92
+ if (typeof frame.root !== "string" || !isCursor(frame.seq)) {
93
+ return { t: "err", reason: "malformed-live" };
94
+ }
95
+ if (frame.gen !== undefined && typeof frame.gen !== "string") {
96
+ return { t: "err", reason: "malformed-live", detail: "gen must be a string" };
97
+ }
98
+ return {
99
+ t: "live",
100
+ root: frame.root,
101
+ seq: frame.seq,
102
+ ...(frame.gen !== undefined ? { gen: frame.gen } : {}),
103
+ };
104
+ case "presence":
105
+ if (typeof frame.root !== "string") {
106
+ return { t: "err", reason: "malformed-presence" };
107
+ }
108
+ return { t: "presence", root: frame.root, data: frame.data };
109
+ default:
110
+ return {
111
+ t: "err",
112
+ reason: typeof frame.reason === "string" ? frame.reason : "unspecified",
113
+ ...(typeof frame.root === "string" ? { root: frame.root } : {}),
114
+ ...(typeof frame.detail === "string" ? { detail: frame.detail } : {}),
115
+ };
116
+ }
117
+ }
118
+ /**
119
+ * Extract the event id from a canonical line without trusting anything else
120
+ * in it. The relay never parses beyond this. Returns undefined when no id
121
+ * can be extracted — callers surface that loudly, never drop it silently.
122
+ */
123
+ export function extractLineId(line) {
124
+ try {
125
+ const value = JSON.parse(line);
126
+ if (typeof value === "object" && value !== null && typeof value.id === "string") {
127
+ return value.id;
128
+ }
129
+ }
130
+ catch {
131
+ return undefined;
132
+ }
133
+ return undefined;
134
+ }
135
+ //# sourceMappingURL=sync-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-protocol.js","sourceRoot":"","sources":["../src/sync-protocol.ts"],"names":[],"mappings":"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"}