@anfenn/dync 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +212 -0
  3. package/dist/capacitor.cjs +228 -0
  4. package/dist/capacitor.cjs.map +1 -0
  5. package/dist/capacitor.d.cts +62 -0
  6. package/dist/capacitor.d.ts +62 -0
  7. package/dist/capacitor.js +9 -0
  8. package/dist/capacitor.js.map +1 -0
  9. package/dist/chunk-LGHOZECP.js +3884 -0
  10. package/dist/chunk-LGHOZECP.js.map +1 -0
  11. package/dist/chunk-SQB6E7V2.js +191 -0
  12. package/dist/chunk-SQB6E7V2.js.map +1 -0
  13. package/dist/dexie-Bv-fV10P.d.cts +444 -0
  14. package/dist/dexie-DJFApKsM.d.ts +444 -0
  15. package/dist/dexie.cjs +381 -0
  16. package/dist/dexie.cjs.map +1 -0
  17. package/dist/dexie.d.cts +3 -0
  18. package/dist/dexie.d.ts +3 -0
  19. package/dist/dexie.js +343 -0
  20. package/dist/dexie.js.map +1 -0
  21. package/dist/expoSqlite.cjs +98 -0
  22. package/dist/expoSqlite.cjs.map +1 -0
  23. package/dist/expoSqlite.d.cts +17 -0
  24. package/dist/expoSqlite.d.ts +17 -0
  25. package/dist/expoSqlite.js +61 -0
  26. package/dist/expoSqlite.js.map +1 -0
  27. package/dist/index.cjs +3916 -0
  28. package/dist/index.cjs.map +1 -0
  29. package/dist/index.d.cts +8 -0
  30. package/dist/index.d.ts +8 -0
  31. package/dist/index.js +20 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/index.shared-CPIge2ZM.d.ts +234 -0
  34. package/dist/index.shared-YSn6c01d.d.cts +234 -0
  35. package/dist/node.cjs +126 -0
  36. package/dist/node.cjs.map +1 -0
  37. package/dist/node.d.cts +80 -0
  38. package/dist/node.d.ts +80 -0
  39. package/dist/node.js +89 -0
  40. package/dist/node.js.map +1 -0
  41. package/dist/react/index.cjs +1754 -0
  42. package/dist/react/index.cjs.map +1 -0
  43. package/dist/react/index.d.cts +40 -0
  44. package/dist/react/index.d.ts +40 -0
  45. package/dist/react/index.js +78 -0
  46. package/dist/react/index.js.map +1 -0
  47. package/dist/types-CSbIAfu2.d.cts +46 -0
  48. package/dist/types-CSbIAfu2.d.ts +46 -0
  49. package/dist/wa-sqlite.cjs +318 -0
  50. package/dist/wa-sqlite.cjs.map +1 -0
  51. package/dist/wa-sqlite.d.cts +175 -0
  52. package/dist/wa-sqlite.d.ts +175 -0
  53. package/dist/wa-sqlite.js +281 -0
  54. package/dist/wa-sqlite.js.map +1 -0
  55. package/package.json +171 -0
  56. package/src/addVisibilityChangeListener.native.ts +33 -0
  57. package/src/addVisibilityChangeListener.ts +24 -0
  58. package/src/capacitor.ts +4 -0
  59. package/src/core/StateManager.ts +272 -0
  60. package/src/core/firstLoad.ts +332 -0
  61. package/src/core/pullOperations.ts +212 -0
  62. package/src/core/pushOperations.ts +290 -0
  63. package/src/core/tableEnhancers.ts +457 -0
  64. package/src/core/types.ts +3 -0
  65. package/src/createLocalId.native.ts +8 -0
  66. package/src/createLocalId.ts +6 -0
  67. package/src/dexie.ts +2 -0
  68. package/src/expoSqlite.ts +2 -0
  69. package/src/helpers.ts +87 -0
  70. package/src/index.native.ts +28 -0
  71. package/src/index.shared.ts +613 -0
  72. package/src/index.ts +28 -0
  73. package/src/logger.ts +26 -0
  74. package/src/node.ts +4 -0
  75. package/src/react/index.ts +2 -0
  76. package/src/react/useDync.ts +156 -0
  77. package/src/storage/dexie/DexieAdapter.ts +72 -0
  78. package/src/storage/dexie/DexieQueryContext.ts +14 -0
  79. package/src/storage/dexie/DexieStorageCollection.ts +124 -0
  80. package/src/storage/dexie/DexieStorageTable.ts +123 -0
  81. package/src/storage/dexie/DexieStorageWhereClause.ts +103 -0
  82. package/src/storage/dexie/helpers.ts +1 -0
  83. package/src/storage/dexie/index.ts +7 -0
  84. package/src/storage/memory/MemoryAdapter.ts +55 -0
  85. package/src/storage/memory/MemoryCollection.ts +215 -0
  86. package/src/storage/memory/MemoryQueryContext.ts +14 -0
  87. package/src/storage/memory/MemoryTable.ts +336 -0
  88. package/src/storage/memory/MemoryWhereClause.ts +134 -0
  89. package/src/storage/memory/index.ts +7 -0
  90. package/src/storage/memory/types.ts +24 -0
  91. package/src/storage/sqlite/SQLiteAdapter.ts +564 -0
  92. package/src/storage/sqlite/SQLiteCollection.ts +294 -0
  93. package/src/storage/sqlite/SQLiteTable.ts +604 -0
  94. package/src/storage/sqlite/SQLiteWhereClause.ts +341 -0
  95. package/src/storage/sqlite/SqliteQueryContext.ts +30 -0
  96. package/src/storage/sqlite/drivers/BetterSqlite3Driver.ts +156 -0
  97. package/src/storage/sqlite/drivers/CapacitorFastSqlDriver.ts +114 -0
  98. package/src/storage/sqlite/drivers/CapacitorSQLiteDriver.ts +137 -0
  99. package/src/storage/sqlite/drivers/ExpoSQLiteDriver.native.ts +67 -0
  100. package/src/storage/sqlite/drivers/WaSqliteDriver.ts +537 -0
  101. package/src/storage/sqlite/drivers/wa-sqlite-vfs.d.ts +46 -0
  102. package/src/storage/sqlite/helpers.ts +144 -0
  103. package/src/storage/sqlite/index.ts +11 -0
  104. package/src/storage/sqlite/schema.ts +44 -0
  105. package/src/storage/sqlite/types.ts +164 -0
  106. package/src/storage/types.ts +112 -0
  107. package/src/types.ts +186 -0
  108. package/src/wa-sqlite.ts +4 -0
