@prabhask5/stellar-engine 1.0.3
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 +295 -0
- package/dist/actions/remoteChange.d.ts +79 -0
- package/dist/actions/remoteChange.d.ts.map +1 -0
- package/dist/actions/remoteChange.js +300 -0
- package/dist/actions/remoteChange.js.map +1 -0
- package/dist/auth/admin.d.ts +12 -0
- package/dist/auth/admin.d.ts.map +1 -0
- package/dist/auth/admin.js +23 -0
- package/dist/auth/admin.js.map +1 -0
- package/dist/auth/offlineCredentials.d.ts +41 -0
- package/dist/auth/offlineCredentials.d.ts.map +1 -0
- package/dist/auth/offlineCredentials.js +121 -0
- package/dist/auth/offlineCredentials.js.map +1 -0
- package/dist/auth/offlineLogin.d.ts +34 -0
- package/dist/auth/offlineLogin.d.ts.map +1 -0
- package/dist/auth/offlineLogin.js +75 -0
- package/dist/auth/offlineLogin.js.map +1 -0
- package/dist/auth/offlineSession.d.ts +22 -0
- package/dist/auth/offlineSession.d.ts.map +1 -0
- package/dist/auth/offlineSession.js +54 -0
- package/dist/auth/offlineSession.js.map +1 -0
- package/dist/auth/resolveAuthState.d.ts +24 -0
- package/dist/auth/resolveAuthState.d.ts.map +1 -0
- package/dist/auth/resolveAuthState.js +69 -0
- package/dist/auth/resolveAuthState.js.map +1 -0
- package/dist/config.d.ts +53 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +55 -0
- package/dist/config.js.map +1 -0
- package/dist/conflicts.d.ts +70 -0
- package/dist/conflicts.d.ts.map +1 -0
- package/dist/conflicts.js +321 -0
- package/dist/conflicts.js.map +1 -0
- package/dist/data.d.ts +77 -0
- package/dist/data.d.ts.map +1 -0
- package/dist/data.js +360 -0
- package/dist/data.js.map +1 -0
- package/dist/database.d.ts +31 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +51 -0
- package/dist/database.js.map +1 -0
- package/dist/debug.d.ts +11 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +48 -0
- package/dist/debug.js.map +1 -0
- package/dist/deviceId.d.ts +16 -0
- package/dist/deviceId.d.ts.map +1 -0
- package/dist/deviceId.js +48 -0
- package/dist/deviceId.js.map +1 -0
- package/dist/engine.d.ts +14 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +1903 -0
- package/dist/engine.js.map +1 -0
- package/dist/entries/actions.d.ts +2 -0
- package/dist/entries/actions.d.ts.map +1 -0
- package/dist/entries/actions.js +3 -0
- package/dist/entries/actions.js.map +1 -0
- package/dist/entries/auth.d.ts +7 -0
- package/dist/entries/auth.d.ts.map +1 -0
- package/dist/entries/auth.js +6 -0
- package/dist/entries/auth.js.map +1 -0
- package/dist/entries/config.d.ts +3 -0
- package/dist/entries/config.d.ts.map +1 -0
- package/dist/entries/config.js +3 -0
- package/dist/entries/config.js.map +1 -0
- package/dist/entries/stores.d.ts +9 -0
- package/dist/entries/stores.d.ts.map +1 -0
- package/dist/entries/stores.js +9 -0
- package/dist/entries/stores.js.map +1 -0
- package/dist/entries/types.d.ts +11 -0
- package/dist/entries/types.d.ts.map +1 -0
- package/dist/entries/types.js +2 -0
- package/dist/entries/types.js.map +1 -0
- package/dist/entries/utils.d.ts +3 -0
- package/dist/entries/utils.d.ts.map +1 -0
- package/dist/entries/utils.js +4 -0
- package/dist/entries/utils.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/operations.d.ts +73 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +227 -0
- package/dist/operations.js.map +1 -0
- package/dist/queue.d.ts +32 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +377 -0
- package/dist/queue.js.map +1 -0
- package/dist/realtime.d.ts +57 -0
- package/dist/realtime.d.ts.map +1 -0
- package/dist/realtime.js +491 -0
- package/dist/realtime.js.map +1 -0
- package/dist/reconnectHandler.d.ts +16 -0
- package/dist/reconnectHandler.d.ts.map +1 -0
- package/dist/reconnectHandler.js +21 -0
- package/dist/reconnectHandler.js.map +1 -0
- package/dist/runtime/runtimeConfig.d.ts +27 -0
- package/dist/runtime/runtimeConfig.d.ts.map +1 -0
- package/dist/runtime/runtimeConfig.js +133 -0
- package/dist/runtime/runtimeConfig.js.map +1 -0
- package/dist/stores/authState.d.ts +57 -0
- package/dist/stores/authState.d.ts.map +1 -0
- package/dist/stores/authState.js +154 -0
- package/dist/stores/authState.js.map +1 -0
- package/dist/stores/network.d.ts +9 -0
- package/dist/stores/network.d.ts.map +1 -0
- package/dist/stores/network.js +97 -0
- package/dist/stores/network.js.map +1 -0
- package/dist/stores/remoteChanges.d.ts +142 -0
- package/dist/stores/remoteChanges.d.ts.map +1 -0
- package/dist/stores/remoteChanges.js +353 -0
- package/dist/stores/remoteChanges.js.map +1 -0
- package/dist/stores/sync.d.ts +35 -0
- package/dist/stores/sync.d.ts.map +1 -0
- package/dist/stores/sync.js +115 -0
- package/dist/stores/sync.js.map +1 -0
- package/dist/supabase/auth.d.ts +60 -0
- package/dist/supabase/auth.d.ts.map +1 -0
- package/dist/supabase/auth.js +298 -0
- package/dist/supabase/auth.js.map +1 -0
- package/dist/supabase/client.d.ts +15 -0
- package/dist/supabase/client.d.ts.map +1 -0
- package/dist/supabase/client.js +149 -0
- package/dist/supabase/client.js.map +1 -0
- package/dist/supabase/validate.d.ts +11 -0
- package/dist/supabase/validate.d.ts.map +1 -0
- package/dist/supabase/validate.js +38 -0
- package/dist/supabase/validate.js.map +1 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +24 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +56 -0
- package/dist/utils.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Real-Time Subscription Manager
|
|
3
|
+
*
|
|
4
|
+
* Phase 5 of multi-device sync: Implements Supabase Realtime subscriptions
|
|
5
|
+
* for instant multi-device synchronization.
|
|
6
|
+
*
|
|
7
|
+
* Design decisions:
|
|
8
|
+
* - Uses Supabase Realtime PostgreSQL Changes for all entity tables
|
|
9
|
+
* - Skips echo (own changes) by comparing device_id in the payload
|
|
10
|
+
* - Tracks recently processed entities to prevent duplicate processing with polling
|
|
11
|
+
* - Applies changes through existing conflict resolution engine
|
|
12
|
+
* - Falls back to polling if WebSocket connection fails (max 5 reconnect attempts)
|
|
13
|
+
* - Single channel per user with filter by user_id for efficiency
|
|
14
|
+
* - Pauses reconnection attempts while offline (waits for online event)
|
|
15
|
+
* - Uses reconnectScheduled flag to prevent duplicate reconnect attempts
|
|
16
|
+
*/
|
|
17
|
+
export type RealtimeConnectionState = 'disconnected' | 'connecting' | 'connected' | 'error';
|
|
18
|
+
/**
|
|
19
|
+
* Subscribe to connection state changes
|
|
20
|
+
*/
|
|
21
|
+
export declare function onConnectionStateChange(callback: (state: RealtimeConnectionState) => void): () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Subscribe to data update notifications (called after local DB is updated)
|
|
24
|
+
*/
|
|
25
|
+
export declare function onRealtimeDataUpdate(callback: (table: string, entityId: string) => void): () => void;
|
|
26
|
+
/**
|
|
27
|
+
* Get current realtime connection state.
|
|
28
|
+
* Used by debug utilities exposed on the window object.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getConnectionState(): RealtimeConnectionState;
|
|
31
|
+
/**
|
|
32
|
+
* Check if an entity was recently processed via realtime
|
|
33
|
+
* Used by engine.ts to prevent duplicate processing during polling
|
|
34
|
+
*/
|
|
35
|
+
export declare function wasRecentlyProcessedByRealtime(entityId: string): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Start realtime subscriptions for a user
|
|
38
|
+
*/
|
|
39
|
+
export declare function startRealtimeSubscriptions(userId: string): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Stop realtime subscriptions (public API)
|
|
42
|
+
*/
|
|
43
|
+
export declare function stopRealtimeSubscriptions(): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Pause realtime (when going offline) - stops reconnection attempts
|
|
46
|
+
* Called by sync engine when offline event fires
|
|
47
|
+
*/
|
|
48
|
+
export declare function pauseRealtime(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Check if realtime is healthy (connected and not in error state)
|
|
51
|
+
*/
|
|
52
|
+
export declare function isRealtimeHealthy(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Clean up expired entries from recently processed tracking
|
|
55
|
+
*/
|
|
56
|
+
export declare function cleanupRealtimeTracking(): void;
|
|
57
|
+
//# sourceMappingURL=realtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAkBH,MAAM,MAAM,uBAAuB,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,CAAC;AAqC5F;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GACjD,MAAM,IAAI,CAKZ;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAClD,MAAM,IAAI,CAGZ;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,uBAAuB,CAE5D;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUxE;AAiUD;;GAEG;AACH,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2G9E;AAED;;GAEG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAiB/D;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAWpC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAO9C"}
|
package/dist/realtime.js
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Real-Time Subscription Manager
|
|
3
|
+
*
|
|
4
|
+
* Phase 5 of multi-device sync: Implements Supabase Realtime subscriptions
|
|
5
|
+
* for instant multi-device synchronization.
|
|
6
|
+
*
|
|
7
|
+
* Design decisions:
|
|
8
|
+
* - Uses Supabase Realtime PostgreSQL Changes for all entity tables
|
|
9
|
+
* - Skips echo (own changes) by comparing device_id in the payload
|
|
10
|
+
* - Tracks recently processed entities to prevent duplicate processing with polling
|
|
11
|
+
* - Applies changes through existing conflict resolution engine
|
|
12
|
+
* - Falls back to polling if WebSocket connection fails (max 5 reconnect attempts)
|
|
13
|
+
* - Single channel per user with filter by user_id for efficiency
|
|
14
|
+
* - Pauses reconnection attempts while offline (waits for online event)
|
|
15
|
+
* - Uses reconnectScheduled flag to prevent duplicate reconnect attempts
|
|
16
|
+
*/
|
|
17
|
+
import { debugLog, debugWarn, debugError } from './debug';
|
|
18
|
+
import { getEngineConfig } from './config';
|
|
19
|
+
import { getDeviceId } from './deviceId';
|
|
20
|
+
import { resolveConflicts, storeConflictHistory, getPendingOpsForEntity } from './conflicts';
|
|
21
|
+
import { getPendingEntityIds } from './queue';
|
|
22
|
+
import { remoteChangesStore } from './stores/remoteChanges';
|
|
23
|
+
// Protection window for recently modified entities (matches engine.ts)
|
|
24
|
+
const RECENTLY_MODIFIED_TTL_MS = 2000;
|
|
25
|
+
// Track entities that realtime has just processed (to prevent duplicate processing with polling)
|
|
26
|
+
// This is separate from engine.ts's recentlyModifiedEntities (which tracks local writes)
|
|
27
|
+
const recentlyProcessedByRealtime = new Map();
|
|
28
|
+
const state = {
|
|
29
|
+
channel: null,
|
|
30
|
+
connectionState: 'disconnected',
|
|
31
|
+
userId: null,
|
|
32
|
+
deviceId: '',
|
|
33
|
+
lastError: null,
|
|
34
|
+
reconnectAttempts: 0,
|
|
35
|
+
reconnectTimeout: null
|
|
36
|
+
};
|
|
37
|
+
// Callbacks for state changes and data updates
|
|
38
|
+
const connectionCallbacks = new Set();
|
|
39
|
+
const dataUpdateCallbacks = new Set();
|
|
40
|
+
// Maximum reconnect attempts before giving up (will fall back to polling)
|
|
41
|
+
const MAX_RECONNECT_ATTEMPTS = 5;
|
|
42
|
+
// Base delay for exponential backoff (ms)
|
|
43
|
+
const RECONNECT_BASE_DELAY = 1000;
|
|
44
|
+
// Lock to prevent concurrent start/stop operations
|
|
45
|
+
let operationInProgress = false;
|
|
46
|
+
// Flag to track if reconnect is already scheduled (prevents duplicate scheduling)
|
|
47
|
+
let reconnectScheduled = false;
|
|
48
|
+
/**
|
|
49
|
+
* Subscribe to connection state changes
|
|
50
|
+
*/
|
|
51
|
+
export function onConnectionStateChange(callback) {
|
|
52
|
+
connectionCallbacks.add(callback);
|
|
53
|
+
// Immediately call with current state
|
|
54
|
+
callback(state.connectionState);
|
|
55
|
+
return () => connectionCallbacks.delete(callback);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Subscribe to data update notifications (called after local DB is updated)
|
|
59
|
+
*/
|
|
60
|
+
export function onRealtimeDataUpdate(callback) {
|
|
61
|
+
dataUpdateCallbacks.add(callback);
|
|
62
|
+
return () => dataUpdateCallbacks.delete(callback);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get current realtime connection state.
|
|
66
|
+
* Used by debug utilities exposed on the window object.
|
|
67
|
+
*/
|
|
68
|
+
export function getConnectionState() {
|
|
69
|
+
return state.connectionState;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if an entity was recently processed via realtime
|
|
73
|
+
* Used by engine.ts to prevent duplicate processing during polling
|
|
74
|
+
*/
|
|
75
|
+
export function wasRecentlyProcessedByRealtime(entityId) {
|
|
76
|
+
const processedAt = recentlyProcessedByRealtime.get(entityId);
|
|
77
|
+
if (!processedAt)
|
|
78
|
+
return false;
|
|
79
|
+
const age = Date.now() - processedAt;
|
|
80
|
+
if (age > RECENTLY_MODIFIED_TTL_MS) {
|
|
81
|
+
recentlyProcessedByRealtime.delete(entityId);
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Update connection state and notify subscribers
|
|
88
|
+
*/
|
|
89
|
+
function setConnectionState(newState, error) {
|
|
90
|
+
state.connectionState = newState;
|
|
91
|
+
state.lastError = error || null;
|
|
92
|
+
for (const callback of connectionCallbacks) {
|
|
93
|
+
try {
|
|
94
|
+
callback(newState);
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
debugError('[Realtime] Connection callback error:', e);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Notify data update subscribers
|
|
103
|
+
*/
|
|
104
|
+
function notifyDataUpdate(table, entityId) {
|
|
105
|
+
debugLog(`[Realtime] Notifying ${dataUpdateCallbacks.size} subscribers of update: ${table}/${entityId}`);
|
|
106
|
+
for (const callback of dataUpdateCallbacks) {
|
|
107
|
+
try {
|
|
108
|
+
callback(table, entityId);
|
|
109
|
+
}
|
|
110
|
+
catch (e) {
|
|
111
|
+
debugError('[Realtime] Data update callback error:', e);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Check if this change came from our own device (skip to prevent echo)
|
|
117
|
+
*/
|
|
118
|
+
function isOwnDeviceChange(record) {
|
|
119
|
+
if (!record)
|
|
120
|
+
return false;
|
|
121
|
+
const recordDeviceId = record.device_id;
|
|
122
|
+
return recordDeviceId === state.deviceId;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Check if entity was recently processed by realtime (prevent duplicate processing)
|
|
126
|
+
*/
|
|
127
|
+
function wasRecentlyProcessed(entityId) {
|
|
128
|
+
const processedAt = recentlyProcessedByRealtime.get(entityId);
|
|
129
|
+
if (!processedAt)
|
|
130
|
+
return false;
|
|
131
|
+
const age = Date.now() - processedAt;
|
|
132
|
+
if (age > RECENTLY_MODIFIED_TTL_MS) {
|
|
133
|
+
recentlyProcessedByRealtime.delete(entityId);
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Handle incoming realtime change
|
|
140
|
+
*/
|
|
141
|
+
async function handleRealtimeChange(table, payload) {
|
|
142
|
+
const eventType = payload.eventType;
|
|
143
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
144
|
+
const newRecord = payload.new;
|
|
145
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
146
|
+
const oldRecord = payload.old;
|
|
147
|
+
// Determine entity ID
|
|
148
|
+
const entityId = (newRecord?.id || oldRecord?.id);
|
|
149
|
+
debugLog(`[Realtime] Received ${eventType} on ${table}:`, entityId);
|
|
150
|
+
if (!entityId) {
|
|
151
|
+
debugWarn('[Realtime] Change without entity ID:', table, eventType);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// Skip if this change came from our own device (prevents echo)
|
|
155
|
+
if (isOwnDeviceChange(newRecord)) {
|
|
156
|
+
debugLog(`[Realtime] Skipping own device change: ${table}/${entityId}`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// Skip if we just processed this entity (prevents rapid duplicate processing)
|
|
160
|
+
if (wasRecentlyProcessed(entityId)) {
|
|
161
|
+
debugLog(`[Realtime] Skipping recently processed: ${table}/${entityId}`);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
debugLog(`[Realtime] Processing remote change: ${eventType} ${table}/${entityId}`);
|
|
165
|
+
const dexieTable = getEngineConfig().tables.find(t => t.supabaseName === table)?.dexieTable;
|
|
166
|
+
if (!dexieTable) {
|
|
167
|
+
debugWarn('[Realtime] Unknown table:', table);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
switch (eventType) {
|
|
172
|
+
case 'INSERT':
|
|
173
|
+
case 'UPDATE': {
|
|
174
|
+
if (!newRecord)
|
|
175
|
+
return;
|
|
176
|
+
// Check if entity is being edited in a manual-save form
|
|
177
|
+
const _isBeingEdited = remoteChangesStore.isEditing(entityId, table);
|
|
178
|
+
// Get local entity if it exists
|
|
179
|
+
const localEntity = await getEngineConfig().db.table(dexieTable).get(entityId);
|
|
180
|
+
// Determine which fields changed
|
|
181
|
+
const changedFields = [];
|
|
182
|
+
if (localEntity && newRecord) {
|
|
183
|
+
for (const key of Object.keys(newRecord)) {
|
|
184
|
+
if (key === 'updated_at' || key === '_version')
|
|
185
|
+
continue;
|
|
186
|
+
if (JSON.stringify(localEntity[key]) !== JSON.stringify(newRecord[key])) {
|
|
187
|
+
changedFields.push(key);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Soft delete: UPDATE with deleted=true is treated as a deletion
|
|
192
|
+
// Play the delete animation BEFORE writing to DB so stores don't filter it out instantly
|
|
193
|
+
const isSoftDelete = newRecord.deleted === true && localEntity && !localEntity.deleted;
|
|
194
|
+
if (isSoftDelete) {
|
|
195
|
+
debugLog(`[Realtime] Soft delete detected for ${table}/${entityId}`);
|
|
196
|
+
// Record delete animation and wait for it to play
|
|
197
|
+
remoteChangesStore.recordRemoteChange(entityId, table, ['*'], true, 'DELETE');
|
|
198
|
+
await remoteChangesStore.markPendingDelete(entityId, table);
|
|
199
|
+
// Now write the soft-deleted record to DB (triggers reactive store refresh)
|
|
200
|
+
await getEngineConfig().db.table(dexieTable).put(newRecord);
|
|
201
|
+
recentlyProcessedByRealtime.set(entityId, Date.now());
|
|
202
|
+
notifyDataUpdate(table, entityId);
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
// Check for pending operations
|
|
206
|
+
const pendingEntityIds = await getPendingEntityIds();
|
|
207
|
+
const hasPendingOps = pendingEntityIds.has(entityId);
|
|
208
|
+
let applied = false;
|
|
209
|
+
if (!localEntity) {
|
|
210
|
+
// New entity - just insert it
|
|
211
|
+
await getEngineConfig().db.table(dexieTable).put(newRecord);
|
|
212
|
+
applied = true;
|
|
213
|
+
}
|
|
214
|
+
else if (!hasPendingOps) {
|
|
215
|
+
// No pending ops - check if remote is newer
|
|
216
|
+
const localUpdatedAt = new Date(localEntity.updated_at).getTime();
|
|
217
|
+
const remoteUpdatedAt = new Date(newRecord.updated_at).getTime();
|
|
218
|
+
if (remoteUpdatedAt > localUpdatedAt) {
|
|
219
|
+
// Remote is newer, accept it
|
|
220
|
+
await getEngineConfig().db.table(dexieTable).put(newRecord);
|
|
221
|
+
applied = true;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
// Has pending operations - use conflict resolution
|
|
226
|
+
const pendingOps = await getPendingOpsForEntity(entityId);
|
|
227
|
+
const resolution = await resolveConflicts(table, entityId, localEntity, newRecord, pendingOps);
|
|
228
|
+
// Store merged entity
|
|
229
|
+
await getEngineConfig().db.table(dexieTable).put(resolution.mergedEntity);
|
|
230
|
+
applied = true;
|
|
231
|
+
// Store conflict history if there were conflicts
|
|
232
|
+
if (resolution.hasConflicts) {
|
|
233
|
+
await storeConflictHistory(resolution);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// Calculate value delta for increment/decrement detection
|
|
237
|
+
let valueDelta;
|
|
238
|
+
if (changedFields.includes('current_value') && localEntity && newRecord) {
|
|
239
|
+
const oldValue = localEntity.current_value || 0;
|
|
240
|
+
const newValue = newRecord.current_value || 0;
|
|
241
|
+
valueDelta = newValue - oldValue;
|
|
242
|
+
}
|
|
243
|
+
// Record the remote change for UI animation
|
|
244
|
+
// If entity is being edited in a form, the change will be deferred
|
|
245
|
+
// We pass the eventType so the store can detect the action type
|
|
246
|
+
if (changedFields.length > 0 || !localEntity) {
|
|
247
|
+
remoteChangesStore.recordRemoteChange(entityId, table, changedFields.length > 0 ? changedFields : ['*'], applied, eventType, valueDelta);
|
|
248
|
+
// Call table-specific onRemoteChange hook if configured
|
|
249
|
+
const tblConfig = getEngineConfig().tables.find(t => t.supabaseName === table);
|
|
250
|
+
if (tblConfig?.onRemoteChange) {
|
|
251
|
+
tblConfig.onRemoteChange(table, newRecord);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Mark as recently processed to prevent duplicate processing by polling
|
|
255
|
+
recentlyProcessedByRealtime.set(entityId, Date.now());
|
|
256
|
+
// Notify subscribers
|
|
257
|
+
notifyDataUpdate(table, entityId);
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
case 'DELETE': {
|
|
261
|
+
// For soft-delete systems, this would be an UPDATE with deleted=true
|
|
262
|
+
// But if hard delete happens, we should remove locally too
|
|
263
|
+
if (oldRecord) {
|
|
264
|
+
// Record the delete for UI animation before removing
|
|
265
|
+
remoteChangesStore.recordRemoteChange(entityId, table, ['*'], true, 'DELETE');
|
|
266
|
+
// Mark as pending delete and wait for animation to complete
|
|
267
|
+
// This allows the UI to play the delete animation before DOM removal
|
|
268
|
+
await remoteChangesStore.markPendingDelete(entityId, table);
|
|
269
|
+
// Now actually delete from database (triggers reactive DOM removal)
|
|
270
|
+
await getEngineConfig().db.table(dexieTable).delete(entityId);
|
|
271
|
+
// Mark as recently processed
|
|
272
|
+
recentlyProcessedByRealtime.set(entityId, Date.now());
|
|
273
|
+
notifyDataUpdate(table, entityId);
|
|
274
|
+
}
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
debugError(`[Realtime] Error handling ${eventType} on ${table}:`, error);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Schedule reconnection with exponential backoff
|
|
285
|
+
* Only schedules if online - no point reconnecting while offline
|
|
286
|
+
*/
|
|
287
|
+
function scheduleReconnect() {
|
|
288
|
+
// Prevent duplicate scheduling from multiple event callbacks
|
|
289
|
+
if (reconnectScheduled) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (state.reconnectTimeout) {
|
|
293
|
+
clearTimeout(state.reconnectTimeout);
|
|
294
|
+
state.reconnectTimeout = null;
|
|
295
|
+
}
|
|
296
|
+
// Don't attempt reconnection while offline - wait for online event
|
|
297
|
+
if (typeof navigator !== 'undefined' && !navigator.onLine) {
|
|
298
|
+
debugLog('[Realtime] Offline - waiting for online event to reconnect');
|
|
299
|
+
setConnectionState('disconnected');
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (state.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
|
303
|
+
debugLog('[Realtime] Max reconnect attempts reached, falling back to polling');
|
|
304
|
+
setConnectionState('error', 'Max reconnection attempts reached');
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
reconnectScheduled = true;
|
|
308
|
+
const delay = RECONNECT_BASE_DELAY * Math.pow(2, state.reconnectAttempts);
|
|
309
|
+
debugLog(`[Realtime] Scheduling reconnect attempt ${state.reconnectAttempts + 1} in ${delay}ms`);
|
|
310
|
+
state.reconnectTimeout = setTimeout(async () => {
|
|
311
|
+
reconnectScheduled = false;
|
|
312
|
+
// Double-check we're still online before attempting
|
|
313
|
+
if (typeof navigator !== 'undefined' && !navigator.onLine) {
|
|
314
|
+
debugLog('[Realtime] Went offline during backoff, cancelling reconnect');
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
state.reconnectAttempts++;
|
|
318
|
+
if (state.userId) {
|
|
319
|
+
await startRealtimeSubscriptions(state.userId);
|
|
320
|
+
}
|
|
321
|
+
}, delay);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Internal stop function (doesn't check operation lock)
|
|
325
|
+
*/
|
|
326
|
+
async function stopRealtimeSubscriptionsInternal() {
|
|
327
|
+
// Clear reconnect timeout and flag
|
|
328
|
+
if (state.reconnectTimeout) {
|
|
329
|
+
clearTimeout(state.reconnectTimeout);
|
|
330
|
+
state.reconnectTimeout = null;
|
|
331
|
+
}
|
|
332
|
+
reconnectScheduled = false;
|
|
333
|
+
// Unsubscribe from channel
|
|
334
|
+
if (state.channel) {
|
|
335
|
+
try {
|
|
336
|
+
await getEngineConfig().supabase.removeChannel(state.channel);
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
debugError('[Realtime] Error removing channel:', error);
|
|
340
|
+
}
|
|
341
|
+
state.channel = null;
|
|
342
|
+
}
|
|
343
|
+
state.reconnectAttempts = 0;
|
|
344
|
+
setConnectionState('disconnected');
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Start realtime subscriptions for a user
|
|
348
|
+
*/
|
|
349
|
+
export async function startRealtimeSubscriptions(userId) {
|
|
350
|
+
if (typeof window === 'undefined')
|
|
351
|
+
return;
|
|
352
|
+
// Don't start if offline - wait for online event
|
|
353
|
+
if (!navigator.onLine) {
|
|
354
|
+
debugLog('[Realtime] Offline - skipping subscription start');
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
// Don't start if already connected with same user
|
|
358
|
+
if (state.channel && state.userId === userId && state.connectionState === 'connected') {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
// Prevent concurrent start/stop operations
|
|
362
|
+
if (operationInProgress) {
|
|
363
|
+
debugLog('[Realtime] Operation already in progress, skipping');
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
operationInProgress = true;
|
|
367
|
+
try {
|
|
368
|
+
// Stop existing subscriptions first
|
|
369
|
+
await stopRealtimeSubscriptionsInternal();
|
|
370
|
+
state.userId = userId;
|
|
371
|
+
state.deviceId = getDeviceId();
|
|
372
|
+
setConnectionState('connecting');
|
|
373
|
+
const config = getEngineConfig();
|
|
374
|
+
const realtimeTables = config.tables.map(t => t.supabaseName);
|
|
375
|
+
// Create a single channel for all tables
|
|
376
|
+
// Using a unique channel name per user
|
|
377
|
+
const channelName = `${config.prefix}_sync_${userId}`;
|
|
378
|
+
state.channel = config.supabase.channel(channelName);
|
|
379
|
+
// Subscribe to all tables without user_id filter
|
|
380
|
+
// RLS (Row Level Security) policies handle security at the database level
|
|
381
|
+
debugLog(`[Realtime] Setting up subscriptions for ${realtimeTables.length} tables`);
|
|
382
|
+
for (const table of realtimeTables) {
|
|
383
|
+
state.channel = state.channel.on('postgres_changes', {
|
|
384
|
+
event: '*',
|
|
385
|
+
schema: 'public',
|
|
386
|
+
table: table
|
|
387
|
+
}, (payload) => {
|
|
388
|
+
debugLog(`[Realtime] Raw payload received for ${table}:`, payload.eventType);
|
|
389
|
+
handleRealtimeChange(table, payload).catch((error) => {
|
|
390
|
+
debugError(`[Realtime] Error processing ${table} change:`, error);
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
// Subscribe to the channel
|
|
395
|
+
state.channel.subscribe((status, err) => {
|
|
396
|
+
// Release the operation lock once we get any response
|
|
397
|
+
operationInProgress = false;
|
|
398
|
+
switch (status) {
|
|
399
|
+
case 'SUBSCRIBED':
|
|
400
|
+
debugLog('[Realtime] Connected and subscribed');
|
|
401
|
+
state.reconnectAttempts = 0;
|
|
402
|
+
reconnectScheduled = false;
|
|
403
|
+
setConnectionState('connected');
|
|
404
|
+
break;
|
|
405
|
+
case 'CHANNEL_ERROR':
|
|
406
|
+
if (err?.message) {
|
|
407
|
+
debugError('[Realtime] Channel error:', err?.message);
|
|
408
|
+
}
|
|
409
|
+
setConnectionState('error', err?.message || 'Channel error');
|
|
410
|
+
scheduleReconnect();
|
|
411
|
+
break;
|
|
412
|
+
case 'TIMED_OUT':
|
|
413
|
+
debugWarn('[Realtime] Connection timed out');
|
|
414
|
+
setConnectionState('error', 'Connection timed out');
|
|
415
|
+
scheduleReconnect();
|
|
416
|
+
break;
|
|
417
|
+
case 'CLOSED':
|
|
418
|
+
debugLog('[Realtime] Channel closed');
|
|
419
|
+
// Only try to reconnect if:
|
|
420
|
+
// 1. We weren't intentionally disconnected
|
|
421
|
+
// 2. We have a user
|
|
422
|
+
// 3. We're not already scheduled for reconnect (prevents duplicate from CHANNEL_ERROR + CLOSED)
|
|
423
|
+
if (state.connectionState !== 'disconnected' && state.userId && !reconnectScheduled) {
|
|
424
|
+
setConnectionState('disconnected');
|
|
425
|
+
scheduleReconnect();
|
|
426
|
+
}
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
catch (error) {
|
|
432
|
+
operationInProgress = false;
|
|
433
|
+
debugError('[Realtime] Failed to start subscriptions:', error);
|
|
434
|
+
setConnectionState('error', error instanceof Error ? error.message : 'Failed to connect');
|
|
435
|
+
scheduleReconnect();
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Stop realtime subscriptions (public API)
|
|
440
|
+
*/
|
|
441
|
+
export async function stopRealtimeSubscriptions() {
|
|
442
|
+
// Prevent concurrent operations
|
|
443
|
+
if (operationInProgress) {
|
|
444
|
+
debugLog('[Realtime] Operation already in progress, skipping stop');
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
operationInProgress = true;
|
|
448
|
+
try {
|
|
449
|
+
await stopRealtimeSubscriptionsInternal();
|
|
450
|
+
state.userId = null;
|
|
451
|
+
// Clear recently processed tracking
|
|
452
|
+
recentlyProcessedByRealtime.clear();
|
|
453
|
+
}
|
|
454
|
+
finally {
|
|
455
|
+
operationInProgress = false;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Pause realtime (when going offline) - stops reconnection attempts
|
|
460
|
+
* Called by sync engine when offline event fires
|
|
461
|
+
*/
|
|
462
|
+
export function pauseRealtime() {
|
|
463
|
+
// Clear any pending reconnect attempts and reset flags
|
|
464
|
+
if (state.reconnectTimeout) {
|
|
465
|
+
clearTimeout(state.reconnectTimeout);
|
|
466
|
+
state.reconnectTimeout = null;
|
|
467
|
+
}
|
|
468
|
+
reconnectScheduled = false;
|
|
469
|
+
// Reset reconnect attempts so we get fresh attempts when coming online
|
|
470
|
+
state.reconnectAttempts = 0;
|
|
471
|
+
setConnectionState('disconnected');
|
|
472
|
+
debugLog('[Realtime] Paused - waiting for online event');
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Check if realtime is healthy (connected and not in error state)
|
|
476
|
+
*/
|
|
477
|
+
export function isRealtimeHealthy() {
|
|
478
|
+
return state.connectionState === 'connected';
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Clean up expired entries from recently processed tracking
|
|
482
|
+
*/
|
|
483
|
+
export function cleanupRealtimeTracking() {
|
|
484
|
+
const now = Date.now();
|
|
485
|
+
for (const [entityId, processedAt] of recentlyProcessedByRealtime) {
|
|
486
|
+
if (now - processedAt > RECENTLY_MODIFIED_TTL_MS) {
|
|
487
|
+
recentlyProcessedByRealtime.delete(entityId);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
//# sourceMappingURL=realtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime.js","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reconnect Handler Registry
|
|
3
|
+
* Allows layout components to register callbacks for reconnection events
|
|
4
|
+
*/
|
|
5
|
+
type ReconnectHandler = () => Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Set the reconnect handler (called from layout.svelte)
|
|
8
|
+
*/
|
|
9
|
+
export declare function setReconnectHandler(handler: ReconnectHandler | null): void;
|
|
10
|
+
/**
|
|
11
|
+
* Call the reconnect handler if one is registered
|
|
12
|
+
* Called from the network store on reconnection
|
|
13
|
+
*/
|
|
14
|
+
export declare function callReconnectHandler(): Promise<void>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=reconnectHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnectHandler.d.ts","sourceRoot":"","sources":["../src/reconnectHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,KAAK,gBAAgB,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;AAI5C;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAE1E;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAI1D"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reconnect Handler Registry
|
|
3
|
+
* Allows layout components to register callbacks for reconnection events
|
|
4
|
+
*/
|
|
5
|
+
let reconnectHandler = null;
|
|
6
|
+
/**
|
|
7
|
+
* Set the reconnect handler (called from layout.svelte)
|
|
8
|
+
*/
|
|
9
|
+
export function setReconnectHandler(handler) {
|
|
10
|
+
reconnectHandler = handler;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Call the reconnect handler if one is registered
|
|
14
|
+
* Called from the network store on reconnection
|
|
15
|
+
*/
|
|
16
|
+
export async function callReconnectHandler() {
|
|
17
|
+
if (reconnectHandler) {
|
|
18
|
+
await reconnectHandler();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=reconnectHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnectHandler.js","sourceRoot":"","sources":["../src/reconnectHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,IAAI,gBAAgB,GAA4B,IAAI,CAAC;AAErD;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAgC;IAClE,gBAAgB,GAAG,OAAO,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,gBAAgB,EAAE,CAAC;IAC3B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime Configuration Module
|
|
3
|
+
*
|
|
4
|
+
* Replaces build-time $env/static/public with runtime config fetched from the server.
|
|
5
|
+
* Config is cached in localStorage for instant subsequent loads and offline PWA support.
|
|
6
|
+
*/
|
|
7
|
+
export interface AppConfig {
|
|
8
|
+
supabaseUrl: string;
|
|
9
|
+
supabaseAnonKey: string;
|
|
10
|
+
configured: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function _setConfigPrefix(prefix: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Initialize config: tries localStorage first (instant), then validates against server.
|
|
15
|
+
* Returns the config if configured, null if not.
|
|
16
|
+
*/
|
|
17
|
+
export declare function initConfig(): Promise<AppConfig | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Get config synchronously. Returns cached config or null.
|
|
20
|
+
* Call initConfig() first to ensure config is loaded.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getConfig(): AppConfig | null;
|
|
23
|
+
/**
|
|
24
|
+
* Set config directly (used after setup wizard completes)
|
|
25
|
+
*/
|
|
26
|
+
export declare function setConfig(config: AppConfig): void;
|
|
27
|
+
//# sourceMappingURL=runtimeConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtimeConfig.d.ts","sourceRoot":"","sources":["../../src/runtime/runtimeConfig.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;CACrB;AAID,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,QAE9C;AAuCD;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CA6C5D;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,SAAS,GAAG,IAAI,CAQ5C;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAGjD"}
|