@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,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CRDT Supabase Persistence
|
|
3
|
+
*
|
|
4
|
+
* Handles durable persistence of Yjs document state to the Supabase
|
|
5
|
+
* `crdt_documents` table. This is the long-term storage layer — the
|
|
6
|
+
* "source of truth" that survives device loss, browser data clearing,
|
|
7
|
+
* and cross-device sync.
|
|
8
|
+
*
|
|
9
|
+
* Key behaviors:
|
|
10
|
+
* - {@link persistDocument} — Upserts full Yjs state to Supabase
|
|
11
|
+
* - {@link persistAllDirty} — Persists all active dirty documents
|
|
12
|
+
* - {@link fetchRemoteState} — Fetches latest state for initial load / sync
|
|
13
|
+
* - Binary state is base64-encoded for Supabase REST transport
|
|
14
|
+
* - Skips unchanged documents (compares state vectors)
|
|
15
|
+
* - Updates `lastPersistedAt` in IndexedDB on success
|
|
16
|
+
* - Clears pending updates after successful persist
|
|
17
|
+
*
|
|
18
|
+
* Timing:
|
|
19
|
+
* - Periodic persist: every `persistIntervalMs` (default 30s)
|
|
20
|
+
* - On document close (if dirty and online)
|
|
21
|
+
* - On offline → online reconnection (immediate)
|
|
22
|
+
*
|
|
23
|
+
* @see {@link ./provider.ts} for the timer that triggers periodic persists
|
|
24
|
+
* @see {@link ./store.ts} for IndexedDB operations
|
|
25
|
+
* @see {@link ./config.ts} for timing configuration
|
|
26
|
+
*/
|
|
27
|
+
import * as Y from 'yjs';
|
|
28
|
+
import { supabase } from '../supabase/client';
|
|
29
|
+
import { getDeviceId } from '../deviceId';
|
|
30
|
+
import { debugLog, debugWarn } from '../debug';
|
|
31
|
+
import { getCRDTConfig } from './config';
|
|
32
|
+
import { clearPendingUpdates, saveDocumentState, loadDocumentState } from './store';
|
|
33
|
+
import { getActiveProvider } from './provider';
|
|
34
|
+
// =============================================================================
|
|
35
|
+
// Binary ↔ Base64 Encoding
|
|
36
|
+
// =============================================================================
|
|
37
|
+
/**
|
|
38
|
+
* Encode a `Uint8Array` to a base64 string for Supabase REST transport.
|
|
39
|
+
*/
|
|
40
|
+
function uint8ToBase64(bytes) {
|
|
41
|
+
let binary = '';
|
|
42
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
43
|
+
binary += String.fromCharCode(bytes[i]);
|
|
44
|
+
}
|
|
45
|
+
return btoa(binary);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Decode a base64 string back to a `Uint8Array`.
|
|
49
|
+
*/
|
|
50
|
+
function base64ToUint8(base64) {
|
|
51
|
+
const binary = atob(base64);
|
|
52
|
+
const bytes = new Uint8Array(binary.length);
|
|
53
|
+
for (let i = 0; i < binary.length; i++) {
|
|
54
|
+
bytes[i] = binary.charCodeAt(i);
|
|
55
|
+
}
|
|
56
|
+
return bytes;
|
|
57
|
+
}
|
|
58
|
+
// =============================================================================
|
|
59
|
+
// Supabase Persistence
|
|
60
|
+
// =============================================================================
|
|
61
|
+
/**
|
|
62
|
+
* Persist a Yjs document's full state to Supabase.
|
|
63
|
+
*
|
|
64
|
+
* Performs an upsert: if a row for this `page_id` already exists, it is
|
|
65
|
+
* updated; otherwise a new row is created. The upsert key is `page_id`
|
|
66
|
+
* (unique per user via RLS).
|
|
67
|
+
*
|
|
68
|
+
* On success:
|
|
69
|
+
* - Clears `crdtPendingUpdates` for this document in IndexedDB
|
|
70
|
+
* - Updates `lastPersistedAt` in the local `crdtDocuments` record
|
|
71
|
+
*
|
|
72
|
+
* @param documentId - The document identifier (for logging and IndexedDB updates).
|
|
73
|
+
* @param doc - The Yjs document to persist.
|
|
74
|
+
*
|
|
75
|
+
* @throws {Error} If the Supabase upsert fails.
|
|
76
|
+
*/
|
|
77
|
+
export async function persistDocument(documentId, doc) {
|
|
78
|
+
const config = getCRDTConfig();
|
|
79
|
+
const state = Y.encodeStateAsUpdate(doc);
|
|
80
|
+
const stateVector = Y.encodeStateVector(doc);
|
|
81
|
+
const deviceId = getDeviceId();
|
|
82
|
+
/* Find the pageId from the active provider. */
|
|
83
|
+
const provider = getActiveProvider(documentId);
|
|
84
|
+
if (!provider) {
|
|
85
|
+
debugWarn(`[CRDT] Document ${documentId}: cannot persist — no active provider`);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
debugLog(`[CRDT] Document ${documentId}: persisting to Supabase (${state.byteLength} bytes)`);
|
|
89
|
+
const { error } = await supabase.from(config.supabaseTable).upsert({
|
|
90
|
+
page_id: provider.pageId,
|
|
91
|
+
state: uint8ToBase64(state),
|
|
92
|
+
state_vector: uint8ToBase64(stateVector),
|
|
93
|
+
state_size: state.byteLength,
|
|
94
|
+
device_id: deviceId
|
|
95
|
+
}, { onConflict: 'page_id' });
|
|
96
|
+
if (error) {
|
|
97
|
+
debugWarn(`[CRDT] Document ${documentId}: Supabase persist failed: ${error.message}`);
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
/* Clear pending updates from IndexedDB (now captured in Supabase). */
|
|
101
|
+
const cleared = await clearPendingUpdates(documentId);
|
|
102
|
+
debugLog(`[CRDT] Document ${documentId}: Supabase persist success (cleared ${cleared} pending updates)`);
|
|
103
|
+
/* Update lastPersistedAt in IndexedDB. */
|
|
104
|
+
const localRecord = await loadDocumentState(documentId);
|
|
105
|
+
if (localRecord) {
|
|
106
|
+
localRecord.lastPersistedAt = new Date().toISOString();
|
|
107
|
+
await saveDocumentState(localRecord);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Persist all active dirty documents to Supabase.
|
|
112
|
+
*
|
|
113
|
+
* Iterates all active providers, checks if they are dirty, and persists
|
|
114
|
+
* each one. Errors are caught per-document to avoid one failure blocking others.
|
|
115
|
+
*
|
|
116
|
+
* Useful as a manual "save all" action or for pre-close cleanup.
|
|
117
|
+
*/
|
|
118
|
+
export async function persistAllDirty() {
|
|
119
|
+
/*
|
|
120
|
+
* Dynamic import to avoid circular dependency at module load time.
|
|
121
|
+
* The provider module imports from persistence (this file), so we cannot
|
|
122
|
+
* statically import the provider registry here. Dynamic import breaks the cycle.
|
|
123
|
+
*/
|
|
124
|
+
const { getActiveProviderEntries } = await import('./provider');
|
|
125
|
+
const entries = getActiveProviderEntries();
|
|
126
|
+
let persisted = 0;
|
|
127
|
+
for (const [documentId, provider] of entries) {
|
|
128
|
+
if (!provider.isDirty)
|
|
129
|
+
continue;
|
|
130
|
+
try {
|
|
131
|
+
await persistDocument(documentId, provider.doc);
|
|
132
|
+
persisted++;
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
debugWarn(`[CRDT] persistAllDirty: failed for document ${documentId}:`, e);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
debugLog(`[CRDT] persistAllDirty: persisted ${persisted} documents`);
|
|
139
|
+
}
|
|
140
|
+
// =============================================================================
|
|
141
|
+
// Supabase Fetch
|
|
142
|
+
// =============================================================================
|
|
143
|
+
/**
|
|
144
|
+
* Fetch the latest CRDT document state from Supabase by page ID.
|
|
145
|
+
*
|
|
146
|
+
* Used during `openDocument` when no local state exists and the device is
|
|
147
|
+
* online. Returns the raw Yjs binary state ready to be applied via
|
|
148
|
+
* `Y.applyUpdate(doc, state)`.
|
|
149
|
+
*
|
|
150
|
+
* @param pageId - The page/entity ID to fetch the document for.
|
|
151
|
+
* @returns The Yjs state as a `Uint8Array`, or `null` if no document exists.
|
|
152
|
+
*/
|
|
153
|
+
export async function fetchRemoteState(pageId) {
|
|
154
|
+
const config = getCRDTConfig();
|
|
155
|
+
const { data, error } = await supabase
|
|
156
|
+
.from(config.supabaseTable)
|
|
157
|
+
.select('state')
|
|
158
|
+
.eq('page_id', pageId)
|
|
159
|
+
.maybeSingle();
|
|
160
|
+
if (error) {
|
|
161
|
+
debugWarn(`[CRDT] Failed to fetch remote state for page ${pageId}: ${error.message}`);
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
if (!data?.state) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
const state = base64ToUint8(data.state);
|
|
168
|
+
debugLog(`[CRDT] Fetched remote state for page ${pageId} (${state.byteLength} bytes)`);
|
|
169
|
+
return state;
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=persistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../../src/crdt/persistence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CRDT Document Provider — Per-Document Lifecycle Manager
|
|
3
|
+
*
|
|
4
|
+
* The `CRDTProvider` is the central orchestrator for a single collaborative
|
|
5
|
+
* document. It manages:
|
|
6
|
+
* - Yjs `Y.Doc` creation and state loading (from IndexedDB or Supabase)
|
|
7
|
+
* - Wiring `doc.on('update')` to persistence, broadcast, and crash recovery
|
|
8
|
+
* - Supabase Broadcast channel for real-time update distribution
|
|
9
|
+
* - Periodic Supabase persistence timer
|
|
10
|
+
* - Local IndexedDB full-state saves (debounced)
|
|
11
|
+
* - Document lifecycle (open → edit → close → destroy)
|
|
12
|
+
*
|
|
13
|
+
* Module-level `Map<string, CRDTProvider>` tracks all active providers.
|
|
14
|
+
* Factory functions {@link openDocument} / {@link closeDocument} manage the lifecycle.
|
|
15
|
+
*
|
|
16
|
+
* @see {@link ./channel.ts} for Broadcast channel management
|
|
17
|
+
* @see {@link ./store.ts} for IndexedDB persistence
|
|
18
|
+
* @see {@link ./persistence.ts} for Supabase persistence
|
|
19
|
+
* @see {@link ./awareness.ts} for cursor/presence management
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* import { openDocument, closeDocument } from '@prabhask5/stellar-engine/crdt';
|
|
23
|
+
*
|
|
24
|
+
* const provider = await openDocument('doc-1', 'page-1', { offlineEnabled: true });
|
|
25
|
+
* // provider.doc is a Y.Doc — use with your editor
|
|
26
|
+
* // ...
|
|
27
|
+
* await closeDocument('doc-1');
|
|
28
|
+
*/
|
|
29
|
+
import * as Y from 'yjs';
|
|
30
|
+
import type { CRDTConnectionState, OpenDocumentOptions } from './types';
|
|
31
|
+
/**
|
|
32
|
+
* Public interface for a CRDT document provider.
|
|
33
|
+
*
|
|
34
|
+
* Consumers receive this from {@link openDocument}. All mutable state
|
|
35
|
+
* (timers, channels, pending updates) is hidden in the implementation.
|
|
36
|
+
*/
|
|
37
|
+
export interface CRDTProvider {
|
|
38
|
+
/** The Yjs document instance — use with your editor. */
|
|
39
|
+
readonly doc: Y.Doc;
|
|
40
|
+
/** Unique document identifier. */
|
|
41
|
+
readonly documentId: string;
|
|
42
|
+
/** The page/entity this document belongs to. */
|
|
43
|
+
readonly pageId: string;
|
|
44
|
+
/** Current Broadcast channel connection state. */
|
|
45
|
+
readonly connectionState: CRDTConnectionState;
|
|
46
|
+
/** Whether the document has unsaved changes. */
|
|
47
|
+
readonly isDirty: boolean;
|
|
48
|
+
/** Destroy this provider and release all resources. */
|
|
49
|
+
destroy(): Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Open a collaborative CRDT document.
|
|
53
|
+
*
|
|
54
|
+
* Creates a new `CRDTProvider` for the document, loads its initial state
|
|
55
|
+
* (from IndexedDB or Supabase), wires update handlers, joins the Broadcast
|
|
56
|
+
* channel, and starts the periodic persist timer.
|
|
57
|
+
*
|
|
58
|
+
* **Idempotent:** If the document is already open, returns the existing provider.
|
|
59
|
+
*
|
|
60
|
+
* @param documentId - Unique identifier for the document.
|
|
61
|
+
* @param pageId - The page/entity this document belongs to.
|
|
62
|
+
* @param options - Optional configuration (offline mode, initial presence).
|
|
63
|
+
* @returns The active `CRDTProvider` for this document.
|
|
64
|
+
*
|
|
65
|
+
* @throws {Error} If CRDT is not configured in `initEngine()`.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* const provider = await openDocument('doc-1', 'page-1', {
|
|
69
|
+
* offlineEnabled: true,
|
|
70
|
+
* initialPresence: { name: 'Alice' },
|
|
71
|
+
* });
|
|
72
|
+
* const text = provider.doc.getText('content');
|
|
73
|
+
*/
|
|
74
|
+
export declare function openDocument(documentId: string, pageId: string, options?: OpenDocumentOptions): Promise<CRDTProvider>;
|
|
75
|
+
/**
|
|
76
|
+
* Close a specific CRDT document.
|
|
77
|
+
*
|
|
78
|
+
* Saves final state, persists to Supabase if dirty, leaves the Broadcast
|
|
79
|
+
* channel, and destroys the Y.Doc.
|
|
80
|
+
*
|
|
81
|
+
* @param documentId - The document to close.
|
|
82
|
+
*/
|
|
83
|
+
export declare function closeDocument(documentId: string): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Close all active CRDT documents.
|
|
86
|
+
*
|
|
87
|
+
* Called during sign-out to ensure all documents are properly saved and
|
|
88
|
+
* all channels are cleaned up. Each document is closed in parallel.
|
|
89
|
+
*/
|
|
90
|
+
export declare function closeAllDocuments(): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Get the active provider for a document, if open.
|
|
93
|
+
*
|
|
94
|
+
* @param documentId - The document to look up.
|
|
95
|
+
* @returns The active provider, or `undefined` if not open.
|
|
96
|
+
* @internal
|
|
97
|
+
*/
|
|
98
|
+
export declare function getActiveProvider(documentId: string): CRDTProvider | undefined;
|
|
99
|
+
/**
|
|
100
|
+
* Get all active provider entries for iteration.
|
|
101
|
+
*
|
|
102
|
+
* Used by {@link persistence.ts#persistAllDirty} to iterate and persist
|
|
103
|
+
* all dirty documents. Returns `[documentId, provider]` pairs.
|
|
104
|
+
*
|
|
105
|
+
* @returns Iterator of `[documentId, CRDTProvider]` entries.
|
|
106
|
+
* @internal
|
|
107
|
+
*/
|
|
108
|
+
export declare function getActiveProviderEntries(): IterableIterator<[string, CRDTProvider]>;
|
|
109
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/crdt/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAczB,OAAO,KAAK,EAAE,mBAAmB,EAAsB,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAoB5F;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC;IACpB,kCAAkC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,eAAe,EAAE,mBAAmB,CAAC;IAC9C,gDAAgD;IAChD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uDAAuD;IACvD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AA8eD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,YAAY,CAAC,CAuBvB;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIrE;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQvD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAE9E;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAEnF"}
|