@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.
- package/LICENSE +21 -0
- package/README.md +212 -0
- package/dist/capacitor.cjs +228 -0
- package/dist/capacitor.cjs.map +1 -0
- package/dist/capacitor.d.cts +62 -0
- package/dist/capacitor.d.ts +62 -0
- package/dist/capacitor.js +9 -0
- package/dist/capacitor.js.map +1 -0
- package/dist/chunk-LGHOZECP.js +3884 -0
- package/dist/chunk-LGHOZECP.js.map +1 -0
- package/dist/chunk-SQB6E7V2.js +191 -0
- package/dist/chunk-SQB6E7V2.js.map +1 -0
- package/dist/dexie-Bv-fV10P.d.cts +444 -0
- package/dist/dexie-DJFApKsM.d.ts +444 -0
- package/dist/dexie.cjs +381 -0
- package/dist/dexie.cjs.map +1 -0
- package/dist/dexie.d.cts +3 -0
- package/dist/dexie.d.ts +3 -0
- package/dist/dexie.js +343 -0
- package/dist/dexie.js.map +1 -0
- package/dist/expoSqlite.cjs +98 -0
- package/dist/expoSqlite.cjs.map +1 -0
- package/dist/expoSqlite.d.cts +17 -0
- package/dist/expoSqlite.d.ts +17 -0
- package/dist/expoSqlite.js +61 -0
- package/dist/expoSqlite.js.map +1 -0
- package/dist/index.cjs +3916 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/index.shared-CPIge2ZM.d.ts +234 -0
- package/dist/index.shared-YSn6c01d.d.cts +234 -0
- package/dist/node.cjs +126 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +80 -0
- package/dist/node.d.ts +80 -0
- package/dist/node.js +89 -0
- package/dist/node.js.map +1 -0
- package/dist/react/index.cjs +1754 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +40 -0
- package/dist/react/index.d.ts +40 -0
- package/dist/react/index.js +78 -0
- package/dist/react/index.js.map +1 -0
- package/dist/types-CSbIAfu2.d.cts +46 -0
- package/dist/types-CSbIAfu2.d.ts +46 -0
- package/dist/wa-sqlite.cjs +318 -0
- package/dist/wa-sqlite.cjs.map +1 -0
- package/dist/wa-sqlite.d.cts +175 -0
- package/dist/wa-sqlite.d.ts +175 -0
- package/dist/wa-sqlite.js +281 -0
- package/dist/wa-sqlite.js.map +1 -0
- package/package.json +171 -0
- package/src/addVisibilityChangeListener.native.ts +33 -0
- package/src/addVisibilityChangeListener.ts +24 -0
- package/src/capacitor.ts +4 -0
- package/src/core/StateManager.ts +272 -0
- package/src/core/firstLoad.ts +332 -0
- package/src/core/pullOperations.ts +212 -0
- package/src/core/pushOperations.ts +290 -0
- package/src/core/tableEnhancers.ts +457 -0
- package/src/core/types.ts +3 -0
- package/src/createLocalId.native.ts +8 -0
- package/src/createLocalId.ts +6 -0
- package/src/dexie.ts +2 -0
- package/src/expoSqlite.ts +2 -0
- package/src/helpers.ts +87 -0
- package/src/index.native.ts +28 -0
- package/src/index.shared.ts +613 -0
- package/src/index.ts +28 -0
- package/src/logger.ts +26 -0
- package/src/node.ts +4 -0
- package/src/react/index.ts +2 -0
- package/src/react/useDync.ts +156 -0
- package/src/storage/dexie/DexieAdapter.ts +72 -0
- package/src/storage/dexie/DexieQueryContext.ts +14 -0
- package/src/storage/dexie/DexieStorageCollection.ts +124 -0
- package/src/storage/dexie/DexieStorageTable.ts +123 -0
- package/src/storage/dexie/DexieStorageWhereClause.ts +103 -0
- package/src/storage/dexie/helpers.ts +1 -0
- package/src/storage/dexie/index.ts +7 -0
- package/src/storage/memory/MemoryAdapter.ts +55 -0
- package/src/storage/memory/MemoryCollection.ts +215 -0
- package/src/storage/memory/MemoryQueryContext.ts +14 -0
- package/src/storage/memory/MemoryTable.ts +336 -0
- package/src/storage/memory/MemoryWhereClause.ts +134 -0
- package/src/storage/memory/index.ts +7 -0
- package/src/storage/memory/types.ts +24 -0
- package/src/storage/sqlite/SQLiteAdapter.ts +564 -0
- package/src/storage/sqlite/SQLiteCollection.ts +294 -0
- package/src/storage/sqlite/SQLiteTable.ts +604 -0
- package/src/storage/sqlite/SQLiteWhereClause.ts +341 -0
- package/src/storage/sqlite/SqliteQueryContext.ts +30 -0
- package/src/storage/sqlite/drivers/BetterSqlite3Driver.ts +156 -0
- package/src/storage/sqlite/drivers/CapacitorFastSqlDriver.ts +114 -0
- package/src/storage/sqlite/drivers/CapacitorSQLiteDriver.ts +137 -0
- package/src/storage/sqlite/drivers/ExpoSQLiteDriver.native.ts +67 -0
- package/src/storage/sqlite/drivers/WaSqliteDriver.ts +537 -0
- package/src/storage/sqlite/drivers/wa-sqlite-vfs.d.ts +46 -0
- package/src/storage/sqlite/helpers.ts +144 -0
- package/src/storage/sqlite/index.ts +11 -0
- package/src/storage/sqlite/schema.ts +44 -0
- package/src/storage/sqlite/types.ts +164 -0
- package/src/storage/types.ts +112 -0
- package/src/types.ts +186 -0
- package/src/wa-sqlite.ts +4 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { SQLiteConnection, SQLiteDBConnection } from '@capacitor-community/sqlite';
|
|
2
|
+
import type { SQLiteDatabaseDriver, SQLiteRunResult, SQLiteQueryResult } from '../types';
|
|
3
|
+
|
|
4
|
+
// Lazily loaded module cache to avoid top-level imports that break web bundlers
|
|
5
|
+
let sqliteModuleCache: typeof import('@capacitor-community/sqlite') | null = null;
|
|
6
|
+
|
|
7
|
+
async function getSqliteModule(): Promise<typeof import('@capacitor-community/sqlite')> {
|
|
8
|
+
if (!sqliteModuleCache) {
|
|
9
|
+
sqliteModuleCache = await import('@capacitor-community/sqlite');
|
|
10
|
+
}
|
|
11
|
+
return sqliteModuleCache;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface CapacitorSQLiteDriverOptions {
|
|
15
|
+
encrypted?: boolean;
|
|
16
|
+
getEncryptionKey?: () => string;
|
|
17
|
+
readonly?: boolean;
|
|
18
|
+
mode?: string;
|
|
19
|
+
version?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class CapacitorSQLiteDriver implements SQLiteDatabaseDriver {
|
|
23
|
+
readonly type = 'CapacitorSQLiteDriver';
|
|
24
|
+
private connectionFactory?: SQLiteConnection;
|
|
25
|
+
private readonly config: CapacitorSQLiteDriverOptions;
|
|
26
|
+
private db?: SQLiteDBConnection;
|
|
27
|
+
private openPromise?: Promise<void>;
|
|
28
|
+
private opened = false;
|
|
29
|
+
readonly name: string;
|
|
30
|
+
|
|
31
|
+
constructor(databaseName: string, config: CapacitorSQLiteDriverOptions = {}) {
|
|
32
|
+
this.name = databaseName;
|
|
33
|
+
this.config = config;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private async getConnectionFactory(): Promise<SQLiteConnection> {
|
|
37
|
+
if (!this.connectionFactory) {
|
|
38
|
+
const { CapacitorSQLite, SQLiteConnection } = await getSqliteModule();
|
|
39
|
+
this.connectionFactory = new SQLiteConnection(CapacitorSQLite);
|
|
40
|
+
}
|
|
41
|
+
return this.connectionFactory;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private async ensureDb(): Promise<SQLiteDBConnection> {
|
|
45
|
+
if (!this.db) {
|
|
46
|
+
const connectionFactory = await this.getConnectionFactory();
|
|
47
|
+
const readonly = this.config.readonly ?? false;
|
|
48
|
+
|
|
49
|
+
// Check if a connection already exists (e.g., after page reload)
|
|
50
|
+
const existsResult = await connectionFactory.isConnection(this.name, readonly);
|
|
51
|
+
if (existsResult.result) {
|
|
52
|
+
// Connection exists - retrieve it instead of creating a new one
|
|
53
|
+
this.db = await connectionFactory.retrieveConnection(this.name, readonly);
|
|
54
|
+
} else {
|
|
55
|
+
// Close any stale native connection (e.g., after page reload) before creating
|
|
56
|
+
await connectionFactory.closeConnection(this.name, readonly).catch(() => {});
|
|
57
|
+
this.db = await connectionFactory.createConnection(
|
|
58
|
+
this.name,
|
|
59
|
+
this.config.encrypted ?? false,
|
|
60
|
+
this.config.mode ?? 'no-encryption',
|
|
61
|
+
this.config.version ?? 1,
|
|
62
|
+
readonly,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// New/retrieved connection means we need to (re)open it.
|
|
67
|
+
this.opened = false;
|
|
68
|
+
}
|
|
69
|
+
return this.db;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async open(): Promise<void> {
|
|
73
|
+
if (this.opened) return;
|
|
74
|
+
if (this.openPromise) return this.openPromise;
|
|
75
|
+
|
|
76
|
+
this.openPromise = (async () => {
|
|
77
|
+
const connectionFactory = await this.getConnectionFactory();
|
|
78
|
+
// Set encryption secret if provided and not already stored (must be done before opening)
|
|
79
|
+
if (this.config.getEncryptionKey) {
|
|
80
|
+
const { result: isStored } = await connectionFactory.isSecretStored();
|
|
81
|
+
if (!isStored) {
|
|
82
|
+
const key = this.config.getEncryptionKey();
|
|
83
|
+
if (!key && this.config.encrypted) {
|
|
84
|
+
throw new Error('CapacitorSQLiteDriverOptions.encrypted=true but no encryption key was provided (getEncryptionKey).');
|
|
85
|
+
}
|
|
86
|
+
await connectionFactory.setEncryptionSecret(key);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const db = await this.ensureDb();
|
|
90
|
+
await db.open();
|
|
91
|
+
this.opened = true;
|
|
92
|
+
})();
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
await this.openPromise;
|
|
96
|
+
} finally {
|
|
97
|
+
this.openPromise = undefined;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async close(): Promise<void> {
|
|
102
|
+
if (!this.db) return;
|
|
103
|
+
await this.db.close();
|
|
104
|
+
const connectionFactory = await this.getConnectionFactory();
|
|
105
|
+
await connectionFactory.closeConnection(this.name, this.config.readonly ?? false);
|
|
106
|
+
this.db = undefined;
|
|
107
|
+
this.opened = false;
|
|
108
|
+
this.openPromise = undefined;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async execute(statement: string): Promise<void> {
|
|
112
|
+
await this.open();
|
|
113
|
+
const db = await this.ensureDb();
|
|
114
|
+
await db.execute(statement, false);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async run(statement: string, values: any[] = []): Promise<SQLiteRunResult> {
|
|
118
|
+
await this.open();
|
|
119
|
+
const db = await this.ensureDb();
|
|
120
|
+
const result = await db.run(statement, values, false, 'no');
|
|
121
|
+
const changes = (result as any)?.changes?.changes ?? (result as any)?.changes ?? 0;
|
|
122
|
+
const lastId = (result as any)?.changes?.lastId ?? undefined;
|
|
123
|
+
return { changes, lastId };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async query(statement: string, values: any[] = []): Promise<SQLiteQueryResult> {
|
|
127
|
+
await this.open();
|
|
128
|
+
const db = await this.ensureDb();
|
|
129
|
+
const result: any = await db.query(statement, values, true);
|
|
130
|
+
if (Array.isArray(result?.values) && result.values.length > 0 && !Array.isArray(result.values[0])) {
|
|
131
|
+
const columns = Object.keys(result.values[0]);
|
|
132
|
+
const rows = result.values.map((row: Record<string, any>) => columns.map((column) => row[column]));
|
|
133
|
+
return { columns, values: rows };
|
|
134
|
+
}
|
|
135
|
+
return { columns: result?.columns ?? [], values: result?.values ?? [] };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as SQLite from 'expo-sqlite';
|
|
2
|
+
|
|
3
|
+
import type { SQLiteDatabaseDriver, SQLiteQueryResult, SQLiteRunResult } from '../types';
|
|
4
|
+
|
|
5
|
+
export class ExpoSQLiteDriver implements SQLiteDatabaseDriver {
|
|
6
|
+
readonly type = 'ExpoSQLiteDriver';
|
|
7
|
+
private db: SQLite.SQLiteDatabase | null = null;
|
|
8
|
+
private openPromise?: Promise<void>;
|
|
9
|
+
private opened = false;
|
|
10
|
+
readonly name: string;
|
|
11
|
+
|
|
12
|
+
constructor(name: string) {
|
|
13
|
+
this.name = name;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async open(): Promise<void> {
|
|
17
|
+
if (this.opened) return;
|
|
18
|
+
if (this.openPromise) return this.openPromise;
|
|
19
|
+
|
|
20
|
+
this.openPromise = (async () => {
|
|
21
|
+
if (!this.db) {
|
|
22
|
+
this.db = await SQLite.openDatabaseAsync(this.name);
|
|
23
|
+
this.opened = true;
|
|
24
|
+
}
|
|
25
|
+
})();
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
await this.openPromise;
|
|
29
|
+
} finally {
|
|
30
|
+
this.openPromise = undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async close(): Promise<void> {
|
|
35
|
+
const db = this.db;
|
|
36
|
+
this.db = null;
|
|
37
|
+
this.opened = false;
|
|
38
|
+
this.openPromise = undefined;
|
|
39
|
+
if (db?.closeAsync) {
|
|
40
|
+
await db.closeAsync();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async execute(statement: string): Promise<void> {
|
|
45
|
+
await this.run(statement, []);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async run(statement: string, values: any[] = []): Promise<SQLiteRunResult> {
|
|
49
|
+
await this.open();
|
|
50
|
+
const db = this.db!;
|
|
51
|
+
const result = await db.runAsync(statement, values);
|
|
52
|
+
return {
|
|
53
|
+
changes: result.changes ?? 0,
|
|
54
|
+
lastId: (result as any).lastInsertRowId ?? (result as any).lastInsertId ?? undefined,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async query(statement: string, values: any[] = []): Promise<SQLiteQueryResult> {
|
|
59
|
+
await this.open();
|
|
60
|
+
const db = this.db!;
|
|
61
|
+
const rows = await db.getAllAsync(statement, values);
|
|
62
|
+
const first = rows[0];
|
|
63
|
+
const columns = first ? Object.keys(first) : [];
|
|
64
|
+
const valuesMatrix = rows.map((row) => columns.map((col) => (row as any)[col]));
|
|
65
|
+
return { columns, values: valuesMatrix };
|
|
66
|
+
}
|
|
67
|
+
}
|