@prabhask5/stellar-engine 1.1.18 → 1.2.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.
- package/README.md +448 -321
- package/dist/bin/commands.d.ts +14 -0
- package/dist/bin/commands.d.ts.map +1 -0
- package/dist/bin/commands.js +68 -0
- package/dist/bin/commands.js.map +1 -0
- package/dist/bin/install-pwa.d.ts +20 -6
- package/dist/bin/install-pwa.d.ts.map +1 -1
- package/dist/bin/install-pwa.js +111 -184
- package/dist/bin/install-pwa.js.map +1 -1
- package/dist/config.d.ts +67 -11
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +265 -24
- package/dist/config.js.map +1 -1
- package/dist/crdt/awareness.d.ts +128 -0
- package/dist/crdt/awareness.d.ts.map +1 -0
- package/dist/crdt/awareness.js +284 -0
- package/dist/crdt/awareness.js.map +1 -0
- package/dist/crdt/channel.d.ts +165 -0
- package/dist/crdt/channel.d.ts.map +1 -0
- package/dist/crdt/channel.js +522 -0
- package/dist/crdt/channel.js.map +1 -0
- package/dist/crdt/config.d.ts +58 -0
- package/dist/crdt/config.d.ts.map +1 -0
- package/dist/crdt/config.js +123 -0
- package/dist/crdt/config.js.map +1 -0
- package/dist/crdt/helpers.d.ts +104 -0
- package/dist/crdt/helpers.d.ts.map +1 -0
- package/dist/crdt/helpers.js +116 -0
- package/dist/crdt/helpers.js.map +1 -0
- package/dist/crdt/offline.d.ts +58 -0
- package/dist/crdt/offline.d.ts.map +1 -0
- package/dist/crdt/offline.js +130 -0
- package/dist/crdt/offline.js.map +1 -0
- package/dist/crdt/persistence.d.ts +65 -0
- package/dist/crdt/persistence.d.ts.map +1 -0
- package/dist/crdt/persistence.js +171 -0
- package/dist/crdt/persistence.js.map +1 -0
- package/dist/crdt/provider.d.ts +109 -0
- package/dist/crdt/provider.d.ts.map +1 -0
- package/dist/crdt/provider.js +543 -0
- package/dist/crdt/provider.js.map +1 -0
- package/dist/crdt/store.d.ts +111 -0
- package/dist/crdt/store.d.ts.map +1 -0
- package/dist/crdt/store.js +158 -0
- package/dist/crdt/store.js.map +1 -0
- package/dist/crdt/types.d.ts +281 -0
- package/dist/crdt/types.d.ts.map +1 -0
- package/dist/crdt/types.js +26 -0
- package/dist/crdt/types.js.map +1 -0
- package/dist/database.d.ts +66 -1
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +133 -7
- package/dist/database.js.map +1 -1
- package/dist/diagnostics.d.ts +75 -0
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +114 -2
- package/dist/diagnostics.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +21 -1
- package/dist/engine.js.map +1 -1
- package/dist/entries/crdt.d.ts +32 -0
- package/dist/entries/crdt.d.ts.map +1 -0
- package/dist/entries/crdt.js +52 -0
- package/dist/entries/crdt.js.map +1 -0
- package/dist/entries/types.d.ts +5 -3
- package/dist/entries/types.d.ts.map +1 -1
- package/dist/entries/utils.d.ts +1 -0
- package/dist/entries/utils.d.ts.map +1 -1
- package/dist/entries/utils.js +8 -0
- package/dist/entries/utils.js.map +1 -1
- package/dist/entries/vite.d.ts +1 -1
- package/dist/entries/vite.d.ts.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/schema.d.ts +150 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +891 -0
- package/dist/schema.js.map +1 -0
- package/dist/sw/build/vite-plugin.d.ts +93 -18
- package/dist/sw/build/vite-plugin.d.ts.map +1 -1
- package/dist/sw/build/vite-plugin.js +356 -22
- package/dist/sw/build/vite-plugin.js.map +1 -1
- package/dist/types.d.ts +139 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -3
- package/dist/operations.d.ts +0 -73
- package/dist/operations.d.ts.map +0 -1
- package/dist/operations.js +0 -227
- package/dist/operations.js.map +0 -1
- package/dist/reconnectHandler.d.ts +0 -16
- package/dist/reconnectHandler.d.ts.map +0 -1
- package/dist/reconnectHandler.js +0 -21
- package/dist/reconnectHandler.js.map +0 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CRDT IndexedDB Persistence Layer
|
|
3
|
+
*
|
|
4
|
+
* Provides CRUD operations for the two CRDT-specific IndexedDB tables:
|
|
5
|
+
* - `crdtDocuments` — Full Yjs document state snapshots
|
|
6
|
+
* - `crdtPendingUpdates` — Incremental Yjs update deltas for crash recovery
|
|
7
|
+
*
|
|
8
|
+
* These tables are conditionally created by {@link ../database.ts#buildDexie}
|
|
9
|
+
* only when `crdt` config is provided to `initEngine()`.
|
|
10
|
+
*
|
|
11
|
+
* This module also exposes offline management query functions:
|
|
12
|
+
* - {@link isOfflineEnabled} — check if a document is stored for offline
|
|
13
|
+
* - {@link getOfflineDocuments} — list all offline-enabled documents
|
|
14
|
+
* - {@link getOfflineDocumentCount} — count for limit enforcement
|
|
15
|
+
*
|
|
16
|
+
* All functions access Dexie via the engine-managed instance from
|
|
17
|
+
* {@link ../database.ts#getDb}. Binary Yjs state is stored directly as
|
|
18
|
+
* `Uint8Array` — Dexie/IndexedDB handles binary data natively.
|
|
19
|
+
*
|
|
20
|
+
* @see {@link ./types.ts} for record shapes (CRDTDocumentRecord, CRDTPendingUpdate)
|
|
21
|
+
* @see {@link ./provider.ts} for the orchestrator that calls these functions
|
|
22
|
+
* @see {@link ../database.ts} for conditional CRDT table creation
|
|
23
|
+
*/
|
|
24
|
+
import { getDb } from '../database';
|
|
25
|
+
import { debugLog } from '../debug';
|
|
26
|
+
// =============================================================================
|
|
27
|
+
// Document State CRUD
|
|
28
|
+
// =============================================================================
|
|
29
|
+
/**
|
|
30
|
+
* Load a CRDT document record from IndexedDB.
|
|
31
|
+
*
|
|
32
|
+
* @param documentId - The unique document identifier.
|
|
33
|
+
* @returns The document record, or `undefined` if not found.
|
|
34
|
+
*/
|
|
35
|
+
export async function loadDocumentState(documentId) {
|
|
36
|
+
const db = getDb();
|
|
37
|
+
return db.table('crdtDocuments').get(documentId);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Save a full CRDT document state snapshot to IndexedDB.
|
|
41
|
+
*
|
|
42
|
+
* Uses Dexie's `put()` for upsert semantics — creates a new record if the
|
|
43
|
+
* document doesn't exist, or overwrites the existing one.
|
|
44
|
+
*
|
|
45
|
+
* @param record - The full document record to persist.
|
|
46
|
+
*/
|
|
47
|
+
export async function saveDocumentState(record) {
|
|
48
|
+
const db = getDb();
|
|
49
|
+
await db.table('crdtDocuments').put(record);
|
|
50
|
+
debugLog(`[CRDT] Document ${record.documentId}: local save (${record.stateSize} bytes to IndexedDB)`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Delete a CRDT document record from IndexedDB.
|
|
54
|
+
*
|
|
55
|
+
* Also clears all associated pending updates for the document.
|
|
56
|
+
*
|
|
57
|
+
* @param documentId - The document to delete.
|
|
58
|
+
*/
|
|
59
|
+
export async function deleteDocumentState(documentId) {
|
|
60
|
+
const db = getDb();
|
|
61
|
+
await db.table('crdtDocuments').delete(documentId);
|
|
62
|
+
await clearPendingUpdates(documentId);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Load a CRDT document record by page ID.
|
|
66
|
+
*
|
|
67
|
+
* Pages may have at most one CRDT document. Returns the first match.
|
|
68
|
+
*
|
|
69
|
+
* @param pageId - The page/entity ID to look up.
|
|
70
|
+
* @returns The document record, or `undefined` if not found.
|
|
71
|
+
*/
|
|
72
|
+
export async function loadDocumentByPageId(pageId) {
|
|
73
|
+
const db = getDb();
|
|
74
|
+
return db.table('crdtDocuments').where('pageId').equals(pageId).first();
|
|
75
|
+
}
|
|
76
|
+
// =============================================================================
|
|
77
|
+
// Pending Updates (Crash Recovery)
|
|
78
|
+
// =============================================================================
|
|
79
|
+
/**
|
|
80
|
+
* Append an incremental Yjs update to the pending updates table.
|
|
81
|
+
*
|
|
82
|
+
* Called on every `doc.on('update')` event for crash safety. If the browser
|
|
83
|
+
* crashes between full-state saves (every 5s), these deltas can be replayed
|
|
84
|
+
* to recover the document.
|
|
85
|
+
*
|
|
86
|
+
* @param documentId - The document this update belongs to.
|
|
87
|
+
* @param update - The incremental Yjs update delta.
|
|
88
|
+
*/
|
|
89
|
+
export async function appendPendingUpdate(documentId, update) {
|
|
90
|
+
const db = getDb();
|
|
91
|
+
const record = {
|
|
92
|
+
documentId,
|
|
93
|
+
update,
|
|
94
|
+
timestamp: new Date().toISOString()
|
|
95
|
+
};
|
|
96
|
+
await db.table('crdtPendingUpdates').add(record);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Load all pending updates for a specific document, ordered by ID (insertion order).
|
|
100
|
+
*
|
|
101
|
+
* Used during document opening to replay any updates that weren't captured
|
|
102
|
+
* in the last full-state save.
|
|
103
|
+
*
|
|
104
|
+
* @param documentId - The document to load updates for.
|
|
105
|
+
* @returns Array of pending update records, oldest first.
|
|
106
|
+
*/
|
|
107
|
+
export async function loadPendingUpdates(documentId) {
|
|
108
|
+
const db = getDb();
|
|
109
|
+
return db.table('crdtPendingUpdates').where('documentId').equals(documentId).sortBy('id');
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Clear all pending updates for a document.
|
|
113
|
+
*
|
|
114
|
+
* Called after a successful full-state save to IndexedDB or Supabase persist,
|
|
115
|
+
* since the updates have been captured in the full state snapshot.
|
|
116
|
+
*
|
|
117
|
+
* @param documentId - The document to clear updates for.
|
|
118
|
+
* @returns The number of updates cleared.
|
|
119
|
+
*/
|
|
120
|
+
export async function clearPendingUpdates(documentId) {
|
|
121
|
+
const db = getDb();
|
|
122
|
+
return db.table('crdtPendingUpdates').where('documentId').equals(documentId).delete();
|
|
123
|
+
}
|
|
124
|
+
// =============================================================================
|
|
125
|
+
// Offline Management Queries
|
|
126
|
+
// =============================================================================
|
|
127
|
+
/**
|
|
128
|
+
* Check whether a specific document is stored for offline access.
|
|
129
|
+
*
|
|
130
|
+
* @param documentId - The document to check.
|
|
131
|
+
* @returns `true` if the document has `offlineEnabled: 1` in IndexedDB.
|
|
132
|
+
*/
|
|
133
|
+
export async function isOfflineEnabled(documentId) {
|
|
134
|
+
const record = await loadDocumentState(documentId);
|
|
135
|
+
return record?.offlineEnabled === 1;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get all documents that are stored for offline access.
|
|
139
|
+
*
|
|
140
|
+
* @returns Array of document records with `offlineEnabled: 1`.
|
|
141
|
+
*/
|
|
142
|
+
export async function getOfflineDocuments() {
|
|
143
|
+
const db = getDb();
|
|
144
|
+
return db.table('crdtDocuments').where('offlineEnabled').equals(1).toArray();
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Count the number of documents currently stored for offline access.
|
|
148
|
+
*
|
|
149
|
+
* Used by {@link ./offline.ts#enableOffline} to enforce the
|
|
150
|
+
* `maxOfflineDocuments` limit.
|
|
151
|
+
*
|
|
152
|
+
* @returns The number of offline-enabled documents.
|
|
153
|
+
*/
|
|
154
|
+
export async function getOfflineDocumentCount() {
|
|
155
|
+
const db = getDb();
|
|
156
|
+
return db.table('crdtDocuments').where('offlineEnabled').equals(1).count();
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/crdt/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAGpC,gFAAgF;AAChF,uBAAuB;AACvB,gFAAgF;AAEhF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,UAAkB;IAElB,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,OAAO,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAA0B;IAChE,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5C,QAAQ,CACN,mBAAmB,MAAM,CAAC,UAAU,iBAAiB,MAAM,CAAC,SAAS,sBAAsB,CAC5F,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,UAAkB;IAC1D,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACnD,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAc;IAEd,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,OAAO,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC;AAC1E,CAAC;AAED,gFAAgF;AAChF,oCAAoC;AACpC,gFAAgF;AAEhF;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,UAAkB,EAAE,MAAkB;IAC9E,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,MAAM,GAAsB;QAChC,UAAU;QACV,MAAM;QACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IACF,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,UAAkB;IACzD,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,OAAO,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC5F,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,UAAkB;IAC1D,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,OAAO,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,CAAC;AACxF,CAAC;AAED,gFAAgF;AAChF,8BAA8B;AAC9B,gFAAgF;AAEhF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,UAAkB;IACvD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACnD,OAAO,MAAM,EAAE,cAAc,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,OAAO,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;AAC/E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,OAAO,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CRDT Subsystem Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Defines all TypeScript interfaces and types used by the CRDT collaborative
|
|
5
|
+
* editing subsystem. This includes:
|
|
6
|
+
* - {@link CRDTConfig} — configuration passed via `initEngine({ crdt: ... })`
|
|
7
|
+
* - {@link CRDTDocumentRecord} — IndexedDB record shape for persisted CRDT state
|
|
8
|
+
* - {@link CRDTPendingUpdate} — crash-safe incremental update records
|
|
9
|
+
* - {@link UserPresenceState} — per-user cursor/presence state for awareness
|
|
10
|
+
* - {@link OpenDocumentOptions} — options bag for `openDocument()`
|
|
11
|
+
* - {@link BroadcastMessage} — union of all Broadcast channel message types
|
|
12
|
+
*
|
|
13
|
+
* Architecture note:
|
|
14
|
+
* The CRDT subsystem is an optional layer on top of the existing sync engine.
|
|
15
|
+
* It uses Yjs for conflict-free document merging, Supabase Broadcast for
|
|
16
|
+
* real-time update distribution, Supabase Presence for cursor/awareness,
|
|
17
|
+
* and IndexedDB (via Dexie) for local persistence. Consumers never import
|
|
18
|
+
* yjs directly — all Yjs types are re-exported from the engine.
|
|
19
|
+
*
|
|
20
|
+
* @see {@link ./config.ts} for configuration singleton management
|
|
21
|
+
* @see {@link ./provider.ts} for the per-document lifecycle orchestrator
|
|
22
|
+
* @see {@link ./channel.ts} for Broadcast message handling
|
|
23
|
+
* @see {@link ./awareness.ts} for Supabase Presence ↔ Yjs Awareness bridge
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Configuration for the CRDT collaborative editing subsystem.
|
|
27
|
+
*
|
|
28
|
+
* Passed as the `crdt` field of {@link SyncEngineConfig} in `initEngine()`.
|
|
29
|
+
* All fields are optional with sensible defaults. When this config is provided,
|
|
30
|
+
* the engine creates additional IndexedDB tables for CRDT document storage and
|
|
31
|
+
* enables the `@prabhask5/stellar-engine/crdt` API surface.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* initEngine({
|
|
35
|
+
* prefix: 'myapp',
|
|
36
|
+
* tables: [...],
|
|
37
|
+
* database: { name: 'myapp-db', versions: [...] },
|
|
38
|
+
* crdt: {
|
|
39
|
+
* persistIntervalMs: 60000, // Persist to Supabase every 60s
|
|
40
|
+
* maxOfflineDocuments: 100, // Allow up to 100 docs offline
|
|
41
|
+
* },
|
|
42
|
+
* });
|
|
43
|
+
*/
|
|
44
|
+
export interface CRDTConfig {
|
|
45
|
+
/**
|
|
46
|
+
* Supabase table name for CRDT document storage.
|
|
47
|
+
* @default 'crdt_documents'
|
|
48
|
+
*/
|
|
49
|
+
supabaseTable?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Columns to SELECT from Supabase (egress optimization).
|
|
52
|
+
* @default 'id,page_id,state,state_vector,state_size,device_id,updated_at,created_at'
|
|
53
|
+
*/
|
|
54
|
+
columns?: string;
|
|
55
|
+
/**
|
|
56
|
+
* How often to persist dirty documents to Supabase (ms).
|
|
57
|
+
* Lower values reduce data loss risk on crash but increase Supabase writes.
|
|
58
|
+
* @default 30000 (30 seconds)
|
|
59
|
+
*/
|
|
60
|
+
persistIntervalMs?: number;
|
|
61
|
+
/**
|
|
62
|
+
* Broadcast debounce window (ms). Updates within this window are merged
|
|
63
|
+
* via `Y.mergeUpdates()` into a single Broadcast payload.
|
|
64
|
+
* @default 100
|
|
65
|
+
*/
|
|
66
|
+
broadcastDebounceMs?: number;
|
|
67
|
+
/**
|
|
68
|
+
* How long to debounce local IndexedDB full-state saves (ms).
|
|
69
|
+
* Writes full Yjs state to IndexedDB on this interval to ensure recovery
|
|
70
|
+
* from crashes without storing every single keystroke.
|
|
71
|
+
* @default 5000 (5 seconds)
|
|
72
|
+
*/
|
|
73
|
+
localSaveDebounceMs?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Cursor/presence update debounce (ms). Limits the rate at which
|
|
76
|
+
* cursor position changes are broadcast to other users.
|
|
77
|
+
* @default 50
|
|
78
|
+
*/
|
|
79
|
+
cursorDebounceMs?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Maximum number of documents stored locally for offline access.
|
|
82
|
+
* When the limit is reached, `enableOffline()` will reject new documents.
|
|
83
|
+
* @default 50
|
|
84
|
+
*/
|
|
85
|
+
maxOfflineDocuments?: number;
|
|
86
|
+
/**
|
|
87
|
+
* Maximum Broadcast payload size in bytes before chunking.
|
|
88
|
+
* Supabase Broadcast has a ~1MB hard limit; we chunk well below that.
|
|
89
|
+
* @default 250000 (250KB)
|
|
90
|
+
*/
|
|
91
|
+
maxBroadcastPayloadBytes?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Timeout (ms) waiting for peer sync-step-2 responses on reconnect.
|
|
94
|
+
* If no peers respond within this window, falls back to Supabase fetch.
|
|
95
|
+
* @default 3000
|
|
96
|
+
*/
|
|
97
|
+
syncPeerTimeoutMs?: number;
|
|
98
|
+
/**
|
|
99
|
+
* Maximum reconnection attempts for the Broadcast channel.
|
|
100
|
+
* After this many failures, the channel enters a permanent error state
|
|
101
|
+
* and must be manually reconnected.
|
|
102
|
+
* @default 5
|
|
103
|
+
*/
|
|
104
|
+
maxReconnectAttempts?: number;
|
|
105
|
+
/**
|
|
106
|
+
* Base delay (ms) for exponential backoff on channel reconnect.
|
|
107
|
+
* Actual delay: `baseDelay * 2^(attemptNumber - 1)`.
|
|
108
|
+
* @default 1000
|
|
109
|
+
*/
|
|
110
|
+
reconnectBaseDelayMs?: number;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Fully resolved CRDT configuration with all defaults applied.
|
|
114
|
+
*
|
|
115
|
+
* Created by {@link config.ts#_initCRDT} from the user-provided
|
|
116
|
+
* {@link CRDTConfig}. All fields are required (no `undefined` values).
|
|
117
|
+
*
|
|
118
|
+
* @internal
|
|
119
|
+
*/
|
|
120
|
+
export interface ResolvedCRDTConfig {
|
|
121
|
+
supabaseTable: string;
|
|
122
|
+
columns: string;
|
|
123
|
+
persistIntervalMs: number;
|
|
124
|
+
broadcastDebounceMs: number;
|
|
125
|
+
localSaveDebounceMs: number;
|
|
126
|
+
cursorDebounceMs: number;
|
|
127
|
+
maxOfflineDocuments: number;
|
|
128
|
+
maxBroadcastPayloadBytes: number;
|
|
129
|
+
syncPeerTimeoutMs: number;
|
|
130
|
+
maxReconnectAttempts: number;
|
|
131
|
+
reconnectBaseDelayMs: number;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Shape of a record in the `crdtDocuments` IndexedDB table.
|
|
135
|
+
*
|
|
136
|
+
* Stores the full Yjs document state as a binary `Uint8Array`, along with
|
|
137
|
+
* metadata for sync, offline management, and diagnostics.
|
|
138
|
+
*
|
|
139
|
+
* The `offlineEnabled` field uses `0 | 1` instead of `boolean` because
|
|
140
|
+
* Dexie/IndexedDB cannot index boolean fields.
|
|
141
|
+
*/
|
|
142
|
+
export interface CRDTDocumentRecord {
|
|
143
|
+
/** Unique document identifier (primary key). */
|
|
144
|
+
documentId: string;
|
|
145
|
+
/** The page/entity this document belongs to. Indexed for lookups. */
|
|
146
|
+
pageId: string;
|
|
147
|
+
/** Full Yjs document state (`Y.encodeStateAsUpdate(doc)`). */
|
|
148
|
+
state: Uint8Array;
|
|
149
|
+
/** Yjs state vector for delta sync (`Y.encodeStateVector(doc)`). */
|
|
150
|
+
stateVector: Uint8Array;
|
|
151
|
+
/**
|
|
152
|
+
* Whether this document is stored locally for offline access.
|
|
153
|
+
* Uses `0 | 1` because IndexedDB cannot index booleans.
|
|
154
|
+
*/
|
|
155
|
+
offlineEnabled: 0 | 1;
|
|
156
|
+
/** ISO 8601 timestamp of the last local modification. */
|
|
157
|
+
localUpdatedAt: string;
|
|
158
|
+
/** ISO 8601 timestamp of the last successful Supabase write, or `null` if never persisted. */
|
|
159
|
+
lastPersistedAt: string | null;
|
|
160
|
+
/** Byte size of the `state` field, for diagnostics and compaction decisions. */
|
|
161
|
+
stateSize: number;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Shape of a record in the `crdtPendingUpdates` IndexedDB table.
|
|
165
|
+
*
|
|
166
|
+
* Stores incremental Yjs update deltas for crash safety. These are written
|
|
167
|
+
* on every `doc.on('update')` event so that if the browser crashes between
|
|
168
|
+
* full-state saves (every 5s), the pending deltas can be replayed to recover
|
|
169
|
+
* the document to its last known state.
|
|
170
|
+
*
|
|
171
|
+
* Cleared after a successful full-state save to IndexedDB or Supabase persist.
|
|
172
|
+
*/
|
|
173
|
+
export interface CRDTPendingUpdate {
|
|
174
|
+
/** Auto-increment primary key (assigned by IndexedDB). */
|
|
175
|
+
id?: number;
|
|
176
|
+
/** Which document this update belongs to. Indexed for efficient batch queries. */
|
|
177
|
+
documentId: string;
|
|
178
|
+
/** Incremental Yjs update delta (`Uint8Array` from `doc.on('update')`). */
|
|
179
|
+
update: Uint8Array;
|
|
180
|
+
/** ISO 8601 timestamp of when the update was received. */
|
|
181
|
+
timestamp: string;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Per-user presence state broadcast via Supabase Presence and bridged to
|
|
185
|
+
* Yjs Awareness. This is what other users see when collaborating on a document.
|
|
186
|
+
*
|
|
187
|
+
* The `cursor` and `selection` fields are intentionally typed as `unknown`
|
|
188
|
+
* because their shape depends on the editor implementation (Tiptap, Prosemirror,
|
|
189
|
+
* CodeMirror, etc.). The CRDT engine transports them opaquely.
|
|
190
|
+
*/
|
|
191
|
+
export interface UserPresenceState {
|
|
192
|
+
/** Supabase user UUID. */
|
|
193
|
+
userId: string;
|
|
194
|
+
/** Display name (e.g., first name or email). */
|
|
195
|
+
name: string;
|
|
196
|
+
/** Avatar URL, if available. */
|
|
197
|
+
avatarUrl?: string;
|
|
198
|
+
/**
|
|
199
|
+
* Deterministic color assigned from userId hash.
|
|
200
|
+
* Used for cursor color, selection highlight, avatar ring, etc.
|
|
201
|
+
*/
|
|
202
|
+
color: string;
|
|
203
|
+
/** Editor-specific cursor position (opaque to the engine). */
|
|
204
|
+
cursor?: unknown;
|
|
205
|
+
/** Editor-specific selection range (opaque to the engine). */
|
|
206
|
+
selection?: unknown;
|
|
207
|
+
/** Device identifier for multi-tab dedup. */
|
|
208
|
+
deviceId: string;
|
|
209
|
+
/** ISO 8601 timestamp of the user's last activity in this document. */
|
|
210
|
+
lastActiveAt: string;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Options for {@link provider.ts#openDocument}.
|
|
214
|
+
*/
|
|
215
|
+
export interface OpenDocumentOptions {
|
|
216
|
+
/**
|
|
217
|
+
* If `true`, the document will be persisted to IndexedDB for offline access.
|
|
218
|
+
* When `false` or omitted, the document exists only in memory and is lost
|
|
219
|
+
* when the provider is destroyed.
|
|
220
|
+
* @default false
|
|
221
|
+
*/
|
|
222
|
+
offlineEnabled?: boolean;
|
|
223
|
+
/**
|
|
224
|
+
* Initial user presence state to announce when joining the document.
|
|
225
|
+
* If omitted, no presence is announced until `updateCursor()` is called.
|
|
226
|
+
*/
|
|
227
|
+
initialPresence?: {
|
|
228
|
+
name: string;
|
|
229
|
+
avatarUrl?: string;
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Connection state of a CRDT document's Broadcast channel.
|
|
234
|
+
*/
|
|
235
|
+
export type CRDTConnectionState = 'disconnected' | 'connecting' | 'connected';
|
|
236
|
+
/**
|
|
237
|
+
* A CRDT document update distributed via Supabase Broadcast.
|
|
238
|
+
*
|
|
239
|
+
* Contains the merged Yjs update (possibly the result of debouncing multiple
|
|
240
|
+
* rapid edits) encoded as a base64 string for JSON transport.
|
|
241
|
+
*/
|
|
242
|
+
export interface BroadcastUpdateMessage {
|
|
243
|
+
type: 'update';
|
|
244
|
+
data: string;
|
|
245
|
+
deviceId: string;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Sync step 1: sent on channel join to request missing updates from peers.
|
|
249
|
+
* Contains the local state vector so peers can compute the delta.
|
|
250
|
+
*/
|
|
251
|
+
export interface BroadcastSyncStep1Message {
|
|
252
|
+
type: 'sync-step-1';
|
|
253
|
+
stateVector: string;
|
|
254
|
+
deviceId: string;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Sync step 2: response to a sync-step-1 request.
|
|
258
|
+
* Contains the computed delta update for the requester.
|
|
259
|
+
*/
|
|
260
|
+
export interface BroadcastSyncStep2Message {
|
|
261
|
+
type: 'sync-step-2';
|
|
262
|
+
update: string;
|
|
263
|
+
deviceId: string;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* A chunk of a large Broadcast payload that exceeds the max payload size.
|
|
267
|
+
* The receiver reassembles chunks by matching `chunkId` and ordering by `index`.
|
|
268
|
+
*/
|
|
269
|
+
export interface BroadcastChunkMessage {
|
|
270
|
+
type: 'chunk';
|
|
271
|
+
chunkId: string;
|
|
272
|
+
index: number;
|
|
273
|
+
total: number;
|
|
274
|
+
data: string;
|
|
275
|
+
deviceId: string;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Union of all Broadcast message types sent over the CRDT channel.
|
|
279
|
+
*/
|
|
280
|
+
export type BroadcastMessage = BroadcastUpdateMessage | BroadcastSyncStep1Message | BroadcastSyncStep2Message | BroadcastChunkMessage;
|
|
281
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/crdt/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CRDT Subsystem Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Defines all TypeScript interfaces and types used by the CRDT collaborative
|
|
5
|
+
* editing subsystem. This includes:
|
|
6
|
+
* - {@link CRDTConfig} — configuration passed via `initEngine({ crdt: ... })`
|
|
7
|
+
* - {@link CRDTDocumentRecord} — IndexedDB record shape for persisted CRDT state
|
|
8
|
+
* - {@link CRDTPendingUpdate} — crash-safe incremental update records
|
|
9
|
+
* - {@link UserPresenceState} — per-user cursor/presence state for awareness
|
|
10
|
+
* - {@link OpenDocumentOptions} — options bag for `openDocument()`
|
|
11
|
+
* - {@link BroadcastMessage} — union of all Broadcast channel message types
|
|
12
|
+
*
|
|
13
|
+
* Architecture note:
|
|
14
|
+
* The CRDT subsystem is an optional layer on top of the existing sync engine.
|
|
15
|
+
* It uses Yjs for conflict-free document merging, Supabase Broadcast for
|
|
16
|
+
* real-time update distribution, Supabase Presence for cursor/awareness,
|
|
17
|
+
* and IndexedDB (via Dexie) for local persistence. Consumers never import
|
|
18
|
+
* yjs directly — all Yjs types are re-exported from the engine.
|
|
19
|
+
*
|
|
20
|
+
* @see {@link ./config.ts} for configuration singleton management
|
|
21
|
+
* @see {@link ./provider.ts} for the per-document lifecycle orchestrator
|
|
22
|
+
* @see {@link ./channel.ts} for Broadcast message handling
|
|
23
|
+
* @see {@link ./awareness.ts} for Supabase Presence ↔ Yjs Awareness bridge
|
|
24
|
+
*/
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/crdt/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG"}
|
package/dist/database.d.ts
CHANGED
|
@@ -44,6 +44,21 @@ export interface DatabaseConfig {
|
|
|
44
44
|
/** Ordered list of version declarations (each adds or modifies tables). */
|
|
45
45
|
versions: DatabaseVersionConfig[];
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Dexie indexes automatically appended to every app table when using the
|
|
49
|
+
* schema-driven API (`initEngine({ schema: {...} })`).
|
|
50
|
+
*
|
|
51
|
+
* These correspond to the system columns that every synced table has:
|
|
52
|
+
* - `id` — UUID primary key
|
|
53
|
+
* - `user_id` — ownership filter for RLS
|
|
54
|
+
* - `created_at` — creation timestamp
|
|
55
|
+
* - `updated_at` — last modification timestamp (sync cursor)
|
|
56
|
+
* - `deleted` — soft-delete flag
|
|
57
|
+
* - `_version` — optimistic concurrency version counter
|
|
58
|
+
*
|
|
59
|
+
* @see {@link config.ts#generateDatabaseFromSchema} for usage
|
|
60
|
+
*/
|
|
61
|
+
export declare const SYSTEM_INDEXES = "id, user_id, created_at, updated_at, deleted, _version";
|
|
47
62
|
/**
|
|
48
63
|
* Create a Dexie database with system tables auto-merged into every version.
|
|
49
64
|
*
|
|
@@ -62,7 +77,7 @@ export interface DatabaseConfig {
|
|
|
62
77
|
* @param config - Database name and version declarations.
|
|
63
78
|
* @returns The opened Dexie instance, ready for use.
|
|
64
79
|
*/
|
|
65
|
-
export declare function createDatabase(config: DatabaseConfig): Promise<Dexie>;
|
|
80
|
+
export declare function createDatabase(config: DatabaseConfig, crdtEnabled?: boolean): Promise<Dexie>;
|
|
66
81
|
/**
|
|
67
82
|
* Get the engine-managed Dexie instance.
|
|
68
83
|
*
|
|
@@ -80,6 +95,56 @@ export declare function getDb(): Dexie;
|
|
|
80
95
|
* @internal
|
|
81
96
|
*/
|
|
82
97
|
export declare function _setManagedDb(db: Dexie): void;
|
|
98
|
+
/**
|
|
99
|
+
* Result of schema version computation.
|
|
100
|
+
*
|
|
101
|
+
* Contains the resolved version number plus the previous stores schema
|
|
102
|
+
* (if any) so that the caller can declare both versions and give Dexie
|
|
103
|
+
* a proper upgrade path.
|
|
104
|
+
*/
|
|
105
|
+
export interface SchemaVersionResult {
|
|
106
|
+
/** The resolved Dexie version number (positive integer, starts at 1). */
|
|
107
|
+
version: number;
|
|
108
|
+
/**
|
|
109
|
+
* The previous version's store schema, or `null` if this is the first
|
|
110
|
+
* run or no change was detected. When non-null, the caller should declare
|
|
111
|
+
* **both** `previousStores` at `version - 1` and the current stores at
|
|
112
|
+
* `version` so Dexie can perform a non-destructive upgrade.
|
|
113
|
+
*/
|
|
114
|
+
previousStores: Record<string, string> | null;
|
|
115
|
+
/** The previous version number, or `null` if no upgrade is needed. */
|
|
116
|
+
previousVersion: number | null;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Compute a stable Dexie version number from a merged store schema.
|
|
120
|
+
*
|
|
121
|
+
* Uses a localStorage-backed hash comparison to detect schema changes:
|
|
122
|
+
* 1. Compute a deterministic hash of the stringified stores object.
|
|
123
|
+
* 2. Compare to the previously stored hash in localStorage.
|
|
124
|
+
* 3. If changed → increment the stored version, persist both hash and
|
|
125
|
+
* previous stores schema, and return the upgrade info.
|
|
126
|
+
* 4. If unchanged → return the stored version.
|
|
127
|
+
* 5. If first run → return version 1.
|
|
128
|
+
*
|
|
129
|
+
* When a schema change is detected, the previous stores schema is returned
|
|
130
|
+
* so that the caller can declare both versions. This gives Dexie a proper
|
|
131
|
+
* upgrade path (version N → version N+1) instead of requiring a full
|
|
132
|
+
* database rebuild.
|
|
133
|
+
*
|
|
134
|
+
* @param prefix - Application prefix for namespacing localStorage keys.
|
|
135
|
+
* @param mergedStores - The complete Dexie store schema (app + system tables).
|
|
136
|
+
* @returns Version info including previous stores for upgrade path.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* const result = computeSchemaVersion('stellar', {
|
|
140
|
+
* goals: 'id, user_id, goal_list_id, order',
|
|
141
|
+
* });
|
|
142
|
+
* // First run: { version: 1, previousStores: null, previousVersion: null }
|
|
143
|
+
* // On change: { version: 2, previousStores: { goals: '...' }, previousVersion: 1 }
|
|
144
|
+
*
|
|
145
|
+
* @see {@link config.ts#generateDatabaseFromSchema} for the caller
|
|
146
|
+
*/
|
|
147
|
+
export declare function computeSchemaVersion(prefix: string, mergedStores: Record<string, string>): SchemaVersionResult;
|
|
83
148
|
/**
|
|
84
149
|
* Delete the IndexedDB database entirely and clear associated state.
|
|
85
150
|
*
|
package/dist/database.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,sEAAsE;IACtE,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,QAAQ,EAAE,qBAAqB,EAAE,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,sEAAsE;IACtE,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,QAAQ,EAAE,qBAAqB,EAAE,CAAC;CACnC;AAMD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,2DAA2D,CAAC;AAoDvF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,WAAW,UAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAsDhG;AAoCD;;;;;GAKG;AACH,wBAAgB,KAAK,IAAI,KAAK,CAK7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,KAAK,GAAG,IAAI,CAE7C;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAC9C,sEAAsE;IACtE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,mBAAmB,CA+CrB;AAyBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyB5D"}
|