@@ -0,0 +1,457 @@
1
+ import { createLocalId } from '../helpers';
2
+ import { SyncAction, type MutationEvent, type SyncedRecord } from '../types';
3
+ import type { StorageTable } from '../storage/types';
4
+ import { DYNC_STATE_TABLE, type StateHelpers } from './StateManager';
5
+ import type { WithTransaction } from './types';
6
+ export type EmitMutation = (event: MutationEvent) => void;
7
+
8
+ /**
9
+ * Wraps a table with mutation emission for reactive updates.
10
+ * This allows useLiveQuery to work with any table.
11
+ */
12
+ export function wrapWithMutationEmitter<T>(table: StorageTable<T>, tableName: string, emitMutation: EmitMutation): void {
13
+ const rawAdd = table.raw.add;
14
+ const rawPut = table.raw.put;
15
+ const rawUpdate = table.raw.update;
16
+ const rawDelete = table.raw.delete;
17
+ const rawBulkAdd = table.raw.bulkAdd;
18
+ const rawBulkPut = table.raw.bulkPut;
19
+ const rawBulkUpdate = table.raw.bulkUpdate;
20
+ const rawBulkDelete = table.raw.bulkDelete;
21
+ const rawClear = table.raw.clear;
22
+
23
+ table.add = async (item: T) => {
24
+ const result = await rawAdd(item);
25
+ emitMutation({ type: 'add', tableName, keys: [result] });
26
+ return result;
27
+ };
28
+
29
+ table.put = async (item: T) => {
30
+ const result = await rawPut(item);
31
+ emitMutation({ type: 'update', tableName, keys: [result] });
32
+ return result;
33
+ };
34
+
35
+ table.update = async (key: unknown, changes: Partial<T>) => {
36
+ const result = await rawUpdate(key, changes);
37
+ if (result > 0) {
38
+ emitMutation({ type: 'update', tableName, keys: [key] });
39
+ }
40
+ return result;
41
+ };
42
+
43
+ table.delete = async (key: unknown) => {
44
+ await rawDelete(key);
45
+ emitMutation({ type: 'delete', tableName, keys: [key] });
46
+ };
47
+
48
+ table.bulkAdd = async (items: T[]) => {
49
+ const result = await rawBulkAdd(items);
50
+ if (items.length > 0) {
51
+ emitMutation({ type: 'add', tableName });
52
+ }
53
+ return result;
54
+ };
55
+
56
+ table.bulkPut = async (items: T[]) => {
57
+ const result = await rawBulkPut(items);
58
+ if (items.length > 0) {
59
+ emitMutation({ type: 'update', tableName });
60
+ }
61
+ return result;
62
+ };
63
+
64
+ table.bulkUpdate = async (keysAndChanges: Array<{ key: unknown; changes: Partial<T> }>) => {
65
+ const result = await rawBulkUpdate(keysAndChanges);
66
+ if (result > 0) {
67
+ emitMutation({ type: 'update', tableName, keys: keysAndChanges.map((kc) => kc.key) });
68
+ }
69
+ return result;
70
+ };
71
+
72
+ table.bulkDelete = async (keys: unknown[]) => {
73
+ await rawBulkDelete(keys);
74
+ if (keys.length > 0) {
75
+ emitMutation({ type: 'delete', tableName });
76
+ }
77
+ };
78
+
79
+ table.clear = async () => {
80
+ await rawClear();
81
+ emitMutation({ type: 'delete', tableName });
82
+ };
83
+ }
84
+
85
+ interface SetupOptions {
86
+ owner: object;
87
+ tableCache: Map<string, StorageTable<any>>;
88
+ enhancedTables: Set<string>;
89
+ getTable: (name: string) => StorageTable<any>;
90
+ }
91
+
92
+ export function setupEnhancedTables({ owner, tableCache, enhancedTables, getTable }: SetupOptions, tableNames: string[]): void {
93
+ for (const tableName of tableNames) {
94
+ tableCache.delete(tableName);
95
+ enhancedTables.delete(tableName);
96
+
97
+ if (!Object.prototype.hasOwnProperty.call(owner, tableName)) {
98
+ Object.defineProperty(owner, tableName, {
99
+ get: () => getTable(tableName),
100
+ enumerable: true,
101
+ configurable: true,
102
+ });
103
+ }
104
+ }
105
+ }
106
+
107
+ interface EnhanceOptions<T> {
108
+ table: StorageTable<T & SyncedRecord>;
109
+ tableName: string;
110
+ withTransaction: WithTransaction;
111
+ state: StateHelpers;
112
+ enhancedTables: Set<string>;
113
+ emitMutation: EmitMutation;
114
+ }
115
+
116
+ export function enhanceSyncTable<T>({ table, tableName, withTransaction, state, enhancedTables, emitMutation }: EnhanceOptions<T>): void {
117
+ const rawAdd = table.raw.add;
118
+ const rawPut = table.raw.put;
119
+ const rawUpdate = table.raw.update;
120
+ const rawDelete = table.raw.delete;
121
+ const rawBulkAdd = table.raw.bulkAdd;
122
+ const rawBulkPut = table.raw.bulkPut;
123
+ const rawBulkUpdate = table.raw.bulkUpdate;
124
+ const rawBulkDelete = table.raw.bulkDelete;
125
+ const rawClear = table.raw.clear;
126
+
127
+ const wrappedAdd = async (item: any) => {
128
+ let localId = item._localId;
129
+ if (!localId) localId = createLocalId();
130
+
131
+ const syncedItem = {
132
+ ...item,
133
+ _localId: localId,
134
+ updated_at: new Date().toISOString(),
135
+ };
136
+
137
+ let result: any;
138
+ await withTransaction('rw', [tableName, DYNC_STATE_TABLE], async () => {
139
+ result = await rawAdd(syncedItem);
140
+
141
+ await state.addPendingChange({
142
+ action: SyncAction.Create,
143
+ stateKey: tableName,
144
+ localId,
145
+ changes: syncedItem,
146
+ before: null,
147
+ after: syncedItem,
148
+ });
149
+ });
150
+
151
+ emitMutation({ type: 'add', tableName, keys: [localId] });
152
+ return result;
153
+ };
154
+
155
+ const wrappedPut = async (item: any) => {
156
+ let localId = item._localId;
157
+ if (!localId) localId = createLocalId();
158
+
159
+ const syncedItem = {
160
+ ...item,
161
+ _localId: localId,
162
+ updated_at: new Date().toISOString(),
163
+ };
164
+
165
+ let result: any;
166
+ let isUpdate = false;
167
+ let existingRecord: any;
168
+
169
+ await withTransaction('rw', [tableName, DYNC_STATE_TABLE], async (tables) => {
170
+ const txTable = tables[tableName]!;
171
+ existingRecord = await txTable.get(localId);
172
+ isUpdate = !!existingRecord;
173
+
174
+ result = await rawPut(syncedItem);
175
+
176
+ await state.addPendingChange({
177
+ action: isUpdate ? SyncAction.Update : SyncAction.Create,
178
+ stateKey: tableName,
179
+ localId,
180
+ id: existingRecord?.id,
181
+ changes: syncedItem,
182
+ before: existingRecord ?? null,
183
+ after: syncedItem,
184
+ });
185
+ });
186
+
187
+ emitMutation({ type: isUpdate ? 'update' : 'add', tableName, keys: [localId] });
188
+ return result;
189
+ };
190
+
191
+ const wrappedUpdate = async (key: any, changes: any) => {
192
+ const updatedChanges = {
193
+ ...changes,
194
+ updated_at: new Date().toISOString(),
195
+ };
196
+
197
+ let result = 0;
198
+ await withTransaction('rw', [tableName, DYNC_STATE_TABLE], async (tables) => {
199
+ const txTable = tables[tableName]!;
200
+ const record = await txTable.get(key);
201
+ if (!record) {
202
+ throw new Error(`Record with key=${key} not found`);
203
+ }
204
+
205
+ result = (await rawUpdate(key, updatedChanges as any)) ?? 0;
206
+ if (result > 0) {
207
+ await state.addPendingChange({
208
+ action: SyncAction.Update,
209
+ stateKey: tableName,
210
+ localId: key,
211
+ id: record.id,
212
+ changes: updatedChanges,
213
+ before: record,
214
+ after: { ...record, ...updatedChanges },
215
+ });
216
+ }
217
+ });
218
+
219
+ if (result > 0) {
220
+ emitMutation({ type: 'update', tableName, keys: [key] });
221
+ }
222
+ return result;
223
+ };
224
+
225
+ const wrappedDelete = async (key: any) => {
226
+ let deletedLocalId: string | undefined;
227
+ await withTransaction('rw', [tableName, DYNC_STATE_TABLE], async (tables) => {
228
+ const txTable = tables[tableName]!;
229
+ const record = await txTable.get(key);
230
+
231
+ await rawDelete(key);
232
+
233
+ if (record) {
234
+ deletedLocalId = record._localId;
235
+ await state.addPendingChange({
236
+ action: SyncAction.Remove,
237
+ stateKey: tableName,
238
+ localId: record._localId,
239
+ id: record.id,
240
+ changes: null,
241
+ before: record,
242
+ });
243
+ }
244
+ });
245
+
246
+ if (deletedLocalId) {
247
+ emitMutation({ type: 'delete', tableName, keys: [deletedLocalId] });
248
+ }
249
+ };
250
+
251
+ const wrappedBulkAdd = async (items: any[]) => {
252
+ if (items.length === 0) return;
253
+
254
+ const now = new Date().toISOString();
255
+ const syncedItems = items.map((item) => {
256
+ const localId = item._localId || createLocalId();
257
+ return {
258
+ ...item,
259
+ _localId: localId,
260
+ updated_at: now,
261
+ };
262
+ });
263
+
264
+ let result: any;
265
+ await withTransaction('rw', [tableName, DYNC_STATE_TABLE], async () => {
266
+ result = await rawBulkAdd(syncedItems);
267
+
268
+ for (const syncedItem of syncedItems) {
269
+ await state.addPendingChange({
270
+ action: SyncAction.Create,
271
+ stateKey: tableName,
272
+ localId: syncedItem._localId,
273
+ changes: syncedItem,
274
+ before: null,
275
+ after: syncedItem,
276
+ });
277
+ }
278
+ });
279
+
280
+ emitMutation({ type: 'add', tableName, keys: syncedItems.map((i) => i._localId) });
281
+ return result;
282
+ };
283
+
284
+ const wrappedBulkPut = async (items: any[]) => {
285
+ if (items.length === 0) return;
286
+
287
+ const now = new Date().toISOString();
288
+ const syncedItems = items.map((item) => {
289
+ const localId = item._localId || createLocalId();
290
+ return {
291
+ ...item,
292
+ _localId: localId,
293
+ updated_at: now,
294
+ };
295
+ });
296
+ const localIds = syncedItems.map((i) => i._localId);
297
+
298
+ let result: any;
299
+ await withTransaction('rw', [tableName, DYNC_STATE_TABLE], async (tables) => {
300
+ const txTable = tables[tableName]!;
301
+
302
+ // Check which items already exist
303
+ const existingRecords = await txTable.bulkGet(localIds);
304
+ const existingMap = new Map<string, any>();
305
+ for (let i = 0; i < localIds.length; i++) {
306
+ if (existingRecords[i]) {
307
+ existingMap.set(localIds[i], existingRecords[i]);
308
+ }
309
+ }
310
+
311
+ result = await rawBulkPut(syncedItems);
312
+
313
+ for (const syncedItem of syncedItems) {
314
+ const existing = existingMap.get(syncedItem._localId);
315
+ await state.addPendingChange({
316
+ action: existing ? SyncAction.Update : SyncAction.Create,
317
+ stateKey: tableName,
318
+ localId: syncedItem._localId,
319
+ id: existing?.id,
320
+ changes: syncedItem,
321
+ before: existing ?? null,
322
+ after: syncedItem,
323
+ });
324
+ }
325
+ });
326
+
327
+ emitMutation({ type: 'update', tableName, keys: localIds });
328
+ return result;
329
+ };
330
+
331
+ const wrappedBulkUpdate = async (keysAndChanges: Array<{ key: any; changes: any }>) => {
332
+ if (keysAndChanges.length === 0) return 0;
333
+
334
+ const now = new Date().toISOString();
335
+ const updatedKeysAndChanges = keysAndChanges.map(({ key, changes }) => ({
336
+ key,
337
+ changes: {
338
+ ...changes,
339
+ updated_at: now,
340
+ },
341
+ }));
342
+
343
+ let result = 0;
344
+ const updatedKeys: string[] = [];
345
+
346
+ await withTransaction('rw', [tableName, DYNC_STATE_TABLE], async (tables) => {
347
+ const txTable = tables[tableName]!;
348
+
349
+ // Get all records before updating
350
+ const keys = updatedKeysAndChanges.map((kc) => kc.key);
351
+ const records = await txTable.bulkGet(keys);
352
+ const recordMap = new Map<string, any>();
353
+ for (let i = 0; i < keys.length; i++) {
354
+ if (records[i]) {
355
+ recordMap.set(String(keys[i]), records[i]);
356
+ }
357
+ }
358
+
359
+ result = await rawBulkUpdate(updatedKeysAndChanges);
360
+
361
+ for (const { key, changes } of updatedKeysAndChanges) {
362
+ const record = recordMap.get(String(key));
363
+ if (record) {
364
+ updatedKeys.push(record._localId);
365
+ await state.addPendingChange({
366
+ action: SyncAction.Update,
367
+ stateKey: tableName,
368
+ localId: record._localId,
369
+ id: record.id,
370
+ changes,
371
+ before: record,
372
+ after: { ...record, ...changes },
373
+ });
374
+ }
375
+ }
376
+ });
377
+
378
+ if (updatedKeys.length > 0) {
379
+ emitMutation({ type: 'update', tableName, keys: updatedKeys });
380
+ }
381
+ return result;
382
+ };
383
+
384
+ const wrappedBulkDelete = async (keys: any[]) => {
385
+ if (keys.length === 0) return;
386
+
387
+ const deletedLocalIds: string[] = [];
388
+ await withTransaction('rw', [tableName, DYNC_STATE_TABLE], async (tables) => {
389
+ const txTable = tables[tableName]!;
390
+
391
+ // Get all records before deleting
392
+ const records = await txTable.bulkGet(keys);
393
+
394
+ await rawBulkDelete(keys);
395
+
396
+ for (const record of records) {
397
+ if (record) {
398
+ deletedLocalIds.push(record._localId);
399
+ await state.addPendingChange({
400
+ action: SyncAction.Remove,
401
+ stateKey: tableName,
402
+ localId: record._localId,
403
+ id: record.id,
404
+ changes: null,
405
+ before: record,
406
+ });
407
+ }
408
+ }
409
+ });
410
+
411
+ if (deletedLocalIds.length > 0) {
412
+ emitMutation({ type: 'delete', tableName, keys: deletedLocalIds });
413
+ }
414
+ };
415
+
416
+ const wrappedClear = async () => {
417
+ const deletedLocalIds: string[] = [];
418
+ await withTransaction('rw', [tableName, DYNC_STATE_TABLE], async (tables) => {
419
+ const txTable = tables[tableName]!;
420
+
421
+ // Get all records before clearing
422
+ const allRecords = await txTable.toArray();
423
+
424
+ await rawClear();
425
+
426
+ for (const record of allRecords) {
427
+ if (record._localId) {
428
+ deletedLocalIds.push(record._localId);
429
+ await state.addPendingChange({
430
+ action: SyncAction.Remove,
431
+ stateKey: tableName,
432
+ localId: record._localId,
433
+ id: record.id,
434
+ changes: null,
435
+ before: record,
436
+ });
437
+ }
438
+ }
439
+ });
440
+
441
+ if (deletedLocalIds.length > 0) {
442
+ emitMutation({ type: 'delete', tableName, keys: deletedLocalIds });
443
+ }
444
+ };
445
+
446
+ table.add = wrappedAdd;
447
+ table.put = wrappedPut;
448
+ table.update = wrappedUpdate;
449
+ table.delete = wrappedDelete;
450
+ table.bulkAdd = wrappedBulkAdd;
451
+ table.bulkPut = wrappedBulkPut;
452
+ table.bulkUpdate = wrappedBulkUpdate;
453
+ table.bulkDelete = wrappedBulkDelete;
454
+ table.clear = wrappedClear;
455
+
456
+ enhancedTables.add(tableName);
457
+ }
@@ -0,0 +1,3 @@
1
+ import type { StorageTable, TransactionMode } from '../storage/types';
2
+
3
+ export type WithTransaction = <T>(mode: TransactionMode, tableNames: string[], fn: (tables: Record<string, StorageTable<any>>) => Promise<T>) => Promise<T>;
@@ -0,0 +1,8 @@
1
+ import * as Crypto from 'expo-crypto';
2
+
3
+ export function createLocalId(): string {
4
+ if (Crypto.randomUUID) {
5
+ return Crypto.randomUUID();
6
+ }
7
+ throw new Error('createLocalId(): expo-crypto randomUUID is not available');
8
+ }
@@ -0,0 +1,6 @@
1
+ export function createLocalId(): string {
2
+ if (typeof globalThis.crypto?.randomUUID === 'function') {
3
+ return globalThis.crypto.randomUUID();
4
+ }
5
+ throw new Error('createLocalId(): crypto.randomUUID is not available');
6
+ }
package/src/dexie.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { DexieAdapter, DexieQueryContext } from './storage/dexie';
2
+ export type { StorageAdapter } from './storage/types';
@@ -0,0 +1,2 @@
1
+ export { ExpoSQLiteDriver } from './storage/sqlite/drivers/ExpoSQLiteDriver.native';
2
+ export type { SQLiteDatabaseDriver, SQLiteQueryResult, SQLiteRunResult } from './storage/sqlite/types';
package/src/helpers.ts ADDED
@@ -0,0 +1,87 @@
1
+ import { SyncAction } from './types';
2
+ import { createLocalId } from './createLocalId';
3
+
4
+ export { createLocalId };
5
+
6
+ export function sleep(ms: number, signal?: AbortSignal): Promise<void> {
7
+ return new Promise((resolve) => {
8
+ if (signal?.aborted) {
9
+ resolve();
10
+ return;
11
+ }
12
+ const timer = setTimeout(resolve, ms);
13
+ signal?.addEventListener('abort', () => {
14
+ clearTimeout(timer);
15
+ resolve();
16
+ });
17
+ });
18
+ }
19
+
20
+ export function changeKeysTo(input: any | any[], toIdKey: string, toUpdatedAtKey: string, toDeletedKey: string) {
21
+ if (!input) return input;
22
+ const isArray = Array.isArray(input);
23
+ const result = (isArray ? input : [input]).map((item) => {
24
+ const { id, updated_at, deleted, ...rest } = item;
25
+ return {
26
+ [toIdKey]: id,
27
+ [toUpdatedAtKey]: updated_at,
28
+ [toDeletedKey]: deleted,
29
+ ...rest,
30
+ };
31
+ });
32
+ return isArray ? result : result[0];
33
+ }
34
+
35
+ export function changeKeysFrom(input: any | any[], fromIdKey: string, fromUpdatedAtKey: string, fromDeletedKey: string) {
36
+ if (!input) return input;
37
+ const isArray = Array.isArray(input);
38
+ const result = (isArray ? input : [input]).map((item) => {
39
+ const { [fromIdKey]: id, [fromUpdatedAtKey]: updated_at, [fromDeletedKey]: deleted, ...rest } = item;
40
+ return {
41
+ id,
42
+ updated_at,
43
+ deleted,
44
+ ...rest,
45
+ };
46
+ });
47
+ return isArray ? result : result[0];
48
+ }
49
+
50
+ export function orderFor(a: SyncAction): number {
51
+ switch (a) {
52
+ case SyncAction.Create:
53
+ return 1;
54
+ case SyncAction.Update:
55
+ return 2;
56
+ case SyncAction.Remove:
57
+ return 3;
58
+ }
59
+ }
60
+
61
+ export function omitFields(item: any, fields: string[]) {
62
+ const result = { ...item };
63
+ for (const k of fields) delete result[k];
64
+ return result;
65
+ }
66
+
67
+ export function addOnSetDo(obj: any, key: string, fn: (v: any) => void): void {
68
+ let value = obj[key];
69
+
70
+ Object.defineProperty(obj, key, {
71
+ get() {
72
+ return value;
73
+ },
74
+ set(newVal) {
75
+ value = newVal;
76
+ fn(value);
77
+ },
78
+ enumerable: true,
79
+ configurable: false,
80
+ });
81
+ }
82
+
83
+ export function deleteKeyIfEmptyObject(obj: any, key: string) {
84
+ if (obj[key] && Object.keys(obj[key]).length === 0) {
85
+ delete obj[key];
86
+ }
87
+ }
@@ -0,0 +1,28 @@
1
+ export * from './index.shared';
2
+ export { MemoryAdapter } from './storage/memory';
3
+ export { SQLiteAdapter } from './storage/sqlite';
4
+ export { MemoryQueryContext } from './storage/memory';
5
+ export { SqliteQueryContext } from './storage/sqlite';
6
+ export type { SQLiteDatabaseDriver, SQLiteQueryResult, SQLiteRunResult } from './storage/sqlite/types';
7
+ export type { StorageAdapter } from './storage/types';
8
+ export { SyncAction } from './types';
9
+ export { createLocalId } from './helpers';
10
+
11
+ export type {
12
+ AfterRemoteAddCallback,
13
+ ApiFunctions,
14
+ BatchSync,
15
+ BatchPushPayload,
16
+ BatchPushResult,
17
+ BatchFirstLoadResult,
18
+ ConflictResolutionStrategy,
19
+ FirstLoadProgress,
20
+ FirstLoadProgressCallback,
21
+ MissingRemoteRecordStrategy,
22
+ MissingRemoteRecordDuringUpdateCallback,
23
+ MutationEvent,
24
+ SyncOptions,
25
+ SyncState,
26
+ SyncedRecord,
27
+ TableMap,
28
+ } from './types';