@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.
- package/LICENSE +21 -0
- package/README.md +374 -0
- package/bin/lync.js +2 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +5 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/index.d.ts +11 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +404 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/sync.d.ts +42 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +232 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/client/create.d.ts +10 -0
- package/dist/client/create.d.ts.map +1 -0
- package/dist/client/create.js +50 -0
- package/dist/client/create.js.map +1 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +3 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/testing.d.ts +14 -0
- package/dist/client/testing.d.ts.map +1 -0
- package/dist/client/testing.js +19 -0
- package/dist/client/testing.js.map +1 -0
- package/dist/client/types.d.ts +49 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +39 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +119 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +686 -0
- package/dist/events.js.map +1 -0
- package/dist/file-log.d.ts +25 -0
- package/dist/file-log.d.ts.map +1 -0
- package/dist/file-log.js +97 -0
- package/dist/file-log.js.map +1 -0
- package/dist/idb-log.d.ts +21 -0
- package/dist/idb-log.d.ts.map +1 -0
- package/dist/idb-log.js +114 -0
- package/dist/idb-log.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/indexes/entries.d.ts +6 -0
- package/dist/indexes/entries.d.ts.map +1 -0
- package/dist/indexes/entries.js +7 -0
- package/dist/indexes/entries.js.map +1 -0
- package/dist/indexes/index.d.ts +3 -0
- package/dist/indexes/index.d.ts.map +1 -0
- package/dist/indexes/index.js +3 -0
- package/dist/indexes/index.js.map +1 -0
- package/dist/indexes/memory.d.ts +4 -0
- package/dist/indexes/memory.d.ts.map +1 -0
- package/dist/indexes/memory.js +193 -0
- package/dist/indexes/memory.js.map +1 -0
- package/dist/indexes/types.d.ts +70 -0
- package/dist/indexes/types.d.ts.map +1 -0
- package/dist/indexes/types.js +2 -0
- package/dist/indexes/types.js.map +1 -0
- package/dist/json.d.ts +3 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +15 -0
- package/dist/json.js.map +1 -0
- package/dist/looms.d.ts +25 -0
- package/dist/looms.d.ts.map +1 -0
- package/dist/looms.js +359 -0
- package/dist/looms.js.map +1 -0
- package/dist/memory-log.d.ts +5 -0
- package/dist/memory-log.d.ts.map +1 -0
- package/dist/memory-log.js +7 -0
- package/dist/memory-log.js.map +1 -0
- package/dist/memory.d.ts +4 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +255 -0
- package/dist/memory.js.map +1 -0
- package/dist/profiles/text-story.d.ts +26 -0
- package/dist/profiles/text-story.d.ts.map +1 -0
- package/dist/profiles/text-story.js +55 -0
- package/dist/profiles/text-story.js.map +1 -0
- package/dist/references.d.ts +14 -0
- package/dist/references.d.ts.map +1 -0
- package/dist/references.js +109 -0
- package/dist/references.js.map +1 -0
- package/dist/relay/attach.d.ts +24 -0
- package/dist/relay/attach.d.ts.map +1 -0
- package/dist/relay/attach.js +54 -0
- package/dist/relay/attach.js.map +1 -0
- package/dist/relay/index.d.ts +4 -0
- package/dist/relay/index.d.ts.map +1 -0
- package/dist/relay/index.js +4 -0
- package/dist/relay/index.js.map +1 -0
- package/dist/relay/relay.d.ts +80 -0
- package/dist/relay/relay.d.ts.map +1 -0
- package/dist/relay/relay.js +329 -0
- package/dist/relay/relay.js.map +1 -0
- package/dist/relay/serve.d.ts +18 -0
- package/dist/relay/serve.d.ts.map +1 -0
- package/dist/relay/serve.js +37 -0
- package/dist/relay/serve.js.map +1 -0
- package/dist/sha256.d.ts +2 -0
- package/dist/sha256.d.ts.map +1 -0
- package/dist/sha256.js +84 -0
- package/dist/sha256.js.map +1 -0
- package/dist/store.d.ts +97 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +250 -0
- package/dist/store.js.map +1 -0
- package/dist/sync-protocol.d.ts +80 -0
- package/dist/sync-protocol.d.ts.map +1 -0
- package/dist/sync-protocol.js +135 -0
- package/dist/sync-protocol.js.map +1 -0
- package/dist/synced-store.d.ts +68 -0
- package/dist/synced-store.d.ts.map +1 -0
- package/dist/synced-store.js +340 -0
- package/dist/synced-store.js.map +1 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/uuid.d.ts +9 -0
- package/dist/uuid.d.ts.map +1 -0
- package/dist/uuid.js +25 -0
- package/dist/uuid.js.map +1 -0
- package/dist/views.d.ts +78 -0
- package/dist/views.d.ts.map +1 -0
- package/dist/views.js +192 -0
- package/dist/views.js.map +1 -0
- package/package.json +183 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { EventStore } from "./store.js";
|
|
2
|
+
import { type SyncFrame } from "./sync-protocol.js";
|
|
3
|
+
/**
|
|
4
|
+
* Live sync for an EventStore, built on the dumb line-union protocol.
|
|
5
|
+
*
|
|
6
|
+
* A synced store is an ordinary EventStore: looms and indexes built over it
|
|
7
|
+
* recompute reactively through its existing `subscribe`, whether an event
|
|
8
|
+
* arrived from a local append or a remote peer. The decorator adds exactly
|
|
9
|
+
* two behaviors — local appends are pushed to the relay, and remote lines are
|
|
10
|
+
* ingested through the same `union` path — because immutable events plus
|
|
11
|
+
* union-by-id make redundancy harmless and merge logic unnecessary.
|
|
12
|
+
*
|
|
13
|
+
* The transport is abstract so this is testable without a socket. A
|
|
14
|
+
* browser-and-Node WebSocket transport is provided below with zero
|
|
15
|
+
* dependencies (global `WebSocket`, present in browsers and Node ≥ 21).
|
|
16
|
+
*/
|
|
17
|
+
export type SyncConnectionState = "connecting" | "online" | "offline";
|
|
18
|
+
export interface SyncStatus {
|
|
19
|
+
connection: SyncConnectionState;
|
|
20
|
+
/** Roots that have received their backlog and are live. */
|
|
21
|
+
liveRoots: string[];
|
|
22
|
+
/** Ids that arrived as same-id-different-body conflicts, surfaced never resolved. */
|
|
23
|
+
conflicts: string[];
|
|
24
|
+
/**
|
|
25
|
+
* Every ingest failure, surfaced never swallowed: a remote line the local
|
|
26
|
+
* store could not durably accept (store write threw) or rejected as
|
|
27
|
+
* garbage. A store-write failure also freezes the root's resume cursor so
|
|
28
|
+
* the line is re-fetched on the next resubscribe instead of being skipped.
|
|
29
|
+
*/
|
|
30
|
+
failures: string[];
|
|
31
|
+
}
|
|
32
|
+
export interface SyncTransport {
|
|
33
|
+
send(frame: SyncFrame): void;
|
|
34
|
+
/** Register a frame handler; returns an unsubscribe. */
|
|
35
|
+
onFrame(handler: (frame: SyncFrame) => void): () => void;
|
|
36
|
+
/** Fires on every (re)connection, so callers can re-subscribe. */
|
|
37
|
+
onOpen(handler: () => void): () => void;
|
|
38
|
+
onStateChange(handler: (state: SyncConnectionState) => void): () => void;
|
|
39
|
+
readonly state: SyncConnectionState;
|
|
40
|
+
close(): void;
|
|
41
|
+
}
|
|
42
|
+
export interface SyncedStoreOptions {
|
|
43
|
+
onStatus?: (status: SyncStatus) => void;
|
|
44
|
+
onPresence?: (root: string, data: unknown) => void;
|
|
45
|
+
}
|
|
46
|
+
export interface SyncedStore extends EventStore {
|
|
47
|
+
/** Begin syncing a root: push local backlog, then subscribe from the cursor. */
|
|
48
|
+
syncRoot(rootId: string): void;
|
|
49
|
+
/** Relay an ephemeral presence frame for a root; never stored. */
|
|
50
|
+
presence(root: string, data: unknown): void;
|
|
51
|
+
status(): SyncStatus;
|
|
52
|
+
close(): void;
|
|
53
|
+
}
|
|
54
|
+
export declare function createSyncedStore(inner: EventStore, transport: SyncTransport, options?: SyncedStoreOptions): SyncedStore;
|
|
55
|
+
export interface WebSocketTransportOptions {
|
|
56
|
+
/** Override the WebSocket constructor (e.g. `ws` in Node < 21, or a fake in tests). */
|
|
57
|
+
WebSocketImpl?: typeof WebSocket;
|
|
58
|
+
/** Reconnect backoff in ms. Default 1500. Set 0 to disable auto-reconnect. */
|
|
59
|
+
reconnectMs?: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A reconnecting WebSocket transport. Sends while offline are queued and
|
|
63
|
+
* flushed on connect; a dropped socket schedules a reconnect and the synced
|
|
64
|
+
* store re-subscribes via `onOpen`. Nothing is silently dropped: an unsent
|
|
65
|
+
* frame waits in the queue rather than vanishing.
|
|
66
|
+
*/
|
|
67
|
+
export declare function createWebSocketTransport(url: string, options?: WebSocketTransportOptions): SyncTransport;
|
|
68
|
+
//# sourceMappingURL=synced-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synced-store.d.ts","sourceRoot":"","sources":["../src/synced-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA6B,MAAM,YAAY,CAAC;AAExE,OAAO,EAA4B,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE9E;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEtE,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,mBAAmB,CAAC;IAChC,2DAA2D;IAC3D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,qFAAqF;IACrF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,wDAAwD;IACxD,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACzD,kEAAkE;IAClE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IACxC,aAAa,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACzE,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACxC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5C,MAAM,IAAI,UAAU,CAAC;IACrB,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,aAAa,EACxB,OAAO,GAAE,kBAAuB,GAC/B,WAAW,CA8Nb;AAED,MAAM,WAAW,yBAAyB;IACxC,uFAAuF;IACvF,aAAa,CAAC,EAAE,OAAO,SAAS,CAAC;IACjC,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,yBAA8B,GAAG,aAAa,CAmG5G"}
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { decodeFrame, encodeFrame } from "./sync-protocol.js";
|
|
2
|
+
export function createSyncedStore(inner, transport, options = {}) {
|
|
3
|
+
const syncedRoots = new Set();
|
|
4
|
+
const liveRoots = new Set();
|
|
5
|
+
const cursors = new Map();
|
|
6
|
+
const conflicts = new Set();
|
|
7
|
+
const failures = [];
|
|
8
|
+
// Server log generation per root. A cursor is only meaningful inside the
|
|
9
|
+
// generation that issued it (a failed relay disk write still consumes a
|
|
10
|
+
// seq, so a restarted server's recovered log can sit BEHIND our cursor).
|
|
11
|
+
// On a generation change the cursor resets to 0 and we resubscribe; union
|
|
12
|
+
// makes the re-download duplicate no-ops.
|
|
13
|
+
const generations = new Map();
|
|
14
|
+
// Roots whose cursor is frozen because a union failed (store write threw):
|
|
15
|
+
// the cursor must not advance past the hole, or the line would be skipped
|
|
16
|
+
// forever. Cleared on resync — the resubscribe re-fetches from the frozen
|
|
17
|
+
// cursor and each refetched line advances it again as its union succeeds.
|
|
18
|
+
const stalledRoots = new Set();
|
|
19
|
+
// Outstanding `sub` frames per root: each sub is answered by exactly one
|
|
20
|
+
// `live`, in order. While a generation-reset sub is stacked behind an
|
|
21
|
+
// earlier one (count > 1), cursor advances are suppressed — frames from the
|
|
22
|
+
// superseded sub carry seqs the reset backlog has not re-covered yet, and
|
|
23
|
+
// trusting them would re-poison the freshly reset cursor.
|
|
24
|
+
const pendingLives = new Map();
|
|
25
|
+
let connection = transport.state;
|
|
26
|
+
const emitStatus = () => {
|
|
27
|
+
options.onStatus?.({
|
|
28
|
+
connection,
|
|
29
|
+
liveRoots: [...liveRoots],
|
|
30
|
+
conflicts: [...conflicts],
|
|
31
|
+
failures: [...failures],
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
const pushLine = (root, line) => {
|
|
35
|
+
transport.send({ t: "ev", root, line });
|
|
36
|
+
};
|
|
37
|
+
const ensureSynced = (rootId) => {
|
|
38
|
+
if (syncedRoots.has(rootId))
|
|
39
|
+
return;
|
|
40
|
+
syncedRoots.add(rootId);
|
|
41
|
+
void resync(rootId);
|
|
42
|
+
};
|
|
43
|
+
// Push a locally-added event. If its root isn't synced yet, begin syncing —
|
|
44
|
+
// resync re-pushes the whole local backlog (this event included), so we must
|
|
45
|
+
// not also push it here, or the relay sees it twice.
|
|
46
|
+
const pushAdded = (event) => {
|
|
47
|
+
if (syncedRoots.has(event.root)) {
|
|
48
|
+
pushLine(event.root, event.bytes);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
ensureSynced(event.root);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
async function resync(rootId) {
|
|
55
|
+
if (transport.state !== "online")
|
|
56
|
+
return; // resumes on the next onOpen
|
|
57
|
+
// Push any local events the relay may not have (offline appends included);
|
|
58
|
+
// duplicates are no-ops under union on the server.
|
|
59
|
+
for (const event of await inner.byRoot(rootId)) {
|
|
60
|
+
pushLine(rootId, event.bytes);
|
|
61
|
+
}
|
|
62
|
+
// A frozen cursor thaws here: the sub below re-fetches from it, and each
|
|
63
|
+
// refetched line advances it again as its union succeeds.
|
|
64
|
+
stalledRoots.delete(rootId);
|
|
65
|
+
// A fresh connection: any lives owed by subs on the dead connection will
|
|
66
|
+
// never arrive, so the count restarts at this sub's one.
|
|
67
|
+
pendingLives.set(rootId, 1);
|
|
68
|
+
transport.send({ t: "sub", root: rootId, since: cursors.get(rootId) ?? 0 });
|
|
69
|
+
}
|
|
70
|
+
transport.onOpen(() => {
|
|
71
|
+
for (const rootId of syncedRoots)
|
|
72
|
+
void resync(rootId);
|
|
73
|
+
});
|
|
74
|
+
transport.onStateChange((state) => {
|
|
75
|
+
connection = state;
|
|
76
|
+
if (state !== "online")
|
|
77
|
+
liveRoots.clear();
|
|
78
|
+
emitStatus();
|
|
79
|
+
});
|
|
80
|
+
/**
|
|
81
|
+
* Returns true when the server's generation differs from the one this root's
|
|
82
|
+
* cursor belongs to — in which case the cursor has been reset to 0 and a
|
|
83
|
+
* fresh `sub` from 0 is already on the wire. Frames without gen (old
|
|
84
|
+
* servers) never trigger a reset.
|
|
85
|
+
*/
|
|
86
|
+
const generationChanged = (root, gen) => {
|
|
87
|
+
if (gen === undefined)
|
|
88
|
+
return false;
|
|
89
|
+
const known = generations.get(root);
|
|
90
|
+
if (known === gen)
|
|
91
|
+
return false;
|
|
92
|
+
generations.set(root, gen);
|
|
93
|
+
if (known === undefined)
|
|
94
|
+
return false; // first sighting: adopt
|
|
95
|
+
failures.push(`generation changed for ${root} (${known} -> ${gen}); resyncing from 0`);
|
|
96
|
+
cursors.set(root, 0);
|
|
97
|
+
stalledRoots.delete(root);
|
|
98
|
+
pendingLives.set(root, (pendingLives.get(root) ?? 0) + 1);
|
|
99
|
+
emitStatus();
|
|
100
|
+
transport.send({ t: "sub", root, since: 0 });
|
|
101
|
+
return true;
|
|
102
|
+
};
|
|
103
|
+
const advanceCursor = (root, seq) => {
|
|
104
|
+
if (stalledRoots.has(root))
|
|
105
|
+
return; // frozen behind a failed union
|
|
106
|
+
if ((pendingLives.get(root) ?? 0) > 1)
|
|
107
|
+
return; // a reset-sub's backlog is still owed
|
|
108
|
+
cursors.set(root, Math.max(cursors.get(root) ?? 0, seq));
|
|
109
|
+
};
|
|
110
|
+
async function handleFrame(frame) {
|
|
111
|
+
switch (frame.t) {
|
|
112
|
+
case "ev": {
|
|
113
|
+
// Remote line: ingest through union WITHOUT re-pushing (the relay has
|
|
114
|
+
// already fanned it out). Subscribers fire via the inner store. The
|
|
115
|
+
// union is awaited and inspected BEFORE the cursor advances — a line
|
|
116
|
+
// the local store failed to accept must be re-fetched, never skipped.
|
|
117
|
+
generationChanged(frame.root, frame.gen);
|
|
118
|
+
let outcome;
|
|
119
|
+
try {
|
|
120
|
+
outcome = await inner.union(frame.line);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
// Store write failed: the line is NOT durable locally. Freeze the
|
|
124
|
+
// cursor so the next resubscribe re-fetches it, and scream.
|
|
125
|
+
failures.push(`store failed to ingest a synced line for ${frame.root}: ${String(error)}`);
|
|
126
|
+
stalledRoots.add(frame.root);
|
|
127
|
+
emitStatus();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
switch (outcome.status) {
|
|
131
|
+
case "conflict":
|
|
132
|
+
conflicts.add(outcome.event.body.id);
|
|
133
|
+
emitStatus();
|
|
134
|
+
break;
|
|
135
|
+
case "garbage":
|
|
136
|
+
// Unusable bytes stay unusable on any re-fetch: surfaced loudly,
|
|
137
|
+
// and the cursor may advance past them.
|
|
138
|
+
failures.push(`synced line rejected as garbage for ${frame.root}: ${outcome.reason}`);
|
|
139
|
+
emitStatus();
|
|
140
|
+
break;
|
|
141
|
+
default:
|
|
142
|
+
break; // added / duplicate / buffered: durably in the store's hands
|
|
143
|
+
}
|
|
144
|
+
if (typeof frame.seq === "number")
|
|
145
|
+
advanceCursor(frame.root, frame.seq);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
case "live": {
|
|
149
|
+
// A stale live is not live: either its generation is dead (the
|
|
150
|
+
// resubscribe from 0 is already on the wire) or it answers a sub a
|
|
151
|
+
// generation reset has since superseded. Wait for the real one.
|
|
152
|
+
const changed = generationChanged(frame.root, frame.gen);
|
|
153
|
+
const outstanding = Math.max(0, (pendingLives.get(frame.root) ?? 1) - 1);
|
|
154
|
+
pendingLives.set(frame.root, outstanding);
|
|
155
|
+
if (changed || outstanding > 0)
|
|
156
|
+
return;
|
|
157
|
+
advanceCursor(frame.root, frame.seq);
|
|
158
|
+
liveRoots.add(frame.root);
|
|
159
|
+
emitStatus();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
case "presence": {
|
|
163
|
+
options.onPresence?.(frame.root, frame.data);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
case "err": {
|
|
167
|
+
if (frame.reason === "same-id-conflict" && frame.detail) {
|
|
168
|
+
conflicts.add(frame.detail);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// Every other relay-side failure — persist-failed, conflict-persist-failed,
|
|
172
|
+
// recovered-damaged-tail, line-without-id, unexpected-live-from-client,
|
|
173
|
+
// server-error — is a failure the client must see, never a silent drop.
|
|
174
|
+
// A durability failure on the relay reaches the client's status channel.
|
|
175
|
+
const where = frame.root ? ` for ${frame.root}` : "";
|
|
176
|
+
const detail = frame.detail ? ` (${frame.detail})` : "";
|
|
177
|
+
failures.push(`relay error${where}: ${frame.reason}${detail}`);
|
|
178
|
+
}
|
|
179
|
+
emitStatus();
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
default:
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Frames apply strictly in arrival order: each union is awaited before the
|
|
187
|
+
// next frame is touched, so a slow union can never let a later frame (or a
|
|
188
|
+
// `live` cursor jump) leapfrog a failure. handleFrame never rejects — the
|
|
189
|
+
// catch above is the only throw path and it returns — but the chain guards
|
|
190
|
+
// anyway so one surprise cannot wedge sync forever.
|
|
191
|
+
let frameChain = Promise.resolve();
|
|
192
|
+
transport.onFrame((frame) => {
|
|
193
|
+
frameChain = frameChain.then(() => handleFrame(frame), () => handleFrame(frame));
|
|
194
|
+
});
|
|
195
|
+
return {
|
|
196
|
+
async append(ev) {
|
|
197
|
+
const result = await inner.append(ev);
|
|
198
|
+
if (result.status === "added")
|
|
199
|
+
pushAdded(result.event);
|
|
200
|
+
return result;
|
|
201
|
+
},
|
|
202
|
+
async union(line) {
|
|
203
|
+
const result = await inner.union(line);
|
|
204
|
+
if (result.status === "added")
|
|
205
|
+
pushAdded(result.event);
|
|
206
|
+
return result;
|
|
207
|
+
},
|
|
208
|
+
byId: (id) => inner.byId(id),
|
|
209
|
+
byRoot: (rootId) => {
|
|
210
|
+
ensureSynced(rootId);
|
|
211
|
+
return inner.byRoot(rootId);
|
|
212
|
+
},
|
|
213
|
+
subscribe: (rootId, listener) => {
|
|
214
|
+
ensureSynced(rootId);
|
|
215
|
+
return inner.subscribe(rootId, listener);
|
|
216
|
+
},
|
|
217
|
+
roots: (kind) => inner.roots(kind),
|
|
218
|
+
...(inner.exportRootBytes ? { exportRootBytes: (rootId) => inner.exportRootBytes(rootId) } : {}),
|
|
219
|
+
...(inner.diagnostics ? { diagnostics: () => inner.diagnostics() } : {}),
|
|
220
|
+
syncRoot: ensureSynced,
|
|
221
|
+
presence: (root, data) => transport.send({ t: "presence", root, data }),
|
|
222
|
+
status: () => ({ connection, liveRoots: [...liveRoots], conflicts: [...conflicts], failures: [...failures] }),
|
|
223
|
+
close: () => transport.close(),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* A reconnecting WebSocket transport. Sends while offline are queued and
|
|
228
|
+
* flushed on connect; a dropped socket schedules a reconnect and the synced
|
|
229
|
+
* store re-subscribes via `onOpen`. Nothing is silently dropped: an unsent
|
|
230
|
+
* frame waits in the queue rather than vanishing.
|
|
231
|
+
*/
|
|
232
|
+
export function createWebSocketTransport(url, options = {}) {
|
|
233
|
+
const WS = options.WebSocketImpl ?? globalThis.WebSocket;
|
|
234
|
+
if (!WS) {
|
|
235
|
+
throw new Error("createWebSocketTransport: no WebSocket implementation available; pass options.WebSocketImpl");
|
|
236
|
+
}
|
|
237
|
+
const reconnectMs = options.reconnectMs ?? 1500;
|
|
238
|
+
const frameHandlers = new Set();
|
|
239
|
+
const openHandlers = new Set();
|
|
240
|
+
const stateHandlers = new Set();
|
|
241
|
+
const queue = [];
|
|
242
|
+
let socket;
|
|
243
|
+
let state = "connecting";
|
|
244
|
+
let closed = false;
|
|
245
|
+
let reconnectTimer;
|
|
246
|
+
const setState = (next) => {
|
|
247
|
+
if (state === next)
|
|
248
|
+
return;
|
|
249
|
+
state = next;
|
|
250
|
+
for (const handler of stateHandlers)
|
|
251
|
+
handler(next);
|
|
252
|
+
};
|
|
253
|
+
const connect = () => {
|
|
254
|
+
if (closed)
|
|
255
|
+
return;
|
|
256
|
+
setState("connecting");
|
|
257
|
+
const ws = new WS(url);
|
|
258
|
+
socket = ws;
|
|
259
|
+
ws.addEventListener("open", () => {
|
|
260
|
+
if (socket !== ws)
|
|
261
|
+
return;
|
|
262
|
+
setState("online");
|
|
263
|
+
while (queue.length > 0)
|
|
264
|
+
ws.send(encodeFrame(queue.shift()));
|
|
265
|
+
for (const handler of openHandlers)
|
|
266
|
+
handler();
|
|
267
|
+
});
|
|
268
|
+
ws.addEventListener("message", (event) => {
|
|
269
|
+
if (socket !== ws)
|
|
270
|
+
return;
|
|
271
|
+
const raw = typeof event.data === "string" ? event.data : String(event.data);
|
|
272
|
+
const frame = decodeFrame(raw);
|
|
273
|
+
for (const handler of frameHandlers)
|
|
274
|
+
handler(frame);
|
|
275
|
+
});
|
|
276
|
+
ws.addEventListener("close", () => {
|
|
277
|
+
if (socket !== ws)
|
|
278
|
+
return;
|
|
279
|
+
socket = undefined;
|
|
280
|
+
setState("offline");
|
|
281
|
+
scheduleReconnect();
|
|
282
|
+
});
|
|
283
|
+
ws.addEventListener("error", () => {
|
|
284
|
+
if (socket !== ws)
|
|
285
|
+
return;
|
|
286
|
+
// A failed connection surfaces as a close on most stacks; force it.
|
|
287
|
+
try {
|
|
288
|
+
ws.close();
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
socket = undefined;
|
|
292
|
+
setState("offline");
|
|
293
|
+
scheduleReconnect();
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
};
|
|
297
|
+
const scheduleReconnect = () => {
|
|
298
|
+
if (closed || reconnectMs <= 0 || reconnectTimer)
|
|
299
|
+
return;
|
|
300
|
+
reconnectTimer = setTimeout(() => {
|
|
301
|
+
reconnectTimer = undefined;
|
|
302
|
+
connect();
|
|
303
|
+
}, reconnectMs);
|
|
304
|
+
};
|
|
305
|
+
connect();
|
|
306
|
+
return {
|
|
307
|
+
send(frame) {
|
|
308
|
+
if (socket && state === "online" && socket.readyState === socket.OPEN) {
|
|
309
|
+
socket.send(encodeFrame(frame));
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
queue.push(frame);
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
onFrame(handler) {
|
|
316
|
+
frameHandlers.add(handler);
|
|
317
|
+
return () => frameHandlers.delete(handler);
|
|
318
|
+
},
|
|
319
|
+
onOpen(handler) {
|
|
320
|
+
openHandlers.add(handler);
|
|
321
|
+
return () => openHandlers.delete(handler);
|
|
322
|
+
},
|
|
323
|
+
onStateChange(handler) {
|
|
324
|
+
stateHandlers.add(handler);
|
|
325
|
+
return () => stateHandlers.delete(handler);
|
|
326
|
+
},
|
|
327
|
+
get state() {
|
|
328
|
+
return state;
|
|
329
|
+
},
|
|
330
|
+
close() {
|
|
331
|
+
closed = true;
|
|
332
|
+
if (reconnectTimer)
|
|
333
|
+
clearTimeout(reconnectTimer);
|
|
334
|
+
socket?.close();
|
|
335
|
+
socket = undefined;
|
|
336
|
+
setState("offline");
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
//# sourceMappingURL=synced-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synced-store.js","sourceRoot":"","sources":["../src/synced-store.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export type LoomId = string;
|
|
2
|
+
export type TurnId = string;
|
|
3
|
+
export type IndexId = string;
|
|
4
|
+
export interface LoomInfo<TMeta = unknown> {
|
|
5
|
+
id: LoomId;
|
|
6
|
+
meta?: TMeta;
|
|
7
|
+
createdAt: number;
|
|
8
|
+
}
|
|
9
|
+
export interface Turn<TPayload = unknown, TMeta = unknown> {
|
|
10
|
+
id: TurnId;
|
|
11
|
+
loomId: LoomId;
|
|
12
|
+
parentId: TurnId | null;
|
|
13
|
+
payload: TPayload;
|
|
14
|
+
meta?: TMeta;
|
|
15
|
+
createdAt: number;
|
|
16
|
+
}
|
|
17
|
+
export interface LoomSnapshot<TPayload = unknown, TLoomMeta = unknown, TTurnMeta = unknown> {
|
|
18
|
+
loom: LoomInfo<TLoomMeta>;
|
|
19
|
+
turns: Turn<TPayload, TTurnMeta>[];
|
|
20
|
+
}
|
|
21
|
+
export type LoomReference = {
|
|
22
|
+
v: 1;
|
|
23
|
+
kind: "loom";
|
|
24
|
+
loomId: LoomId;
|
|
25
|
+
} | {
|
|
26
|
+
v: 1;
|
|
27
|
+
kind: "turn";
|
|
28
|
+
loomId: LoomId;
|
|
29
|
+
turnId: TurnId;
|
|
30
|
+
} | {
|
|
31
|
+
v: 1;
|
|
32
|
+
kind: "thread";
|
|
33
|
+
loomId: LoomId;
|
|
34
|
+
turnId: TurnId;
|
|
35
|
+
} | {
|
|
36
|
+
v: 1;
|
|
37
|
+
kind: "index";
|
|
38
|
+
indexId: IndexId;
|
|
39
|
+
};
|
|
40
|
+
export type LoomEvent<TPayload, TLoomMeta, TTurnMeta> = {
|
|
41
|
+
type: "turn-added";
|
|
42
|
+
loomId: LoomId;
|
|
43
|
+
turn: Turn<TPayload, TTurnMeta>;
|
|
44
|
+
} | {
|
|
45
|
+
type: "loom-updated";
|
|
46
|
+
loom: LoomInfo<TLoomMeta>;
|
|
47
|
+
} | {
|
|
48
|
+
type: "sync-state";
|
|
49
|
+
loomId: LoomId;
|
|
50
|
+
online: boolean;
|
|
51
|
+
syncing: boolean;
|
|
52
|
+
};
|
|
53
|
+
export type LoomListener<TPayload, TLoomMeta, TTurnMeta> = (event: LoomEvent<TPayload, TLoomMeta, TTurnMeta>) => void;
|
|
54
|
+
export interface Loom<TPayload = unknown, TLoomMeta = unknown, TTurnMeta = unknown> {
|
|
55
|
+
id: LoomId;
|
|
56
|
+
info(): Promise<LoomInfo<TLoomMeta>>;
|
|
57
|
+
updateMeta(meta: TLoomMeta): Promise<LoomInfo<TLoomMeta>>;
|
|
58
|
+
appendTurn(parentId: TurnId | null, payload: TPayload, meta?: TTurnMeta): Promise<Turn<TPayload, TTurnMeta>>;
|
|
59
|
+
getTurn(turnId: TurnId): Promise<Turn<TPayload, TTurnMeta> | null>;
|
|
60
|
+
hasTurn(turnId: TurnId): Promise<boolean>;
|
|
61
|
+
childrenOf(parentId: TurnId | null): Promise<Turn<TPayload, TTurnMeta>[]>;
|
|
62
|
+
threadTo(turnId: TurnId): Promise<Turn<TPayload, TTurnMeta>[]>;
|
|
63
|
+
leaves(): Promise<Turn<TPayload, TTurnMeta>[]>;
|
|
64
|
+
subscribe(listener: LoomListener<TPayload, TLoomMeta, TTurnMeta>): () => void;
|
|
65
|
+
export(): Promise<LoomSnapshot<TPayload, TLoomMeta, TTurnMeta>>;
|
|
66
|
+
close(): void;
|
|
67
|
+
}
|
|
68
|
+
export interface Looms<TPayload = unknown, TLoomMeta = unknown, TTurnMeta = unknown> {
|
|
69
|
+
create(meta?: TLoomMeta): Promise<LoomInfo<TLoomMeta>>;
|
|
70
|
+
get(loomId: LoomId): Promise<LoomInfo<TLoomMeta> | null>;
|
|
71
|
+
open(loomId: LoomId): Promise<Loom<TPayload, TLoomMeta, TTurnMeta>>;
|
|
72
|
+
import(snapshot: LoomSnapshot<TPayload, TLoomMeta, TTurnMeta>): Promise<LoomInfo<TLoomMeta>>;
|
|
73
|
+
}
|
|
74
|
+
export interface MemoryLoomsOptions {
|
|
75
|
+
createId?: () => string;
|
|
76
|
+
now?: () => number;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/uuid.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UUIDv7 minting for lync writers. FORMAT.md makes UUID ids a writer
|
|
3
|
+
* obligation: generators mint UUIDv7 (time-ordered, unique per generation);
|
|
4
|
+
* importers transcribing pre-existing events may instead derive deterministic
|
|
5
|
+
* UUIDv8 from source identity. Zero dependencies; uses the Web Crypto global
|
|
6
|
+
* available in browsers and Node.
|
|
7
|
+
*/
|
|
8
|
+
export declare function uuidv7(now?: number): string;
|
|
9
|
+
//# sourceMappingURL=uuid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,wBAAgB,MAAM,CAAC,GAAG,GAAE,MAAmB,GAAG,MAAM,CAgBvD"}
|
package/dist/uuid.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UUIDv7 minting for lync writers. FORMAT.md makes UUID ids a writer
|
|
3
|
+
* obligation: generators mint UUIDv7 (time-ordered, unique per generation);
|
|
4
|
+
* importers transcribing pre-existing events may instead derive deterministic
|
|
5
|
+
* UUIDv8 from source identity. Zero dependencies; uses the Web Crypto global
|
|
6
|
+
* available in browsers and Node.
|
|
7
|
+
*/
|
|
8
|
+
export function uuidv7(now = Date.now()) {
|
|
9
|
+
const bytes = new Uint8Array(16);
|
|
10
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
11
|
+
// 48-bit big-endian unix-ms timestamp.
|
|
12
|
+
const ms = BigInt(now);
|
|
13
|
+
bytes[0] = Number((ms >> 40n) & 0xffn);
|
|
14
|
+
bytes[1] = Number((ms >> 32n) & 0xffn);
|
|
15
|
+
bytes[2] = Number((ms >> 24n) & 0xffn);
|
|
16
|
+
bytes[3] = Number((ms >> 16n) & 0xffn);
|
|
17
|
+
bytes[4] = Number((ms >> 8n) & 0xffn);
|
|
18
|
+
bytes[5] = Number(ms & 0xffn);
|
|
19
|
+
// Version 7 in the high nibble of byte 6; RFC 4122 variant in byte 8.
|
|
20
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x70;
|
|
21
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
22
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
23
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=uuid.js.map
|
package/dist/uuid.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.js","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,UAAU,MAAM,CAAC,MAAc,IAAI,CAAC,GAAG,EAAE;IAC7C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACjC,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IACzC,uCAAuC;IACvC,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACvB,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;IACtC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;IAC9B,sEAAsE;IACtE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACpC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACpC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/E,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;AAC7G,CAAC"}
|
package/dist/views.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type LyncEventBody, type LyncLineDiagnostic, type LyncObstacle, type LyncParseResult } from "./events.js";
|
|
2
|
+
export interface LyncViewEvent {
|
|
3
|
+
id: string;
|
|
4
|
+
event: LyncEventBody;
|
|
5
|
+
line: LyncLineDiagnostic;
|
|
6
|
+
payloadSuppressed: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface LyncBranchTreeNode extends LyncViewEvent {
|
|
9
|
+
parents: string[];
|
|
10
|
+
children: string[];
|
|
11
|
+
missingParents: string[];
|
|
12
|
+
conflictedParents: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface LyncBranchTreeView {
|
|
15
|
+
nodes: LyncBranchTreeNode[];
|
|
16
|
+
roots: string[];
|
|
17
|
+
leaves: string[];
|
|
18
|
+
obstacles: LyncObstacle[];
|
|
19
|
+
partial: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface LyncTranscriptEntry extends LyncViewEvent {
|
|
22
|
+
depth: number;
|
|
23
|
+
}
|
|
24
|
+
export interface LyncTranscriptView {
|
|
25
|
+
head: string;
|
|
26
|
+
entries: LyncTranscriptEntry[];
|
|
27
|
+
downsetIds: string[];
|
|
28
|
+
obstacles: LyncObstacle[];
|
|
29
|
+
partial: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface LyncMemoryView {
|
|
32
|
+
events: LyncViewEvent[];
|
|
33
|
+
frontierIds: string[];
|
|
34
|
+
suppressedPayloadIds: string[];
|
|
35
|
+
conflictIds: string[];
|
|
36
|
+
obstacles: LyncObstacle[];
|
|
37
|
+
partial: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface LyncScoreReference {
|
|
40
|
+
annotationId: string;
|
|
41
|
+
value: number;
|
|
42
|
+
author: LyncEventBody["author"];
|
|
43
|
+
at: string;
|
|
44
|
+
basis?: unknown;
|
|
45
|
+
}
|
|
46
|
+
export interface LyncSelectionReference {
|
|
47
|
+
annotationId: string;
|
|
48
|
+
selected: boolean;
|
|
49
|
+
chosen: string[];
|
|
50
|
+
shown: string[];
|
|
51
|
+
author: LyncEventBody["author"];
|
|
52
|
+
at: string;
|
|
53
|
+
basis?: unknown;
|
|
54
|
+
}
|
|
55
|
+
export interface LyncLeaderboardEntry {
|
|
56
|
+
targetId: string;
|
|
57
|
+
event?: LyncViewEvent;
|
|
58
|
+
scoreTotal: number;
|
|
59
|
+
scoreCount: number;
|
|
60
|
+
scoreMean: number | null;
|
|
61
|
+
selectedCount: number;
|
|
62
|
+
selectionCount: number;
|
|
63
|
+
scores: LyncScoreReference[];
|
|
64
|
+
selections: LyncSelectionReference[];
|
|
65
|
+
rank: number;
|
|
66
|
+
}
|
|
67
|
+
export interface LyncLeaderboardView {
|
|
68
|
+
entries: LyncLeaderboardEntry[];
|
|
69
|
+
ignoredAnnotationIds: string[];
|
|
70
|
+
}
|
|
71
|
+
export interface LyncTranscriptOptions {
|
|
72
|
+
chooseParent?: (event: LyncEventBody, candidates: string[]) => string | undefined;
|
|
73
|
+
}
|
|
74
|
+
export declare function lyncBranchTreeView(result: LyncParseResult): LyncBranchTreeView;
|
|
75
|
+
export declare function lyncTranscriptView(result: LyncParseResult, head: string, options?: LyncTranscriptOptions): LyncTranscriptView;
|
|
76
|
+
export declare function lyncMemoryView(result: LyncParseResult): LyncMemoryView;
|
|
77
|
+
export declare function lyncLeaderboardView(result: LyncParseResult): LyncLeaderboardView;
|
|
78
|
+
//# sourceMappingURL=views.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"views.d.ts","sourceRoot":"","sources":["../src/views.ts"],"names":[],"mappings":"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"}
|