@anfenn/dync 1.0.26 → 1.0.27

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-yJuzCcux.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-BLw25Wlc.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-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,38 @@ interface SyncOptions {
94
94
  onAfterMissingRemoteRecordDuringUpdate?: MissingRemoteRecordDuringUpdateCallback;
95
95
  conflictResolutionStrategy?: ConflictResolutionStrategy;
96
96
  }
97
+ /**
98
+ * Configuration options for creating a Dync instance.
99
+ *
100
+ * @example Per-table sync mode
101
+ * ```ts
102
+ * const db = new Dync<Store>({
103
+ * databaseName: 'my-app',
104
+ * storageAdapter: new SQLiteAdapter(driver),
105
+ * sync: { todos: todoSyncApi },
106
+ * });
107
+ * ```
108
+ *
109
+ * @example Batch sync mode
110
+ * ```ts
111
+ * const db = new Dync<Store>({
112
+ * databaseName: 'my-app',
113
+ * storageAdapter: new SQLiteAdapter(driver),
114
+ * sync: { syncTables: ['todos'], push, pull },
115
+ * });
116
+ * ```
117
+ */
118
+ interface DyncOptions<TStoreMap extends Record<string, any> = Record<string, any>> {
119
+ databaseName: string;
120
+ storageAdapter: StorageAdapter;
121
+ /**
122
+ * Sync configuration - either per-table APIs or batch sync.
123
+ * Per-table: `{ tableName: { add, update, remove, list } }`
124
+ * Batch: `{ syncTables: [...], push, pull }`
125
+ */
126
+ sync: Partial<Record<keyof TStoreMap, ApiFunctions>> | BatchSync;
127
+ options?: SyncOptions;
128
+ }
97
129
  interface FirstLoadProgress {
98
130
  table: string;
99
131
  inserted: number;
@@ -151,8 +183,8 @@ interface FieldConflict {
151
183
  localValue: any;
152
184
  remoteValue: any;
153
185
  }
154
- type TableMap<TStoreMap extends Record<string, unknown>> = {
186
+ type TableMap<TStoreMap extends Record<string, any>> = {
155
187
  [K in keyof TStoreMap]: StorageTable<TStoreMap[K]>;
156
188
  };
157
189
 
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 };
190
+ 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-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,38 @@ interface SyncOptions {
94
94
  onAfterMissingRemoteRecordDuringUpdate?: MissingRemoteRecordDuringUpdateCallback;
95
95
  conflictResolutionStrategy?: ConflictResolutionStrategy;
96
96
  }
97
+ /**
98
+ * Configuration options for creating a Dync instance.
99
+ *
100
+ * @example Per-table sync mode
101
+ * ```ts
102
+ * const db = new Dync<Store>({
103
+ * databaseName: 'my-app',
104
+ * storageAdapter: new SQLiteAdapter(driver),
105
+ * sync: { todos: todoSyncApi },
106
+ * });
107
+ * ```
108
+ *
109
+ * @example Batch sync mode
110
+ * ```ts
111
+ * const db = new Dync<Store>({
112
+ * databaseName: 'my-app',
113
+ * storageAdapter: new SQLiteAdapter(driver),
114
+ * sync: { syncTables: ['todos'], push, pull },
115
+ * });
116
+ * ```
117
+ */
118
+ interface DyncOptions<TStoreMap extends Record<string, any> = Record<string, any>> {
119
+ databaseName: string;
120
+ storageAdapter: StorageAdapter;
121
+ /**
122
+ * Sync configuration - either per-table APIs or batch sync.
123
+ * Per-table: `{ tableName: { add, update, remove, list } }`
124
+ * Batch: `{ syncTables: [...], push, pull }`
125
+ */
126
+ sync: Partial<Record<keyof TStoreMap, ApiFunctions>> | BatchSync;
127
+ options?: SyncOptions;
128
+ }
97
129
  interface FirstLoadProgress {
98
130
  table: string;
99
131
  inserted: number;
@@ -151,8 +183,8 @@ interface FieldConflict {
151
183
  localValue: any;
152
184
  remoteValue: any;
153
185
  }
154
- type TableMap<TStoreMap extends Record<string, unknown>> = {
186
+ type TableMap<TStoreMap extends Record<string, any>> = {
155
187
  [K in keyof TStoreMap]: StorageTable<TStoreMap[K]>;
156
188
  };
157
189
 
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 };
190
+ 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.27",
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,39 @@ export interface SyncOptions {
122
122
  conflictResolutionStrategy?: ConflictResolutionStrategy;
123
123
  }
124
124
 
125
+ /**
126
+ * Configuration options for creating a Dync instance.
127
+ *
128
+ * @example Per-table sync mode
129
+ * ```ts
130
+ * const db = new Dync<Store>({
131
+ * databaseName: 'my-app',
132
+ * storageAdapter: new SQLiteAdapter(driver),
133
+ * sync: { todos: todoSyncApi },
134
+ * });
135
+ * ```
136
+ *
137
+ * @example Batch sync mode
138
+ * ```ts
139
+ * const db = new Dync<Store>({
140
+ * databaseName: 'my-app',
141
+ * storageAdapter: new SQLiteAdapter(driver),
142
+ * sync: { syncTables: ['todos'], push, pull },
143
+ * });
144
+ * ```
145
+ */
146
+ export interface DyncOptions<TStoreMap extends Record<string, any> = Record<string, any>> {
147
+ databaseName: string;
148
+ storageAdapter: StorageAdapter;
149
+ /**
150
+ * Sync configuration - either per-table APIs or batch sync.
151
+ * Per-table: `{ tableName: { add, update, remove, list } }`
152
+ * Batch: `{ syncTables: [...], push, pull }`
153
+ */
154
+ sync: Partial<Record<keyof TStoreMap, ApiFunctions>> | BatchSync;
155
+ options?: SyncOptions;
156
+ }
157
+
125
158
  export interface FirstLoadProgress {
126
159
  table: string;
127
160
  inserted: number;
@@ -190,7 +223,7 @@ export interface FieldConflict {
190
223
  remoteValue: any;
191
224
  }
192
225
 
193
- export type TableMap<TStoreMap extends Record<string, unknown>> = {
226
+ export type TableMap<TStoreMap extends Record<string, any>> = {
194
227
  [K in keyof TStoreMap]: StorageTable<TStoreMap[K]>;
195
228
  };
196
229