@anfenn/dync 1.0.28 → 1.0.30
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/dist/index.cjs +41 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +41 -11
- package/dist/index.js.map +1 -1
- package/dist/react/index.d.cts +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/{types-9I2fmDbU.d.cts → types-DW42y281.d.cts} +1 -1
- package/dist/{types-DLFva7gq.d.ts → types-n8Zge2zF.d.ts} +1 -1
- package/package.json +6 -4
- package/src/core/tableEnhancers.ts +15 -5
- package/src/index.shared.ts +37 -9
- package/src/types.ts +1 -1
package/dist/react/index.d.cts
CHANGED
package/dist/react/index.d.ts
CHANGED
|
@@ -97,7 +97,7 @@ interface SyncOptions {
|
|
|
97
97
|
interface DyncOptions<TStoreMap extends Record<string, any> = Record<string, any>> {
|
|
98
98
|
databaseName: string;
|
|
99
99
|
storageAdapter: StorageAdapter;
|
|
100
|
-
sync
|
|
100
|
+
sync?: Partial<Record<keyof TStoreMap, ApiFunctions>> | BatchSync;
|
|
101
101
|
options?: SyncOptions;
|
|
102
102
|
}
|
|
103
103
|
interface FirstLoadProgress {
|
|
@@ -97,7 +97,7 @@ interface SyncOptions {
|
|
|
97
97
|
interface DyncOptions<TStoreMap extends Record<string, any> = Record<string, any>> {
|
|
98
98
|
databaseName: string;
|
|
99
99
|
storageAdapter: StorageAdapter;
|
|
100
|
-
sync
|
|
100
|
+
sync?: Partial<Record<keyof TStoreMap, ApiFunctions>> | BatchSync;
|
|
101
101
|
options?: SyncOptions;
|
|
102
102
|
}
|
|
103
103
|
interface FirstLoadProgress {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anfenn/dync",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
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": [
|
|
@@ -132,8 +132,8 @@
|
|
|
132
132
|
"LICENSE"
|
|
133
133
|
],
|
|
134
134
|
"scripts": {
|
|
135
|
-
"build": "pnpm
|
|
136
|
-
"build:all": "pnpm
|
|
135
|
+
"build": "pnpm format && pnpm lint && pnpm exec tsc --noEmit && tsup",
|
|
136
|
+
"build:all": "pnpm build && pnpm --filter react-capacitor build",
|
|
137
137
|
"dev": "tsup --watch",
|
|
138
138
|
"lint": "eslint . --fix \"src/**/*.{js,jsx,ts,tsx,json}\"",
|
|
139
139
|
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
|
|
@@ -142,7 +142,9 @@
|
|
|
142
142
|
"test:all": "pnpm --filter tests test:all",
|
|
143
143
|
"test:ci": "pnpm --filter tests test:ci",
|
|
144
144
|
"test:browser:full": "pnpm --filter tests test:browser:full",
|
|
145
|
-
"reinstall": "find . -name node_modules -type d -prune -exec rm -rf {} + && pnpm install"
|
|
145
|
+
"reinstall": "find . -name node_modules -type d -prune -exec rm -rf {} + && pnpm install",
|
|
146
|
+
"push": "bash -c '[ -n \"$1\" ] && git add . && git commit -m \"$1\" && git push' --",
|
|
147
|
+
"release": "bash -c '[ -n \"$1\" ] || { echo \"Usage: pnpm release <commit-message>\"; exit 1; } && pnpm build:all && pnpm test:all && pnpm test:browser:full && git add . && git commit -m \"$1\" && npm version patch && git push && git push --tags && npm publish' --"
|
|
146
148
|
},
|
|
147
149
|
"devDependencies": {
|
|
148
150
|
"@capacitor-community/sqlite": "7.0.2",
|
|
@@ -6,7 +6,7 @@ import type { WithTransaction } from './types';
|
|
|
6
6
|
export type EmitMutation = (event: MutationEvent) => void;
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Wraps a table with mutation emission for reactive updates.
|
|
9
|
+
* Wraps a table with mutation emission for reactive updates and auto-generates _localId.
|
|
10
10
|
* This allows useLiveQuery to work with any table.
|
|
11
11
|
*/
|
|
12
12
|
export function wrapWithMutationEmitter<T>(table: StorageTable<T>, tableName: string, emitMutation: EmitMutation): void {
|
|
@@ -21,13 +21,15 @@ export function wrapWithMutationEmitter<T>(table: StorageTable<T>, tableName: st
|
|
|
21
21
|
const rawClear = table.raw.clear;
|
|
22
22
|
|
|
23
23
|
table.add = async (item: AddItem<T>) => {
|
|
24
|
-
const
|
|
24
|
+
const itemWithLocalId = { ...item, _localId: (item as any)._localId || createLocalId() } as T;
|
|
25
|
+
const result = await rawAdd(itemWithLocalId);
|
|
25
26
|
emitMutation({ type: 'add', tableName, keys: [result] });
|
|
26
27
|
return result;
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
table.put = async (item: T) => {
|
|
30
|
-
const
|
|
31
|
+
const itemWithLocalId = { ...item, _localId: (item as any)._localId || createLocalId() } as T;
|
|
32
|
+
const result = await rawPut(itemWithLocalId);
|
|
31
33
|
emitMutation({ type: 'update', tableName, keys: [result] });
|
|
32
34
|
return result;
|
|
33
35
|
};
|
|
@@ -46,7 +48,11 @@ export function wrapWithMutationEmitter<T>(table: StorageTable<T>, tableName: st
|
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
table.bulkAdd = async (items: AddItem<T>[]) => {
|
|
49
|
-
const
|
|
51
|
+
const itemsWithLocalIds = items.map((item) => ({
|
|
52
|
+
...item,
|
|
53
|
+
_localId: (item as any)._localId || createLocalId(),
|
|
54
|
+
})) as T[];
|
|
55
|
+
const result = await rawBulkAdd(itemsWithLocalIds);
|
|
50
56
|
if (items.length > 0) {
|
|
51
57
|
emitMutation({ type: 'add', tableName });
|
|
52
58
|
}
|
|
@@ -54,7 +60,11 @@ export function wrapWithMutationEmitter<T>(table: StorageTable<T>, tableName: st
|
|
|
54
60
|
};
|
|
55
61
|
|
|
56
62
|
table.bulkPut = async (items: T[]) => {
|
|
57
|
-
const
|
|
63
|
+
const itemsWithLocalIds = items.map((item) => ({
|
|
64
|
+
...item,
|
|
65
|
+
_localId: (item as any)._localId || createLocalId(),
|
|
66
|
+
})) as T[];
|
|
67
|
+
const result = await rawBulkPut(itemsWithLocalIds);
|
|
58
68
|
if (items.length > 0) {
|
|
59
69
|
emitMutation({ type: 'update', tableName });
|
|
60
70
|
}
|
package/src/index.shared.ts
CHANGED
|
@@ -85,15 +85,17 @@ class DyncBase<_TStoreMap extends Record<string, any> = Record<string, any>> {
|
|
|
85
85
|
constructor(config: DyncOptions<_TStoreMap>) {
|
|
86
86
|
const { databaseName, storageAdapter, sync: syncConfig, options } = config;
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
if (syncConfig) {
|
|
89
|
+
// Detect mode based on whether sync config has batch sync shape
|
|
90
|
+
const isBatchMode = typeof syncConfig.push === 'function' && typeof syncConfig.pull === 'function';
|
|
91
|
+
|
|
92
|
+
if (isBatchMode) {
|
|
93
|
+
this.batchSync = syncConfig as BatchSync;
|
|
94
|
+
this.syncedTables = new Set(this.batchSync.syncTables);
|
|
95
|
+
} else {
|
|
96
|
+
this.syncApis = syncConfig as Record<string, ApiFunctions>;
|
|
97
|
+
this.syncedTables = new Set(Object.keys(this.syncApis));
|
|
98
|
+
}
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
this.adapter = storageAdapter;
|
|
@@ -158,6 +160,9 @@ class DyncBase<_TStoreMap extends Record<string, any> = Record<string, any>> {
|
|
|
158
160
|
// Auto-inject sync fields for sync tables
|
|
159
161
|
// Note: updated_at is indexed to support user queries like orderBy('updated_at')
|
|
160
162
|
fullSchema[tableName] = `${LOCAL_PK}, &${SERVER_PK}, ${tableSchema}, ${UPDATED_AT}`;
|
|
163
|
+
} else {
|
|
164
|
+
// Auto-inject _localId as primary key for non-sync tables
|
|
165
|
+
fullSchema[tableName] = `${LOCAL_PK}, ${tableSchema}`;
|
|
161
166
|
}
|
|
162
167
|
|
|
163
168
|
self.logger.debug(
|
|
@@ -167,6 +172,9 @@ class DyncBase<_TStoreMap extends Record<string, any> = Record<string, any>> {
|
|
|
167
172
|
if (isSyncTable) {
|
|
168
173
|
// Auto-inject sync columns for structured schemas
|
|
169
174
|
fullSchema[tableName] = self.injectSyncColumns(tableSchema);
|
|
175
|
+
} else {
|
|
176
|
+
// Auto-inject _localId column for non-sync structured schemas
|
|
177
|
+
fullSchema[tableName] = self.injectLocalIdColumn(tableSchema);
|
|
170
178
|
}
|
|
171
179
|
|
|
172
180
|
const schemaColumns = Object.keys((fullSchema[tableName] as SQLiteTableDefinition).columns ?? {}).join(', ');
|
|
@@ -350,6 +358,26 @@ class DyncBase<_TStoreMap extends Record<string, any> = Record<string, any>> {
|
|
|
350
358
|
};
|
|
351
359
|
}
|
|
352
360
|
|
|
361
|
+
private injectLocalIdColumn(schema: SQLiteTableDefinition): SQLiteTableDefinition {
|
|
362
|
+
const columns = schema.columns ?? {};
|
|
363
|
+
|
|
364
|
+
// Validate user hasn't defined reserved _localId column
|
|
365
|
+
if (columns[LOCAL_PK]) {
|
|
366
|
+
throw new Error(`Column '${LOCAL_PK}' is auto-injected and cannot be defined manually.`);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Inject _localId column as primary key
|
|
370
|
+
const injectedColumns: Record<string, any> = {
|
|
371
|
+
...columns,
|
|
372
|
+
[LOCAL_PK]: { type: 'TEXT' },
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
return {
|
|
376
|
+
...schema,
|
|
377
|
+
columns: injectedColumns,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
353
381
|
private enhanceSyncTable<T>(table: StorageTable<T & SyncedRecord>, tableName: string): void {
|
|
354
382
|
enhanceSyncTable({
|
|
355
383
|
table,
|
package/src/types.ts
CHANGED
|
@@ -125,7 +125,7 @@ export interface SyncOptions {
|
|
|
125
125
|
export interface DyncOptions<TStoreMap extends Record<string, any> = Record<string, any>> {
|
|
126
126
|
databaseName: string;
|
|
127
127
|
storageAdapter: StorageAdapter;
|
|
128
|
-
sync
|
|
128
|
+
sync?: Partial<Record<keyof TStoreMap, ApiFunctions>> | BatchSync;
|
|
129
129
|
options?: SyncOptions;
|
|
130
130
|
}
|
|
131
131
|
|