@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,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Operation Helpers
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for:
|
|
5
|
+
* - Transforming operations to Supabase mutations
|
|
6
|
+
* - Creating operation items
|
|
7
|
+
* - Operation coalescing logic
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Transform a SyncOperationItem into a Supabase mutation payload.
|
|
11
|
+
* This is called by the sync engine when pushing to Supabase.
|
|
12
|
+
*
|
|
13
|
+
* @param operation The operation to transform
|
|
14
|
+
* @param currentValue The current value of the field (needed for increment operations)
|
|
15
|
+
* @returns The payload to send to Supabase
|
|
16
|
+
*/
|
|
17
|
+
export function operationToMutation(operation, currentValue) {
|
|
18
|
+
switch (operation.operationType) {
|
|
19
|
+
case 'create':
|
|
20
|
+
return {
|
|
21
|
+
mutationType: 'insert',
|
|
22
|
+
payload: {
|
|
23
|
+
id: operation.entityId,
|
|
24
|
+
...operation.value
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
case 'delete':
|
|
28
|
+
return {
|
|
29
|
+
mutationType: 'update',
|
|
30
|
+
payload: {
|
|
31
|
+
deleted: true,
|
|
32
|
+
updated_at: operation.timestamp
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
case 'increment': {
|
|
36
|
+
// For increment, we need to compute the new value
|
|
37
|
+
// currentValue should be provided by the caller from the local entity
|
|
38
|
+
const base = typeof currentValue === 'number' ? currentValue : 0;
|
|
39
|
+
const delta = typeof operation.value === 'number' ? operation.value : 0;
|
|
40
|
+
const newValue = base + delta;
|
|
41
|
+
if (!operation.field) {
|
|
42
|
+
throw new Error('Increment operation requires a field');
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
mutationType: 'update',
|
|
46
|
+
payload: {
|
|
47
|
+
[operation.field]: newValue,
|
|
48
|
+
updated_at: operation.timestamp
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
case 'set': {
|
|
53
|
+
// For set, we either have a single field or a full payload
|
|
54
|
+
if (operation.field) {
|
|
55
|
+
// Single field set
|
|
56
|
+
return {
|
|
57
|
+
mutationType: 'update',
|
|
58
|
+
payload: {
|
|
59
|
+
[operation.field]: operation.value,
|
|
60
|
+
updated_at: operation.timestamp
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// Full payload set
|
|
66
|
+
return {
|
|
67
|
+
mutationType: 'update',
|
|
68
|
+
payload: {
|
|
69
|
+
...operation.value,
|
|
70
|
+
updated_at: operation.timestamp
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
default:
|
|
76
|
+
throw new Error(`Unknown operation type: ${operation.operationType}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Infer the appropriate operation type based on the value and field name.
|
|
81
|
+
*
|
|
82
|
+
* @param value The value being set
|
|
83
|
+
* @param fieldName The name of the field
|
|
84
|
+
* @param isIncrement Whether this is a known increment operation
|
|
85
|
+
* @returns The inferred operation type
|
|
86
|
+
*/
|
|
87
|
+
export function inferOperationType(_value, _fieldName, isIncrement) {
|
|
88
|
+
if (isIncrement) {
|
|
89
|
+
return 'increment';
|
|
90
|
+
}
|
|
91
|
+
// All non-increment operations are 'set'
|
|
92
|
+
return 'set';
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Create an increment operation item.
|
|
96
|
+
*/
|
|
97
|
+
export function createIncrementOperation(table, entityId, field, delta, timestamp) {
|
|
98
|
+
return {
|
|
99
|
+
table,
|
|
100
|
+
entityId,
|
|
101
|
+
operationType: 'increment',
|
|
102
|
+
field,
|
|
103
|
+
value: delta,
|
|
104
|
+
timestamp,
|
|
105
|
+
retries: 0
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Create a set operation item for a single field.
|
|
110
|
+
*/
|
|
111
|
+
export function createSetOperation(table, entityId, field, value, timestamp) {
|
|
112
|
+
return {
|
|
113
|
+
table,
|
|
114
|
+
entityId,
|
|
115
|
+
operationType: 'set',
|
|
116
|
+
field,
|
|
117
|
+
value,
|
|
118
|
+
timestamp,
|
|
119
|
+
retries: 0
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Create a set operation item for multiple fields.
|
|
124
|
+
*/
|
|
125
|
+
export function createMultiFieldSetOperation(table, entityId, fields, timestamp) {
|
|
126
|
+
return {
|
|
127
|
+
table,
|
|
128
|
+
entityId,
|
|
129
|
+
operationType: 'set',
|
|
130
|
+
value: fields,
|
|
131
|
+
timestamp,
|
|
132
|
+
retries: 0
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Create a create operation item.
|
|
137
|
+
*/
|
|
138
|
+
export function createCreateOperation(table, entityId, payload, timestamp) {
|
|
139
|
+
return {
|
|
140
|
+
table,
|
|
141
|
+
entityId,
|
|
142
|
+
operationType: 'create',
|
|
143
|
+
value: payload,
|
|
144
|
+
timestamp,
|
|
145
|
+
retries: 0
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Create a delete operation item.
|
|
150
|
+
*/
|
|
151
|
+
export function createDeleteOperation(table, entityId, timestamp) {
|
|
152
|
+
return {
|
|
153
|
+
table,
|
|
154
|
+
entityId,
|
|
155
|
+
operationType: 'delete',
|
|
156
|
+
timestamp,
|
|
157
|
+
retries: 0
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Check if two operations can be coalesced together.
|
|
162
|
+
*
|
|
163
|
+
* Coalescing rules:
|
|
164
|
+
* - Same table + entityId + operationType can be coalesced
|
|
165
|
+
* - Increment operations: can be coalesced if same field (sums deltas)
|
|
166
|
+
* - Set operations: can be coalesced (keeps merged/latest values)
|
|
167
|
+
* - Create/delete: cannot coalesce (would lose intent)
|
|
168
|
+
*/
|
|
169
|
+
export function canCoalesce(a, b) {
|
|
170
|
+
if (a.table !== b.table || a.entityId !== b.entityId) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
// Same operation type on same field can be coalesced
|
|
174
|
+
if (a.operationType === b.operationType) {
|
|
175
|
+
// Create and delete cannot coalesce (would lose intent)
|
|
176
|
+
if (a.operationType === 'create' || a.operationType === 'delete') {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
// For increment operations, must be same field
|
|
180
|
+
if (a.operationType === 'increment') {
|
|
181
|
+
// Both must have a field specified
|
|
182
|
+
if (!a.field || !b.field) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
// Must be the same field
|
|
186
|
+
return a.field === b.field;
|
|
187
|
+
}
|
|
188
|
+
// For set operations with a specific field, must be same field
|
|
189
|
+
if (a.field && b.field && a.field !== b.field) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Coalesce two operations into one.
|
|
198
|
+
*
|
|
199
|
+
* Coalescing strategy by operation type:
|
|
200
|
+
* - Increment: sum the deltas (e.g., +1 and +1 = +2)
|
|
201
|
+
* - Set: keep the newer value (last-write-wins)
|
|
202
|
+
*
|
|
203
|
+
* @param older The older operation
|
|
204
|
+
* @param newer The newer operation
|
|
205
|
+
* @returns The coalesced operation
|
|
206
|
+
*/
|
|
207
|
+
export function coalesceOperations(older, newer) {
|
|
208
|
+
// For increment operations: sum the deltas
|
|
209
|
+
if (older.operationType === 'increment' && newer.operationType === 'increment') {
|
|
210
|
+
const olderDelta = typeof older.value === 'number' ? older.value : 0;
|
|
211
|
+
const newerDelta = typeof newer.value === 'number' ? newer.value : 0;
|
|
212
|
+
const summedDelta = olderDelta + newerDelta;
|
|
213
|
+
return {
|
|
214
|
+
...older,
|
|
215
|
+
// Keep older's id and timestamp for queue management and backoff
|
|
216
|
+
value: summedDelta
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
// For set operations: keep the newer value but preserve older's id/timestamp
|
|
220
|
+
return {
|
|
221
|
+
...newer,
|
|
222
|
+
id: older.id,
|
|
223
|
+
// Keep oldest timestamp for backoff calculation
|
|
224
|
+
timestamp: older.timestamp
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"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"}
|
package/dist/queue.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { SyncOperationItem } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Coalesce multiple operations to the same entity into fewer operations.
|
|
4
|
+
* This dramatically reduces the number of server requests and data transfer.
|
|
5
|
+
*
|
|
6
|
+
* PERFORMANCE OPTIMIZED:
|
|
7
|
+
* - Single DB fetch at start (no re-fetching between phases)
|
|
8
|
+
* - All processing done in memory
|
|
9
|
+
* - Batch deletes and updates at the end
|
|
10
|
+
*/
|
|
11
|
+
export declare function coalescePendingOps(): Promise<number>;
|
|
12
|
+
export declare function getPendingSync(): Promise<SyncOperationItem[]>;
|
|
13
|
+
export declare function cleanupFailedItems(): Promise<{
|
|
14
|
+
count: number;
|
|
15
|
+
tables: string[];
|
|
16
|
+
}>;
|
|
17
|
+
export declare function removeSyncItem(id: number): Promise<void>;
|
|
18
|
+
export declare function incrementRetry(id: number): Promise<void>;
|
|
19
|
+
export declare function getPendingEntityIds(): Promise<Set<string>>;
|
|
20
|
+
/**
|
|
21
|
+
* Queue a sync operation using the intent-based format.
|
|
22
|
+
*/
|
|
23
|
+
export declare function queueSyncOperation(item: Omit<SyncOperationItem, 'id' | 'timestamp' | 'retries'>): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Helper to queue a create operation.
|
|
26
|
+
*/
|
|
27
|
+
export declare function queueCreateOperation(table: string, entityId: string, payload: Record<string, unknown>): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Helper to queue a delete operation.
|
|
30
|
+
*/
|
|
31
|
+
export declare function queueDeleteOperation(table: string, entityId: string): Promise<void>;
|
|
32
|
+
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AASjD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CA8O1D;AAmFD,wBAAsB,cAAc,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAOnE;AAGD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAuBvF;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9D;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU9D;AAGD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAIhE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,CAAC,iBAAiB,EAAE,IAAI,GAAG,WAAW,GAAG,SAAS,CAAC,GAC5D,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC,CAOf;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzF"}
|
package/dist/queue.js
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import { debugWarn } from './debug';
|
|
2
|
+
import { getEngineConfig } from './config';
|
|
3
|
+
// Max retries before giving up on a sync item
|
|
4
|
+
const MAX_SYNC_RETRIES = 5;
|
|
5
|
+
function getDb() {
|
|
6
|
+
return getEngineConfig().db;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Coalesce multiple operations to the same entity into fewer operations.
|
|
10
|
+
* This dramatically reduces the number of server requests and data transfer.
|
|
11
|
+
*
|
|
12
|
+
* PERFORMANCE OPTIMIZED:
|
|
13
|
+
* - Single DB fetch at start (no re-fetching between phases)
|
|
14
|
+
* - All processing done in memory
|
|
15
|
+
* - Batch deletes and updates at the end
|
|
16
|
+
*/
|
|
17
|
+
export async function coalescePendingOps() {
|
|
18
|
+
const db = getDb();
|
|
19
|
+
const allItems = (await db.table('syncQueue').toArray());
|
|
20
|
+
if (allItems.length <= 1)
|
|
21
|
+
return 0;
|
|
22
|
+
// Track changes in memory - apply in batch at the end
|
|
23
|
+
const idsToDelete = new Set();
|
|
24
|
+
const itemUpdates = new Map();
|
|
25
|
+
// Track which items are still "alive" (not marked for deletion)
|
|
26
|
+
const isAlive = (item) => item.id !== undefined && !idsToDelete.has(item.id);
|
|
27
|
+
// Helper to mark item for deletion
|
|
28
|
+
const markDeleted = (item) => {
|
|
29
|
+
if (item.id !== undefined)
|
|
30
|
+
idsToDelete.add(item.id);
|
|
31
|
+
};
|
|
32
|
+
// Helper to mark item for update
|
|
33
|
+
const markUpdated = (item, updates) => {
|
|
34
|
+
if (item.id !== undefined) {
|
|
35
|
+
const existing = itemUpdates.get(item.id) || {};
|
|
36
|
+
itemUpdates.set(item.id, { ...existing, ...updates });
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
// Helper to get effective value (considering pending updates)
|
|
40
|
+
const getEffectiveValue = (item) => {
|
|
41
|
+
if (item.id !== undefined && itemUpdates.has(item.id)) {
|
|
42
|
+
return itemUpdates.get(item.id).value ?? item.value;
|
|
43
|
+
}
|
|
44
|
+
return item.value;
|
|
45
|
+
};
|
|
46
|
+
// === STEP 1: Group all operations by entity ===
|
|
47
|
+
const entityGroups = new Map();
|
|
48
|
+
for (const item of allItems) {
|
|
49
|
+
const key = `${item.table}:${item.entityId}`;
|
|
50
|
+
if (!entityGroups.has(key))
|
|
51
|
+
entityGroups.set(key, []);
|
|
52
|
+
entityGroups.get(key).push(item);
|
|
53
|
+
}
|
|
54
|
+
// === STEP 2: Process each entity group ===
|
|
55
|
+
for (const [, items] of entityGroups) {
|
|
56
|
+
// Sort by timestamp to understand the sequence
|
|
57
|
+
items.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
58
|
+
const hasCreate = items.some((i) => i.operationType === 'create');
|
|
59
|
+
const hasDelete = items.some((i) => i.operationType === 'delete');
|
|
60
|
+
// Case 1: CREATE followed eventually by DELETE -> cancel everything for this entity
|
|
61
|
+
if (hasCreate && hasDelete) {
|
|
62
|
+
for (const item of items) {
|
|
63
|
+
markDeleted(item);
|
|
64
|
+
}
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
// Case 2: No CREATE but has DELETE -> remove all non-delete operations
|
|
68
|
+
if (!hasCreate && hasDelete) {
|
|
69
|
+
for (const item of items) {
|
|
70
|
+
if (item.operationType !== 'delete') {
|
|
71
|
+
markDeleted(item);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
// Case 3: Has CREATE but no DELETE -> merge all updates/sets into create
|
|
77
|
+
if (hasCreate && !hasDelete) {
|
|
78
|
+
const createItem = items.find((i) => i.operationType === 'create');
|
|
79
|
+
const otherItems = items.filter((i) => i.operationType !== 'create');
|
|
80
|
+
if (createItem && otherItems.length > 0) {
|
|
81
|
+
let mergedPayload = { ...createItem.value };
|
|
82
|
+
for (const item of otherItems) {
|
|
83
|
+
if (item.operationType === 'set') {
|
|
84
|
+
if (item.field) {
|
|
85
|
+
mergedPayload[item.field] = item.value;
|
|
86
|
+
}
|
|
87
|
+
else if (typeof item.value === 'object' && item.value !== null) {
|
|
88
|
+
mergedPayload = { ...mergedPayload, ...item.value };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else if (item.operationType === 'increment' && item.field) {
|
|
92
|
+
const currentVal = typeof mergedPayload[item.field] === 'number'
|
|
93
|
+
? mergedPayload[item.field]
|
|
94
|
+
: 0;
|
|
95
|
+
const delta = typeof item.value === 'number' ? item.value : 0;
|
|
96
|
+
mergedPayload[item.field] = currentVal + delta;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
markUpdated(createItem, { value: mergedPayload });
|
|
100
|
+
for (const item of otherItems) {
|
|
101
|
+
markDeleted(item);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
// Case 4: No create, no delete - handle increment/set interactions and same-type coalescing
|
|
107
|
+
processFieldOperations(items, markDeleted, markUpdated);
|
|
108
|
+
}
|
|
109
|
+
// === STEP 3: Coalesce remaining INCREMENT operations (not yet deleted) ===
|
|
110
|
+
const incrementGroups = new Map();
|
|
111
|
+
for (const item of allItems) {
|
|
112
|
+
if (item.operationType === 'increment' && item.field && isAlive(item)) {
|
|
113
|
+
const key = `${item.table}:${item.entityId}:${item.field}`;
|
|
114
|
+
if (!incrementGroups.has(key))
|
|
115
|
+
incrementGroups.set(key, []);
|
|
116
|
+
incrementGroups.get(key).push(item);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const [, items] of incrementGroups) {
|
|
120
|
+
const aliveItems = items.filter(isAlive);
|
|
121
|
+
if (aliveItems.length <= 1)
|
|
122
|
+
continue;
|
|
123
|
+
aliveItems.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
124
|
+
let totalDelta = 0;
|
|
125
|
+
for (const item of aliveItems) {
|
|
126
|
+
const effectiveValue = getEffectiveValue(item);
|
|
127
|
+
const delta = typeof effectiveValue === 'number' ? effectiveValue : 0;
|
|
128
|
+
totalDelta += delta;
|
|
129
|
+
}
|
|
130
|
+
const oldestItem = aliveItems[0];
|
|
131
|
+
markUpdated(oldestItem, { value: totalDelta });
|
|
132
|
+
for (let i = 1; i < aliveItems.length; i++) {
|
|
133
|
+
markDeleted(aliveItems[i]);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// === STEP 4: Coalesce remaining SET operations (not yet deleted) ===
|
|
137
|
+
const setGroups = new Map();
|
|
138
|
+
for (const item of allItems) {
|
|
139
|
+
if (item.operationType === 'set' && isAlive(item)) {
|
|
140
|
+
const key = `${item.table}:${item.entityId}`;
|
|
141
|
+
if (!setGroups.has(key))
|
|
142
|
+
setGroups.set(key, []);
|
|
143
|
+
setGroups.get(key).push(item);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
for (const [, items] of setGroups) {
|
|
147
|
+
const aliveItems = items.filter(isAlive);
|
|
148
|
+
if (aliveItems.length <= 1)
|
|
149
|
+
continue;
|
|
150
|
+
aliveItems.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
151
|
+
let mergedValue = {};
|
|
152
|
+
for (const item of aliveItems) {
|
|
153
|
+
const effectiveValue = getEffectiveValue(item);
|
|
154
|
+
if (item.field) {
|
|
155
|
+
mergedValue[item.field] = effectiveValue;
|
|
156
|
+
}
|
|
157
|
+
else if (typeof effectiveValue === 'object' && effectiveValue !== null) {
|
|
158
|
+
mergedValue = { ...mergedValue, ...effectiveValue };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const oldestItem = aliveItems[0];
|
|
162
|
+
markUpdated(oldestItem, { value: mergedValue, field: undefined });
|
|
163
|
+
for (let i = 1; i < aliveItems.length; i++) {
|
|
164
|
+
markDeleted(aliveItems[i]);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// === STEP 5: Remove no-op operations ===
|
|
168
|
+
for (const item of allItems) {
|
|
169
|
+
if (!isAlive(item))
|
|
170
|
+
continue;
|
|
171
|
+
let shouldDelete = false;
|
|
172
|
+
const effectiveValue = getEffectiveValue(item);
|
|
173
|
+
// Zero-delta increments are no-ops
|
|
174
|
+
if (item.operationType === 'increment') {
|
|
175
|
+
const delta = typeof effectiveValue === 'number' ? effectiveValue : 0;
|
|
176
|
+
if (delta === 0) {
|
|
177
|
+
shouldDelete = true;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Empty sets or sets with only updated_at are no-ops
|
|
181
|
+
if (item.operationType === 'set') {
|
|
182
|
+
const pendingUpdate = item.id !== undefined ? itemUpdates.get(item.id) : undefined;
|
|
183
|
+
const effectiveField = pendingUpdate?.field !== undefined ? pendingUpdate.field : item.field;
|
|
184
|
+
if (effectiveField) {
|
|
185
|
+
if (effectiveField === 'updated_at') {
|
|
186
|
+
shouldDelete = true;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else if (typeof effectiveValue === 'object' && effectiveValue !== null) {
|
|
190
|
+
const payload = effectiveValue;
|
|
191
|
+
const keys = Object.keys(payload).filter((k) => k !== 'updated_at');
|
|
192
|
+
if (keys.length === 0) {
|
|
193
|
+
shouldDelete = true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else if (effectiveValue === undefined || effectiveValue === null) {
|
|
197
|
+
shouldDelete = true;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (shouldDelete) {
|
|
201
|
+
markDeleted(item);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// === STEP 6: Apply all changes in batch ===
|
|
205
|
+
const deleteIds = Array.from(idsToDelete);
|
|
206
|
+
// Filter out updates for items we're deleting
|
|
207
|
+
const finalUpdates = [];
|
|
208
|
+
for (const [id, changes] of itemUpdates) {
|
|
209
|
+
if (!idsToDelete.has(id)) {
|
|
210
|
+
finalUpdates.push({ id, changes });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const syncQueue = db.table('syncQueue');
|
|
214
|
+
// Batch delete
|
|
215
|
+
if (deleteIds.length > 0) {
|
|
216
|
+
await syncQueue.bulkDelete(deleteIds);
|
|
217
|
+
}
|
|
218
|
+
// Batch update (Dexie doesn't have bulkUpdate, so we use a transaction)
|
|
219
|
+
if (finalUpdates.length > 0) {
|
|
220
|
+
await db.transaction('rw', syncQueue, async () => {
|
|
221
|
+
for (const { id, changes } of finalUpdates) {
|
|
222
|
+
await syncQueue.update(id, changes);
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return deleteIds.length;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Process increment/set interactions for the same field within an entity (in-memory).
|
|
230
|
+
*/
|
|
231
|
+
function processFieldOperations(items, markDeleted, markUpdated) {
|
|
232
|
+
// Group by field
|
|
233
|
+
const fieldGroups = new Map();
|
|
234
|
+
for (const item of items) {
|
|
235
|
+
if (item.field && (item.operationType === 'increment' || item.operationType === 'set')) {
|
|
236
|
+
const key = item.field;
|
|
237
|
+
if (!fieldGroups.has(key))
|
|
238
|
+
fieldGroups.set(key, []);
|
|
239
|
+
fieldGroups.get(key).push(item);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
for (const [, fieldItems] of fieldGroups) {
|
|
243
|
+
if (fieldItems.length <= 1)
|
|
244
|
+
continue;
|
|
245
|
+
// Sort by timestamp
|
|
246
|
+
fieldItems.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
247
|
+
const hasIncrement = fieldItems.some((i) => i.operationType === 'increment');
|
|
248
|
+
const hasSet = fieldItems.some((i) => i.operationType === 'set');
|
|
249
|
+
if (hasIncrement && hasSet) {
|
|
250
|
+
// Find the last set operation
|
|
251
|
+
const lastSetIndex = fieldItems.map((i) => i.operationType).lastIndexOf('set');
|
|
252
|
+
const lastSet = fieldItems[lastSetIndex];
|
|
253
|
+
// Check if there are increments AFTER the last set
|
|
254
|
+
const incrementsAfterSet = fieldItems
|
|
255
|
+
.slice(lastSetIndex + 1)
|
|
256
|
+
.filter((i) => i.operationType === 'increment');
|
|
257
|
+
if (incrementsAfterSet.length > 0) {
|
|
258
|
+
// SET followed by INCREMENT(s): sum increments and add to set value
|
|
259
|
+
let totalDelta = 0;
|
|
260
|
+
for (const inc of incrementsAfterSet) {
|
|
261
|
+
totalDelta += typeof inc.value === 'number' ? inc.value : 0;
|
|
262
|
+
}
|
|
263
|
+
const baseValue = typeof lastSet.value === 'number' ? lastSet.value : 0;
|
|
264
|
+
const finalValue = baseValue + totalDelta;
|
|
265
|
+
markUpdated(lastSet, { value: finalValue });
|
|
266
|
+
// Delete all increments after the set
|
|
267
|
+
for (const inc of incrementsAfterSet) {
|
|
268
|
+
markDeleted(inc);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Delete all operations BEFORE the last set (they're overwritten anyway)
|
|
272
|
+
const itemsBeforeLastSet = fieldItems.slice(0, lastSetIndex);
|
|
273
|
+
for (const item of itemsBeforeLastSet) {
|
|
274
|
+
markDeleted(item);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Exponential backoff: check if item should be retried based on retry count
|
|
280
|
+
// Returns true if enough time has passed since last attempt
|
|
281
|
+
function shouldRetryItem(item) {
|
|
282
|
+
if (item.retries >= MAX_SYNC_RETRIES)
|
|
283
|
+
return false;
|
|
284
|
+
// First attempt (retries=0) is always immediate
|
|
285
|
+
if (item.retries === 0)
|
|
286
|
+
return true;
|
|
287
|
+
// Exponential backoff for retries: 2^(retries-1) seconds (1s, 2s, 4s, 8s)
|
|
288
|
+
const backoffMs = Math.pow(2, item.retries - 1) * 1000;
|
|
289
|
+
const lastAttempt = new Date(item.timestamp).getTime();
|
|
290
|
+
const now = Date.now();
|
|
291
|
+
return now - lastAttempt >= backoffMs;
|
|
292
|
+
}
|
|
293
|
+
export async function getPendingSync() {
|
|
294
|
+
const db = getDb();
|
|
295
|
+
const allItems = (await db.table('syncQueue')
|
|
296
|
+
.orderBy('timestamp')
|
|
297
|
+
.toArray());
|
|
298
|
+
// Filter to only items that should be retried (haven't exceeded max retries and backoff has passed)
|
|
299
|
+
return allItems.filter((item) => shouldRetryItem(item));
|
|
300
|
+
}
|
|
301
|
+
// Remove items that have exceeded max retries and return details for notification
|
|
302
|
+
export async function cleanupFailedItems() {
|
|
303
|
+
const db = getDb();
|
|
304
|
+
const allItems = (await db.table('syncQueue').toArray());
|
|
305
|
+
const failedItems = allItems.filter((item) => item.retries >= MAX_SYNC_RETRIES);
|
|
306
|
+
const affectedTables = new Set();
|
|
307
|
+
for (const item of failedItems) {
|
|
308
|
+
affectedTables.add(item.table);
|
|
309
|
+
if (item.id) {
|
|
310
|
+
debugWarn(`Sync item permanently failed after ${MAX_SYNC_RETRIES} retries:`, {
|
|
311
|
+
table: item.table,
|
|
312
|
+
operationType: item.operationType,
|
|
313
|
+
entityId: item.entityId
|
|
314
|
+
});
|
|
315
|
+
await db.table('syncQueue').delete(item.id);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
count: failedItems.length,
|
|
320
|
+
tables: Array.from(affectedTables)
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
export async function removeSyncItem(id) {
|
|
324
|
+
const db = getDb();
|
|
325
|
+
await db.table('syncQueue').delete(id);
|
|
326
|
+
}
|
|
327
|
+
export async function incrementRetry(id) {
|
|
328
|
+
const db = getDb();
|
|
329
|
+
const item = await db.table('syncQueue').get(id);
|
|
330
|
+
if (item) {
|
|
331
|
+
// Update retry count and timestamp for exponential backoff calculation
|
|
332
|
+
await db.table('syncQueue').update(id, {
|
|
333
|
+
retries: item.retries + 1,
|
|
334
|
+
timestamp: new Date().toISOString()
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
// Get entity IDs that have pending sync operations
|
|
339
|
+
export async function getPendingEntityIds() {
|
|
340
|
+
const db = getDb();
|
|
341
|
+
const pending = (await db.table('syncQueue').toArray());
|
|
342
|
+
return new Set(pending.map((item) => item.entityId));
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Queue a sync operation using the intent-based format.
|
|
346
|
+
*/
|
|
347
|
+
export async function queueSyncOperation(item) {
|
|
348
|
+
const db = getDb();
|
|
349
|
+
const fullItem = {
|
|
350
|
+
...item,
|
|
351
|
+
timestamp: new Date().toISOString(),
|
|
352
|
+
retries: 0
|
|
353
|
+
};
|
|
354
|
+
await db.table('syncQueue').add(fullItem);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Helper to queue a create operation.
|
|
358
|
+
*/
|
|
359
|
+
export async function queueCreateOperation(table, entityId, payload) {
|
|
360
|
+
await queueSyncOperation({
|
|
361
|
+
table,
|
|
362
|
+
entityId,
|
|
363
|
+
operationType: 'create',
|
|
364
|
+
value: payload
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Helper to queue a delete operation.
|
|
369
|
+
*/
|
|
370
|
+
export async function queueDeleteOperation(table, entityId) {
|
|
371
|
+
await queueSyncOperation({
|
|
372
|
+
table,
|
|
373
|
+
entityId,
|
|
374
|
+
operationType: 'delete'
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
//# sourceMappingURL=queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"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"}
|