@anfenn/dync 1.0.26 → 1.0.28

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.
@@ -1,5 +1,5 @@
1
- import { b as SyncApi, k as SyncState } from '../types-BgGGLrE9.cjs';
2
- import '../dexie-DtgGGM68.cjs';
1
+ import { a as SyncApi, k as SyncState } from '../types-9I2fmDbU.cjs';
2
+ import '../dexie-T9m1mP1h.cjs';
3
3
  import 'dexie';
4
4
  import '../types-CSbIAfu2.cjs';
5
5
 
@@ -1,5 +1,5 @@
1
- import { b as SyncApi, k as SyncState } from '../types-B1Vn8_DF.js';
2
- import '../dexie-B1FuZqDB.js';
1
+ import { a as SyncApi, k as SyncState } from '../types-DLFva7gq.js';
2
+ import '../dexie-BFPA0JU2.js';
3
3
  import 'dexie';
4
4
  import '../types-CSbIAfu2.js';
5
5
 
@@ -1,4 +1,4 @@
1
- import { b as StorageTable } from './dexie-DtgGGM68.cjs';
1
+ import { d as StorageAdapter, a as StorageTable } from './dexie-T9m1mP1h.cjs';
2
2
 
3
3
  type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';
4
4
  interface Logger {
@@ -94,6 +94,12 @@ interface SyncOptions {
94
94
  onAfterMissingRemoteRecordDuringUpdate?: MissingRemoteRecordDuringUpdateCallback;
95
95
  conflictResolutionStrategy?: ConflictResolutionStrategy;
96
96
  }
97
+ interface DyncOptions<TStoreMap extends Record<string, any> = Record<string, any>> {
98
+ databaseName: string;
99
+ storageAdapter: StorageAdapter;
100
+ sync: Partial<Record<keyof TStoreMap, ApiFunctions>> | BatchSync;
101
+ options?: SyncOptions;
102
+ }
97
103
  interface FirstLoadProgress {
98
104
  table: string;
99
105
  inserted: number;
@@ -104,7 +110,6 @@ type FirstLoadProgressCallback = (progress: FirstLoadProgress) => void;
104
110
  type SyncApi = {
105
111
  enable: (enabled: boolean) => Promise<void>;
106
112
  startFirstLoad: (onProgress?: FirstLoadProgressCallback) => Promise<void>;
107
- /** Current sync state - use useSyncState() hook for reactive updates in React */
108
113
  readonly state: SyncState;
109
114
  resolveConflict: (localId: string, keepLocal: boolean) => Promise<void>;
110
115
  onStateChange: (fn: (state: SyncState) => void) => () => void;
@@ -151,8 +156,8 @@ interface FieldConflict {
151
156
  localValue: any;
152
157
  remoteValue: any;
153
158
  }
154
- type TableMap<TStoreMap extends Record<string, unknown>> = {
159
+ type TableMap<TStoreMap extends Record<string, any>> = {
155
160
  [K in keyof TStoreMap]: StorageTable<TStoreMap[K]>;
156
161
  };
157
162
 
158
- export { type ApiFunctions as A, type BatchSync as B, type ConflictResolutionStrategy as C, type FirstLoadProgress as F, type MissingRemoteRecordStrategy as M, type SyncOptions as S, type TableMap as T, type SyncStatus as a, type SyncApi as b, SyncAction as c, type AfterRemoteAddCallback as d, type BatchPushPayload as e, type BatchPushResult as f, type BatchFirstLoadResult as g, type FirstLoadProgressCallback as h, type MissingRemoteRecordDuringUpdateCallback as i, type MutationEvent as j, type SyncState as k, type SyncedRecord as l };
163
+ export { type AfterRemoteAddCallback as A, type BatchSync as B, type ConflictResolutionStrategy as C, type DyncOptions as D, type FirstLoadProgress as F, type MissingRemoteRecordStrategy as M, type SyncStatus as S, type TableMap as T, type SyncApi as a, SyncAction as b, type ApiFunctions as c, type BatchPushPayload as d, type BatchPushResult as e, type BatchFirstLoadResult as f, type FirstLoadProgressCallback as g, type MissingRemoteRecordDuringUpdateCallback as h, type MutationEvent as i, type SyncOptions as j, type SyncState as k, type SyncedRecord as l };
@@ -1,4 +1,4 @@
1
- import { b as StorageTable } from './dexie-B1FuZqDB.js';
1
+ import { d as StorageAdapter, a as StorageTable } from './dexie-BFPA0JU2.js';
2
2
 
3
3
  type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';
4
4
  interface Logger {
@@ -94,6 +94,12 @@ interface SyncOptions {
94
94
  onAfterMissingRemoteRecordDuringUpdate?: MissingRemoteRecordDuringUpdateCallback;
95
95
  conflictResolutionStrategy?: ConflictResolutionStrategy;
96
96
  }
97
+ interface DyncOptions<TStoreMap extends Record<string, any> = Record<string, any>> {
98
+ databaseName: string;
99
+ storageAdapter: StorageAdapter;
100
+ sync: Partial<Record<keyof TStoreMap, ApiFunctions>> | BatchSync;
101
+ options?: SyncOptions;
102
+ }
97
103
  interface FirstLoadProgress {
98
104
  table: string;
99
105
  inserted: number;
@@ -104,7 +110,6 @@ type FirstLoadProgressCallback = (progress: FirstLoadProgress) => void;
104
110
  type SyncApi = {
105
111
  enable: (enabled: boolean) => Promise<void>;
106
112
  startFirstLoad: (onProgress?: FirstLoadProgressCallback) => Promise<void>;
107
- /** Current sync state - use useSyncState() hook for reactive updates in React */
108
113
  readonly state: SyncState;
109
114
  resolveConflict: (localId: string, keepLocal: boolean) => Promise<void>;
110
115
  onStateChange: (fn: (state: SyncState) => void) => () => void;
@@ -151,8 +156,8 @@ interface FieldConflict {
151
156
  localValue: any;
152
157
  remoteValue: any;
153
158
  }
154
- type TableMap<TStoreMap extends Record<string, unknown>> = {
159
+ type TableMap<TStoreMap extends Record<string, any>> = {
155
160
  [K in keyof TStoreMap]: StorageTable<TStoreMap[K]>;
156
161
  };
157
162
 
158
- export { type ApiFunctions as A, type BatchSync as B, type ConflictResolutionStrategy as C, type FirstLoadProgress as F, type MissingRemoteRecordStrategy as M, type SyncOptions as S, type TableMap as T, type SyncStatus as a, type SyncApi as b, SyncAction as c, type AfterRemoteAddCallback as d, type BatchPushPayload as e, type BatchPushResult as f, type BatchFirstLoadResult as g, type FirstLoadProgressCallback as h, type MissingRemoteRecordDuringUpdateCallback as i, type MutationEvent as j, type SyncState as k, type SyncedRecord as l };
163
+ export { type AfterRemoteAddCallback as A, type BatchSync as B, type ConflictResolutionStrategy as C, type DyncOptions as D, type FirstLoadProgress as F, type MissingRemoteRecordStrategy as M, type SyncStatus as S, type TableMap as T, type SyncApi as a, SyncAction as b, type ApiFunctions as c, type BatchPushPayload as d, type BatchPushResult as e, type BatchFirstLoadResult as f, type FirstLoadProgressCallback as g, type MissingRemoteRecordDuringUpdateCallback as h, type MutationEvent as i, type SyncOptions as j, type SyncState as k, type SyncedRecord as l };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anfenn/dync",
3
- "version": "1.0.26",
3
+ "version": "1.0.28",
4
4
  "private": false,
5
5
  "description": "Write once, run IndexedDB & SQLite with sync anywhere - React, React Native, Expo, Capacitor, Electron & Node.js",
6
6
  "keywords": [
@@ -16,6 +16,7 @@ export type {
16
16
  BatchPushResult,
17
17
  BatchFirstLoadResult,
18
18
  ConflictResolutionStrategy,
19
+ DyncOptions,
19
20
  FirstLoadProgress,
20
21
  FirstLoadProgressCallback,
21
22
  MissingRemoteRecordStrategy,
@@ -3,6 +3,7 @@ import { sleep } from './helpers';
3
3
  import {
4
4
  type ApiFunctions,
5
5
  type BatchSync,
6
+ type DyncOptions,
6
7
  type SyncOptions,
7
8
  type SyncState,
8
9
  type SyncedRecord,
@@ -36,7 +37,7 @@ const DEFAULT_MIN_LOG_LEVEL: LogLevel = 'debug';
36
37
  const DEFAULT_MISSING_REMOTE_RECORD_STRATEGY: MissingRemoteRecordStrategy = 'insert-remote-record';
37
38
  const DEFAULT_CONFLICT_RESOLUTION_STRATEGY: ConflictResolutionStrategy = 'try-shallow-merge';
38
39
 
39
- class DyncBase<_TStoreMap = Record<string, any>> {
40
+ class DyncBase<_TStoreMap extends Record<string, any> = Record<string, any>> {
40
41
  private readonly adapter: StorageAdapter;
41
42
  private readonly tableCache = new Map<string, StorageTable<any>>();
42
43
  private readonly mutationWrappedTables = new Set<string>();
@@ -63,31 +64,35 @@ class DyncBase<_TStoreMap = Record<string, any>> {
63
64
  /**
64
65
  * Create a new Dync instance.
65
66
  *
66
- * Mode 1 - Per-table endpoints:
67
- * @param databaseName - Name of the database
68
- * @param syncApis - Map of table names to API functions
69
- * @param storageAdapter - Storage adapter implementation (required)
70
- * @param options - Sync options
67
+ * @example Per-table sync mode
68
+ * ```ts
69
+ * const db = new Dync<Store>({
70
+ * databaseName: 'my-app',
71
+ * storageAdapter: new SQLiteAdapter(driver),
72
+ * sync: { todos: todoSyncApi },
73
+ * });
74
+ * ```
71
75
  *
72
- * Mode 2 - Batch endpoints:
73
- * @param databaseName - Name of the database
74
- * @param batchSync - Batch sync config (syncTables, push, pull, firstLoad)
75
- * @param storageAdapter - Storage adapter implementation (required)
76
- * @param options - Sync options
76
+ * @example Batch sync mode
77
+ * ```ts
78
+ * const db = new Dync<Store>({
79
+ * databaseName: 'my-app',
80
+ * storageAdapter: new SQLiteAdapter(driver),
81
+ * sync: { syncTables: ['todos'], push, pull },
82
+ * });
83
+ * ```
77
84
  */
78
- constructor(databaseName: string, syncApis: Record<string, ApiFunctions>, storageAdapter: StorageAdapter, options?: SyncOptions);
79
- constructor(databaseName: string, batchSync: BatchSync, storageAdapter: StorageAdapter, options?: SyncOptions);
80
- constructor(databaseName: string, syncApisOrBatchSync: Record<string, ApiFunctions> | BatchSync, storageAdapter: StorageAdapter, options?: SyncOptions) {
81
- // Detect mode based on whether the second arg has sync API shape (has 'list' function)
82
- const isBatchMode = typeof (syncApisOrBatchSync as BatchSync).push === 'function';
85
+ constructor(config: DyncOptions<_TStoreMap>) {
86
+ const { databaseName, storageAdapter, sync: syncConfig, options } = config;
87
+
88
+ // Detect mode based on whether sync config has batch sync shape
89
+ const isBatchMode = typeof (syncConfig as BatchSync).push === 'function' && typeof (syncConfig as BatchSync).pull === 'function';
83
90
 
84
91
  if (isBatchMode) {
85
- // Batch mode: (databaseName, batchSync, options?)
86
- this.batchSync = syncApisOrBatchSync as BatchSync;
92
+ this.batchSync = syncConfig as BatchSync;
87
93
  this.syncedTables = new Set(this.batchSync.syncTables);
88
94
  } else {
89
- // Per-table mode: (databaseName, syncApis, options?)
90
- this.syncApis = syncApisOrBatchSync as Record<string, ApiFunctions>;
95
+ this.syncApis = syncConfig as Record<string, ApiFunctions>;
91
96
  this.syncedTables = new Set(Object.keys(this.syncApis));
92
97
  }
93
98
 
@@ -177,6 +182,19 @@ class DyncBase<_TStoreMap = Record<string, any>> {
177
182
  self.adapter.defineSchema(versionNumber, fullSchema, schemaOptions);
178
183
  self.setupEnhancedTables(Object.keys(schema));
179
184
 
185
+ // Define getters for direct table access (e.g., db.todos)
186
+ for (const tableName of Object.keys(schema)) {
187
+ if (!(tableName in self)) {
188
+ Object.defineProperty(self, tableName, {
189
+ get() {
190
+ return self.table(tableName);
191
+ },
192
+ enumerable: true,
193
+ configurable: false,
194
+ });
195
+ }
196
+ }
197
+
180
198
  return builder;
181
199
  },
182
200
  sqlite(configure: (builder: SQLiteVersionConfigurator) => void) {
@@ -590,27 +608,16 @@ class DyncBase<_TStoreMap = Record<string, any>> {
590
608
  };
591
609
  }
592
610
 
593
- type DyncInstance<TStoreMap extends Record<string, unknown> = Record<string, unknown>> = DyncBase<TStoreMap> &
611
+ type DyncInstance<TStoreMap extends Record<string, any> = Record<string, any>> = DyncBase<TStoreMap> &
594
612
  TableMap<TStoreMap> & {
595
613
  table<K extends keyof TStoreMap & string>(name: K): StorageTable<TStoreMap[K]>;
596
614
  table(name: string): StorageTable<any>;
597
615
  };
598
616
 
599
- const DyncConstructor = DyncBase as unknown as {
600
- prototype: DyncInstance<Record<string, unknown>>;
601
- new <TStoreMap extends Record<string, unknown> = Record<string, unknown>>(
602
- databaseName: string,
603
- syncApis: Record<string, ApiFunctions>,
604
- storageAdapter: StorageAdapter,
605
- options?: SyncOptions,
606
- ): DyncInstance<TStoreMap>;
607
- new <TStoreMap extends Record<string, unknown> = Record<string, unknown>>(
608
- databaseName: string,
609
- batchSync: BatchSync,
610
- storageAdapter: StorageAdapter,
611
- options?: SyncOptions,
612
- ): DyncInstance<TStoreMap>;
613
- } & typeof DyncBase;
614
-
615
- export const Dync = DyncConstructor;
616
- export type Dync<TStoreMap extends Record<string, unknown> = Record<string, unknown>> = DyncInstance<TStoreMap>;
617
+ // Export Dync as a class-like constructor with proper typing for direct table access
618
+ export const Dync = DyncBase as unknown as {
619
+ <TStoreMap extends Record<string, any> = Record<string, any>>(config: DyncOptions<TStoreMap>): DyncInstance<TStoreMap>;
620
+ new <TStoreMap extends Record<string, any> = Record<string, any>>(config: DyncOptions<TStoreMap>): DyncInstance<TStoreMap>;
621
+ };
622
+
623
+ export type Dync<TStoreMap extends Record<string, any> = Record<string, any>> = DyncInstance<TStoreMap>;
package/src/index.ts CHANGED
@@ -16,6 +16,7 @@ export type {
16
16
  BatchPushResult,
17
17
  BatchFirstLoadResult,
18
18
  ConflictResolutionStrategy,
19
+ DyncOptions,
19
20
  FirstLoadProgress,
20
21
  FirstLoadProgressCallback,
21
22
  MissingRemoteRecordStrategy,
package/src/types.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Logger, LogLevel } from './logger';
2
- import type { StorageTable } from './storage/types';
2
+ import type { StorageAdapter, StorageTable } from './storage/types';
3
3
 
4
4
  export const SERVER_PK = 'id';
5
5
  export const LOCAL_PK = '_localId';
@@ -122,6 +122,13 @@ export interface SyncOptions {
122
122
  conflictResolutionStrategy?: ConflictResolutionStrategy;
123
123
  }
124
124
 
125
+ export interface DyncOptions<TStoreMap extends Record<string, any> = Record<string, any>> {
126
+ databaseName: string;
127
+ storageAdapter: StorageAdapter;
128
+ sync: Partial<Record<keyof TStoreMap, ApiFunctions>> | BatchSync;
129
+ options?: SyncOptions;
130
+ }
131
+
125
132
  export interface FirstLoadProgress {
126
133
  table: string;
127
134
  inserted: number;
@@ -134,7 +141,7 @@ export type FirstLoadProgressCallback = (progress: FirstLoadProgress) => void;
134
141
  export type SyncApi = {
135
142
  enable: (enabled: boolean) => Promise<void>;
136
143
  startFirstLoad: (onProgress?: FirstLoadProgressCallback) => Promise<void>;
137
- /** Current sync state - use useSyncState() hook for reactive updates in React */
144
+ // Current sync state - use useSyncState() hook for reactive updates in React
138
145
  readonly state: SyncState;
139
146
  resolveConflict: (localId: string, keepLocal: boolean) => Promise<void>;
140
147
  onStateChange: (fn: (state: SyncState) => void) => () => void;
@@ -190,7 +197,7 @@ export interface FieldConflict {
190
197
  remoteValue: any;
191
198
  }
192
199
 
193
- export type TableMap<TStoreMap extends Record<string, unknown>> = {
200
+ export type TableMap<TStoreMap extends Record<string, any>> = {
194
201
  [K in keyof TStoreMap]: StorageTable<TStoreMap[K]>;
195
202
  };
196
203