@symbiote-native/sqlite 0.1.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 +283 -0
- package/build/angular/index.d.ts +2 -0
- package/build/angular/index.js +2 -0
- package/build/angular/sqlite.service.d.ts +41 -0
- package/build/angular/sqlite.service.js +127 -0
- package/build/core/index.d.ts +10 -0
- package/build/core/index.js +6 -0
- package/build/core/native-database.d.ts +65 -0
- package/build/core/native-database.js +13 -0
- package/build/core/native-module.d.ts +25 -0
- package/build/core/native-module.js +17 -0
- package/build/core/native-session.d.ts +20 -0
- package/build/core/native-session.js +1 -0
- package/build/core/native-statement.d.ts +45 -0
- package/build/core/native-statement.js +6 -0
- package/build/core/param-utils.d.ts +28 -0
- package/build/core/param-utils.js +126 -0
- package/build/core/path-utils.d.ts +6 -0
- package/build/core/path-utils.js +29 -0
- package/build/core/query-utils.d.ts +17 -0
- package/build/core/query-utils.js +37 -0
- package/build/core/sqlite-database.d.ts +246 -0
- package/build/core/sqlite-database.js +427 -0
- package/build/core/sqlite-session.d.ts +84 -0
- package/build/core/sqlite-session.js +121 -0
- package/build/core/sqlite-statement.d.ts +96 -0
- package/build/core/sqlite-statement.js +321 -0
- package/build/core/sqlite-tagged-query.d.ts +73 -0
- package/build/core/sqlite-tagged-query.js +119 -0
- package/build/core/storage.d.ts +107 -0
- package/build/core/storage.js +382 -0
- package/build/core/types.d.ts +30 -0
- package/build/core/types.js +1 -0
- package/build/react/index.d.ts +2 -0
- package/build/react/index.js +2 -0
- package/build/react/sqlite-context.d.ts +25 -0
- package/build/react/sqlite-context.js +129 -0
- package/build/solid/index.d.ts +2 -0
- package/build/solid/index.js +2 -0
- package/build/solid/sqlite-context.d.ts +23 -0
- package/build/solid/sqlite-context.js +106 -0
- package/build/svelte/SQLiteProvider.svelte +88 -0
- package/build/svelte/SQLiteProvider.svelte.d.ts +13 -0
- package/build/svelte/index.d.ts +3 -0
- package/build/svelte/index.js +5 -0
- package/build/svelte/sqlite-context.d.ts +11 -0
- package/build/svelte/sqlite-context.js +23 -0
- package/build/vue/index.d.ts +2 -0
- package/build/vue/index.js +2 -0
- package/build/vue/sqlite-context.d.ts +21 -0
- package/build/vue/sqlite-context.js +69 -0
- package/build-ngc/angular/index.d.ts +2 -0
- package/build-ngc/angular/index.js +3 -0
- package/build-ngc/angular/index.js.map +1 -0
- package/build-ngc/angular/sqlite.service.d.ts +44 -0
- package/build-ngc/angular/sqlite.service.js +85 -0
- package/build-ngc/angular/sqlite.service.js.map +1 -0
- package/build-ngc/core/index.d.ts +10 -0
- package/build-ngc/core/index.js +7 -0
- package/build-ngc/core/index.js.map +1 -0
- package/build-ngc/core/native-database.d.ts +65 -0
- package/build-ngc/core/native-database.js +14 -0
- package/build-ngc/core/native-database.js.map +1 -0
- package/build-ngc/core/native-module.d.ts +25 -0
- package/build-ngc/core/native-module.js +18 -0
- package/build-ngc/core/native-module.js.map +1 -0
- package/build-ngc/core/native-session.d.ts +20 -0
- package/build-ngc/core/native-session.js +2 -0
- package/build-ngc/core/native-session.js.map +1 -0
- package/build-ngc/core/native-statement.d.ts +45 -0
- package/build-ngc/core/native-statement.js +7 -0
- package/build-ngc/core/native-statement.js.map +1 -0
- package/build-ngc/core/param-utils.d.ts +28 -0
- package/build-ngc/core/param-utils.js +127 -0
- package/build-ngc/core/param-utils.js.map +1 -0
- package/build-ngc/core/path-utils.d.ts +6 -0
- package/build-ngc/core/path-utils.js +30 -0
- package/build-ngc/core/path-utils.js.map +1 -0
- package/build-ngc/core/query-utils.d.ts +17 -0
- package/build-ngc/core/query-utils.js +38 -0
- package/build-ngc/core/query-utils.js.map +1 -0
- package/build-ngc/core/sqlite-database.d.ts +246 -0
- package/build-ngc/core/sqlite-database.js +428 -0
- package/build-ngc/core/sqlite-database.js.map +1 -0
- package/build-ngc/core/sqlite-session.d.ts +84 -0
- package/build-ngc/core/sqlite-session.js +122 -0
- package/build-ngc/core/sqlite-session.js.map +1 -0
- package/build-ngc/core/sqlite-statement.d.ts +96 -0
- package/build-ngc/core/sqlite-statement.js +322 -0
- package/build-ngc/core/sqlite-statement.js.map +1 -0
- package/build-ngc/core/sqlite-tagged-query.d.ts +73 -0
- package/build-ngc/core/sqlite-tagged-query.js +120 -0
- package/build-ngc/core/sqlite-tagged-query.js.map +1 -0
- package/build-ngc/core/storage.d.ts +107 -0
- package/build-ngc/core/storage.js +383 -0
- package/build-ngc/core/storage.js.map +1 -0
- package/build-ngc/core/types.d.ts +30 -0
- package/build-ngc/core/types.js +2 -0
- package/build-ngc/core/types.js.map +1 -0
- package/native-link.json +12 -0
- package/package.json +141 -0
- package/src/angular/index.ts +2 -0
- package/src/angular/sqlite.service.ts +114 -0
- package/src/core/index.ts +40 -0
- package/src/core/native-database.ts +118 -0
- package/src/core/native-module.ts +57 -0
- package/src/core/native-session.ts +64 -0
- package/src/core/native-statement.ts +85 -0
- package/src/core/param-utils.ts +163 -0
- package/src/core/path-utils.ts +38 -0
- package/src/core/query-utils.ts +45 -0
- package/src/core/sqlite-database.ts +676 -0
- package/src/core/sqlite-session.ts +165 -0
- package/src/core/sqlite-statement.ts +578 -0
- package/src/core/sqlite-tagged-query.ts +160 -0
- package/src/core/storage.ts +492 -0
- package/src/core/types.ts +33 -0
- package/src/react/index.ts +2 -0
- package/src/react/sqlite-context.tsx +244 -0
- package/src/solid/index.ts +2 -0
- package/src/solid/sqlite-context.ts +156 -0
- package/src/svelte/SQLiteProvider.svelte +88 -0
- package/src/svelte/index.ts +6 -0
- package/src/svelte/sqlite-context.ts +32 -0
- package/src/svelte/svelte-compile.test-helper.ts +135 -0
- package/src/vue/index.ts +2 -0
- package/src/vue/sqlite-context.ts +105 -0
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
// Ported from expo-sqlite's SQLiteDatabase.ts (.vendors/expo @ origin/sdk-57,
|
|
2
|
+
// packages/expo-sqlite/src/SQLiteDatabase.ts), renamed with this repo's `I`-prefix convention.
|
|
3
|
+
//
|
|
4
|
+
// Not ported: `registerDatabaseForDevToolsAsync`/`unregisterDatabaseForDevToolsAsync`
|
|
5
|
+
// (SQLiteDevToolsClient.ts) — wiring for Expo's own DevTools browser extension, which this
|
|
6
|
+
// project has no equivalent of and does not otherwise depend on.
|
|
7
|
+
import { Platform } from 'expo-modules-core';
|
|
8
|
+
import type { EventSubscription } from 'expo-modules-core';
|
|
9
|
+
|
|
10
|
+
import { expoSQLite } from './native-module';
|
|
11
|
+
import { NativeDatabase, flattenOpenOptions } from './native-database';
|
|
12
|
+
import type { ISQLiteOpenOptions } from './native-database';
|
|
13
|
+
import { SQLiteSession } from './sqlite-session';
|
|
14
|
+
import { SQLiteStatement } from './sqlite-statement';
|
|
15
|
+
import type {
|
|
16
|
+
ISQLiteBindParams,
|
|
17
|
+
ISQLiteExecuteAsyncResult,
|
|
18
|
+
ISQLiteExecuteSyncResult,
|
|
19
|
+
ISQLiteRunResult,
|
|
20
|
+
ISQLiteVariadicBindParams,
|
|
21
|
+
} from './sqlite-statement';
|
|
22
|
+
import { SQLiteTaggedQuery } from './sqlite-tagged-query';
|
|
23
|
+
import { createDatabasePath } from './path-utils';
|
|
24
|
+
import type {
|
|
25
|
+
IDatabaseChangeEvent,
|
|
26
|
+
IOnInitCallback,
|
|
27
|
+
IOpenDatabaseOptions,
|
|
28
|
+
} from './types';
|
|
29
|
+
|
|
30
|
+
export type { ISQLiteOpenOptions } from './native-database';
|
|
31
|
+
export type {
|
|
32
|
+
IDatabaseChangeEvent,
|
|
33
|
+
IOnInitCallback,
|
|
34
|
+
IOpenDatabaseOptions,
|
|
35
|
+
} from './types';
|
|
36
|
+
|
|
37
|
+
/** A SQLite database. */
|
|
38
|
+
export class SQLiteDatabase {
|
|
39
|
+
constructor(
|
|
40
|
+
public readonly databasePath: string,
|
|
41
|
+
public readonly options: ISQLiteOpenOptions,
|
|
42
|
+
public readonly nativeDatabase: NativeDatabase,
|
|
43
|
+
) {}
|
|
44
|
+
|
|
45
|
+
/** Whether the database is currently in a transaction. */
|
|
46
|
+
public isInTransactionAsync(): Promise<boolean> {
|
|
47
|
+
return this.nativeDatabase.isInTransactionAsync();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Closes the database. */
|
|
51
|
+
public closeAsync(): Promise<void> {
|
|
52
|
+
return this.nativeDatabase.closeAsync();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Executes all SQL queries in the supplied string.
|
|
57
|
+
* > **Note:** The queries are not escaped for you — be careful when constructing them.
|
|
58
|
+
*/
|
|
59
|
+
public execAsync(source: string): Promise<void> {
|
|
60
|
+
return this.nativeDatabase.execAsync(source);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* [Serializes the database](https://sqlite.org/c3ref/serialize.html) as a `Uint8Array`.
|
|
65
|
+
* @param databaseName The attached database name. Defaults to `main`.
|
|
66
|
+
*/
|
|
67
|
+
public serializeAsync(databaseName: string = 'main'): Promise<Uint8Array> {
|
|
68
|
+
return this.nativeDatabase.serializeAsync(databaseName);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Creates a [prepared statement](https://www.sqlite.org/c3ref/prepare.html) from `source`.
|
|
73
|
+
*/
|
|
74
|
+
public async prepareAsync(source: string): Promise<SQLiteStatement> {
|
|
75
|
+
const nativeStatement = new expoSQLite.NativeStatement();
|
|
76
|
+
await this.nativeDatabase.prepareAsync(nativeStatement, source);
|
|
77
|
+
return new SQLiteStatement(this.nativeDatabase, nativeStatement);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Creates a new session for the database.
|
|
82
|
+
* @see [`sqlite3session_create`](https://www.sqlite.org/session/sqlite3session_create.html)
|
|
83
|
+
* @param dbName The database name to create a session for. Defaults to `main`.
|
|
84
|
+
*/
|
|
85
|
+
public async createSessionAsync(
|
|
86
|
+
dbName: string = 'main',
|
|
87
|
+
): Promise<SQLiteSession> {
|
|
88
|
+
const nativeSession = new expoSQLite.NativeSession();
|
|
89
|
+
await this.nativeDatabase.createSessionAsync(nativeSession, dbName);
|
|
90
|
+
return new SQLiteSession(this.nativeDatabase, nativeSession);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Loads a SQLite extension.
|
|
95
|
+
* @param libPath The path to the extension library file.
|
|
96
|
+
* @param entryPoint The extension's entry point. Inferred by
|
|
97
|
+
* [`sqlite3_load_extension`](https://www.sqlite.org/c3ref/load_extension.html) when omitted.
|
|
98
|
+
*/
|
|
99
|
+
public loadExtensionAsync(
|
|
100
|
+
libPath: string,
|
|
101
|
+
entryPoint?: string,
|
|
102
|
+
): Promise<void> {
|
|
103
|
+
return this.nativeDatabase.loadExtensionAsync(libPath, entryPoint);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Executes a transaction, committing/rolling back automatically based on `task`'s result.
|
|
108
|
+
*
|
|
109
|
+
* > **Note:** Not exclusive — other async queries can interleave, so the order of execution
|
|
110
|
+
* > relative to a query issued outside the transaction is not guaranteed. Use
|
|
111
|
+
* > `withExclusiveTransactionAsync` when that matters.
|
|
112
|
+
*/
|
|
113
|
+
public async withTransactionAsync(task: () => Promise<void>): Promise<void> {
|
|
114
|
+
try {
|
|
115
|
+
await this.execAsync('BEGIN');
|
|
116
|
+
await task();
|
|
117
|
+
await this.execAsync('COMMIT');
|
|
118
|
+
} catch (error) {
|
|
119
|
+
await this.execAsync('ROLLBACK');
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Executes a transaction, committing/rolling back automatically based on `task`'s result.
|
|
126
|
+
* The transaction may be exclusive: once it becomes a write transaction, other async write
|
|
127
|
+
* queries abort with a `database is locked` error.
|
|
128
|
+
*
|
|
129
|
+
* > **Note:** Not supported on web.
|
|
130
|
+
*
|
|
131
|
+
* @param task Any queries inside it must run on the `txn` object it receives — a private
|
|
132
|
+
* `SQLiteDatabase` subclass bound to the exclusive connection, typed here as the base class
|
|
133
|
+
* since the subclass is an implementation detail, not a public export.
|
|
134
|
+
*/
|
|
135
|
+
public async withExclusiveTransactionAsync(
|
|
136
|
+
task: (txn: SQLiteDatabase) => Promise<void>,
|
|
137
|
+
): Promise<void> {
|
|
138
|
+
if (Platform.OS === 'web') {
|
|
139
|
+
throw new Error('withExclusiveTransactionAsync is not supported on web');
|
|
140
|
+
}
|
|
141
|
+
const transaction = await SQLiteTransaction.createAsync(this);
|
|
142
|
+
let error: unknown;
|
|
143
|
+
try {
|
|
144
|
+
await transaction.execAsync('BEGIN');
|
|
145
|
+
await task(transaction);
|
|
146
|
+
await transaction.execAsync('COMMIT');
|
|
147
|
+
} catch (thrown) {
|
|
148
|
+
await transaction.execAsync('ROLLBACK');
|
|
149
|
+
error = thrown;
|
|
150
|
+
} finally {
|
|
151
|
+
await transaction.closeAsync();
|
|
152
|
+
}
|
|
153
|
+
if (error !== undefined) {
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Whether the database is currently in a transaction. */
|
|
159
|
+
public isInTransactionSync(): boolean {
|
|
160
|
+
return this.nativeDatabase.isInTransactionSync();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Closes the database. */
|
|
164
|
+
public closeSync(): void {
|
|
165
|
+
return this.nativeDatabase.closeSync();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Executes all SQL queries in the supplied string.
|
|
170
|
+
* > **Note:** The queries are not escaped for you. Running heavy tasks with this function can
|
|
171
|
+
* > block the JavaScript thread.
|
|
172
|
+
*/
|
|
173
|
+
public execSync(source: string): void {
|
|
174
|
+
return this.nativeDatabase.execSync(source);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* [Serializes the database](https://sqlite.org/c3ref/serialize.html) as a `Uint8Array`.
|
|
179
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
180
|
+
*/
|
|
181
|
+
public serializeSync(databaseName: string = 'main'): Uint8Array {
|
|
182
|
+
return this.nativeDatabase.serializeSync(databaseName);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Creates a [prepared statement](https://www.sqlite.org/c3ref/prepare.html) from `source`.
|
|
187
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
188
|
+
*/
|
|
189
|
+
public prepareSync(source: string): SQLiteStatement {
|
|
190
|
+
const nativeStatement = new expoSQLite.NativeStatement();
|
|
191
|
+
this.nativeDatabase.prepareSync(nativeStatement, source);
|
|
192
|
+
return new SQLiteStatement(this.nativeDatabase, nativeStatement);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Creates a new session for the database.
|
|
197
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
198
|
+
* @see [`sqlite3session_create`](https://www.sqlite.org/session/sqlite3session_create.html)
|
|
199
|
+
*/
|
|
200
|
+
public createSessionSync(dbName: string = 'main'): SQLiteSession {
|
|
201
|
+
const nativeSession = new expoSQLite.NativeSession();
|
|
202
|
+
this.nativeDatabase.createSessionSync(nativeSession, dbName);
|
|
203
|
+
return new SQLiteSession(this.nativeDatabase, nativeSession);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Loads a SQLite extension.
|
|
208
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
209
|
+
*/
|
|
210
|
+
public loadExtensionSync(libPath: string, entryPoint?: string): void {
|
|
211
|
+
this.nativeDatabase.loadExtensionSync(libPath, entryPoint);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Executes a transaction, committing/rolling back automatically based on `task`'s result.
|
|
216
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
217
|
+
*/
|
|
218
|
+
public withTransactionSync(task: () => void): void {
|
|
219
|
+
try {
|
|
220
|
+
this.execSync('BEGIN');
|
|
221
|
+
task();
|
|
222
|
+
this.execSync('COMMIT');
|
|
223
|
+
} catch (error) {
|
|
224
|
+
this.execSync('ROLLBACK');
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Executes SQL queries using tagged template literals (Bun-style), automatically parameterized
|
|
231
|
+
* against SQL injection. Directly awaitable (returns rows/`ISQLiteRunResult`); use `.values()`,
|
|
232
|
+
* `.first()`, `.each()`, or the `*Sync` variants for other shapes.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```ts
|
|
236
|
+
* const users = await db.sql<User>`SELECT * FROM users WHERE age > ${21}`;
|
|
237
|
+
* const rows = await db.sql`SELECT name, age FROM users`.values();
|
|
238
|
+
* const user = await db.sql<User>`SELECT * FROM users WHERE id = ${userId}`.first();
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
public sql = <T = unknown>(
|
|
242
|
+
strings: TemplateStringsArray,
|
|
243
|
+
...values: unknown[]
|
|
244
|
+
) => new SQLiteTaggedQuery<T>(this, strings, values);
|
|
245
|
+
|
|
246
|
+
//#region Statement API shorthands
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* A convenience wrapper around `prepareAsync()`, `SQLiteStatement.executeAsync()`, and
|
|
250
|
+
* `SQLiteStatement.finalizeAsync()`.
|
|
251
|
+
*/
|
|
252
|
+
public runAsync(
|
|
253
|
+
source: string,
|
|
254
|
+
params: ISQLiteBindParams,
|
|
255
|
+
): Promise<ISQLiteRunResult>;
|
|
256
|
+
/** @hidden */
|
|
257
|
+
public runAsync(
|
|
258
|
+
source: string,
|
|
259
|
+
...params: ISQLiteVariadicBindParams
|
|
260
|
+
): Promise<ISQLiteRunResult>;
|
|
261
|
+
// `any[]`: the implementation signature of an overloaded function is not itself callable, so
|
|
262
|
+
// TS checks `statement.executeAsync(...params)` below against ITS overloads, not against
|
|
263
|
+
// whatever narrower type is written here — `unknown[]` fails that check for every one of
|
|
264
|
+
// these forwarding methods, matching upstream's own `any[]` for the identical reason.
|
|
265
|
+
public async runAsync(
|
|
266
|
+
source: string,
|
|
267
|
+
...params: any[]
|
|
268
|
+
): Promise<ISQLiteRunResult> {
|
|
269
|
+
const statement = await this.prepareAsync(source);
|
|
270
|
+
let result: ISQLiteExecuteAsyncResult<unknown>;
|
|
271
|
+
try {
|
|
272
|
+
result = await statement.executeAsync(...params);
|
|
273
|
+
} finally {
|
|
274
|
+
await statement.finalizeAsync();
|
|
275
|
+
}
|
|
276
|
+
return result;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* A convenience wrapper around `prepareAsync()`, `SQLiteStatement.executeAsync()`,
|
|
281
|
+
* `ISQLiteExecuteAsyncResult.getFirstAsync()`, and `SQLiteStatement.finalizeAsync()`.
|
|
282
|
+
*/
|
|
283
|
+
public getFirstAsync<T>(
|
|
284
|
+
source: string,
|
|
285
|
+
params: ISQLiteBindParams,
|
|
286
|
+
): Promise<T | null>;
|
|
287
|
+
/** @hidden */
|
|
288
|
+
public getFirstAsync<T>(
|
|
289
|
+
source: string,
|
|
290
|
+
...params: ISQLiteVariadicBindParams
|
|
291
|
+
): Promise<T | null>;
|
|
292
|
+
public async getFirstAsync<T>(
|
|
293
|
+
source: string,
|
|
294
|
+
...params: any[]
|
|
295
|
+
): Promise<T | null> {
|
|
296
|
+
const statement = await this.prepareAsync(source);
|
|
297
|
+
let firstRow: T | null;
|
|
298
|
+
try {
|
|
299
|
+
const result = await statement.executeAsync<T>(...params);
|
|
300
|
+
firstRow = await result.getFirstAsync();
|
|
301
|
+
} finally {
|
|
302
|
+
await statement.finalizeAsync();
|
|
303
|
+
}
|
|
304
|
+
return firstRow;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* A convenience wrapper around `prepareAsync()`, `SQLiteStatement.executeAsync()`, the
|
|
309
|
+
* `ISQLiteExecuteAsyncResult` async iterator, and `SQLiteStatement.finalizeAsync()`.
|
|
310
|
+
*/
|
|
311
|
+
public getEachAsync<T>(
|
|
312
|
+
source: string,
|
|
313
|
+
params: ISQLiteBindParams,
|
|
314
|
+
): AsyncIterableIterator<T>;
|
|
315
|
+
/** @hidden */
|
|
316
|
+
public getEachAsync<T>(
|
|
317
|
+
source: string,
|
|
318
|
+
...params: ISQLiteVariadicBindParams
|
|
319
|
+
): AsyncIterableIterator<T>;
|
|
320
|
+
public async *getEachAsync<T>(
|
|
321
|
+
source: string,
|
|
322
|
+
...params: any[]
|
|
323
|
+
): AsyncIterableIterator<T> {
|
|
324
|
+
const statement = await this.prepareAsync(source);
|
|
325
|
+
try {
|
|
326
|
+
const result = await statement.executeAsync<T>(...params);
|
|
327
|
+
for await (const row of result) {
|
|
328
|
+
yield row;
|
|
329
|
+
}
|
|
330
|
+
} finally {
|
|
331
|
+
await statement.finalizeAsync();
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* A convenience wrapper around `prepareAsync()`, `SQLiteStatement.executeAsync()`,
|
|
337
|
+
* `ISQLiteExecuteAsyncResult.getAllAsync()`, and `SQLiteStatement.finalizeAsync()`.
|
|
338
|
+
*/
|
|
339
|
+
public getAllAsync<T>(
|
|
340
|
+
source: string,
|
|
341
|
+
params: ISQLiteBindParams,
|
|
342
|
+
): Promise<T[]>;
|
|
343
|
+
/** @hidden */
|
|
344
|
+
public getAllAsync<T>(
|
|
345
|
+
source: string,
|
|
346
|
+
...params: ISQLiteVariadicBindParams
|
|
347
|
+
): Promise<T[]>;
|
|
348
|
+
public async getAllAsync<T>(source: string, ...params: any[]): Promise<T[]> {
|
|
349
|
+
const statement = await this.prepareAsync(source);
|
|
350
|
+
let allRows: T[];
|
|
351
|
+
try {
|
|
352
|
+
const result = await statement.executeAsync<T>(...params);
|
|
353
|
+
allRows = await result.getAllAsync();
|
|
354
|
+
} finally {
|
|
355
|
+
await statement.finalizeAsync();
|
|
356
|
+
}
|
|
357
|
+
return allRows;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* A convenience wrapper around `prepareSync()`, `SQLiteStatement.executeSync()`, and
|
|
362
|
+
* `SQLiteStatement.finalizeSync()`.
|
|
363
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
364
|
+
*/
|
|
365
|
+
public runSync(source: string, params: ISQLiteBindParams): ISQLiteRunResult;
|
|
366
|
+
/** @hidden */
|
|
367
|
+
public runSync(
|
|
368
|
+
source: string,
|
|
369
|
+
...params: ISQLiteVariadicBindParams
|
|
370
|
+
): ISQLiteRunResult;
|
|
371
|
+
public runSync(source: string, ...params: any[]): ISQLiteRunResult {
|
|
372
|
+
const statement = this.prepareSync(source);
|
|
373
|
+
let result: ISQLiteExecuteSyncResult<unknown>;
|
|
374
|
+
try {
|
|
375
|
+
result = statement.executeSync(...params);
|
|
376
|
+
} finally {
|
|
377
|
+
statement.finalizeSync();
|
|
378
|
+
}
|
|
379
|
+
return result;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* A convenience wrapper around `prepareSync()`, `SQLiteStatement.executeSync()`,
|
|
384
|
+
* `ISQLiteExecuteSyncResult.getFirstSync()`, and `SQLiteStatement.finalizeSync()`.
|
|
385
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
386
|
+
*/
|
|
387
|
+
public getFirstSync<T>(source: string, params: ISQLiteBindParams): T | null;
|
|
388
|
+
/** @hidden */
|
|
389
|
+
public getFirstSync<T>(
|
|
390
|
+
source: string,
|
|
391
|
+
...params: ISQLiteVariadicBindParams
|
|
392
|
+
): T | null;
|
|
393
|
+
public getFirstSync<T>(source: string, ...params: any[]): T | null {
|
|
394
|
+
const statement = this.prepareSync(source);
|
|
395
|
+
let firstRow: T | null;
|
|
396
|
+
try {
|
|
397
|
+
const result = statement.executeSync<T>(...params);
|
|
398
|
+
firstRow = result.getFirstSync();
|
|
399
|
+
} finally {
|
|
400
|
+
statement.finalizeSync();
|
|
401
|
+
}
|
|
402
|
+
return firstRow;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* A convenience wrapper around `prepareSync()`, `SQLiteStatement.executeSync()`, the
|
|
407
|
+
* `ISQLiteExecuteSyncResult` iterator, and `SQLiteStatement.finalizeSync()`.
|
|
408
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
409
|
+
*/
|
|
410
|
+
public getEachSync<T>(
|
|
411
|
+
source: string,
|
|
412
|
+
params: ISQLiteBindParams,
|
|
413
|
+
): IterableIterator<T>;
|
|
414
|
+
/** @hidden */
|
|
415
|
+
public getEachSync<T>(
|
|
416
|
+
source: string,
|
|
417
|
+
...params: ISQLiteVariadicBindParams
|
|
418
|
+
): IterableIterator<T>;
|
|
419
|
+
public *getEachSync<T>(
|
|
420
|
+
source: string,
|
|
421
|
+
...params: any[]
|
|
422
|
+
): IterableIterator<T> {
|
|
423
|
+
const statement = this.prepareSync(source);
|
|
424
|
+
try {
|
|
425
|
+
const result = statement.executeSync<T>(...params);
|
|
426
|
+
for (const row of result) {
|
|
427
|
+
yield row;
|
|
428
|
+
}
|
|
429
|
+
} finally {
|
|
430
|
+
statement.finalizeSync();
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* A convenience wrapper around `prepareSync()`, `SQLiteStatement.executeSync()`,
|
|
436
|
+
* `ISQLiteExecuteSyncResult.getAllSync()`, and `SQLiteStatement.finalizeSync()`.
|
|
437
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
438
|
+
*/
|
|
439
|
+
public getAllSync<T>(source: string, params: ISQLiteBindParams): T[];
|
|
440
|
+
/** @hidden */
|
|
441
|
+
public getAllSync<T>(
|
|
442
|
+
source: string,
|
|
443
|
+
...params: ISQLiteVariadicBindParams
|
|
444
|
+
): T[];
|
|
445
|
+
public getAllSync<T>(source: string, ...params: any[]): T[] {
|
|
446
|
+
const statement = this.prepareSync(source);
|
|
447
|
+
let allRows: T[];
|
|
448
|
+
try {
|
|
449
|
+
const result = statement.executeSync<T>(...params);
|
|
450
|
+
allRows = result.getAllSync();
|
|
451
|
+
} finally {
|
|
452
|
+
statement.finalizeSync();
|
|
453
|
+
}
|
|
454
|
+
return allRows;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/** Synchronizes the local database with the remote libSQL server (libSQL integration only). */
|
|
458
|
+
public syncLibSQL(): Promise<void> {
|
|
459
|
+
if (typeof this.nativeDatabase.syncLibSQL !== 'function') {
|
|
460
|
+
throw new Error('syncLibSQL is not supported in the current environment');
|
|
461
|
+
}
|
|
462
|
+
return this.nativeDatabase.syncLibSQL();
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
//#endregion
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/** The default directory new databases are created in. */
|
|
469
|
+
export const defaultDatabaseDirectory = expoSQLite.defaultDatabaseDirectory;
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Pre-bundled SQLite extensions. Bundling one (e.g. `sqlite-vec`) is a manual native-config
|
|
473
|
+
* step this package does not automate — see the README.
|
|
474
|
+
*/
|
|
475
|
+
export const bundledExtensions = expoSQLite.bundledExtensions;
|
|
476
|
+
|
|
477
|
+
async function runOnInit(
|
|
478
|
+
db: SQLiteDatabase,
|
|
479
|
+
onInit: IOnInitCallback | undefined,
|
|
480
|
+
): Promise<void> {
|
|
481
|
+
if (onInit) {
|
|
482
|
+
await onInit(db);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Opens a database.
|
|
488
|
+
* @param databaseName The database file name to open.
|
|
489
|
+
* @param options Open options — see `IOpenDatabaseOptions` for the `onInit` deviation from
|
|
490
|
+
* upstream (documented in the README).
|
|
491
|
+
* @param directory The directory the database file is located in. Defaults to
|
|
492
|
+
* `defaultDatabaseDirectory`.
|
|
493
|
+
*/
|
|
494
|
+
export async function openDatabaseAsync(
|
|
495
|
+
databaseName: string,
|
|
496
|
+
options?: IOpenDatabaseOptions,
|
|
497
|
+
directory?: string,
|
|
498
|
+
): Promise<SQLiteDatabase> {
|
|
499
|
+
const { onInit, ...openOptions } = options ?? {};
|
|
500
|
+
const databasePath = createDatabasePath(databaseName, directory);
|
|
501
|
+
await expoSQLite.ensureDatabasePathExistsAsync(databasePath);
|
|
502
|
+
const nativeDatabase = new expoSQLite.NativeDatabase(
|
|
503
|
+
databasePath,
|
|
504
|
+
flattenOpenOptions(openOptions),
|
|
505
|
+
);
|
|
506
|
+
await nativeDatabase.initAsync();
|
|
507
|
+
const database = new SQLiteDatabase(
|
|
508
|
+
databasePath,
|
|
509
|
+
openOptions,
|
|
510
|
+
nativeDatabase,
|
|
511
|
+
);
|
|
512
|
+
await runOnInit(database, onInit);
|
|
513
|
+
return database;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Opens a database.
|
|
518
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
519
|
+
*/
|
|
520
|
+
export function openDatabaseSync(
|
|
521
|
+
databaseName: string,
|
|
522
|
+
options?: IOpenDatabaseOptions,
|
|
523
|
+
directory?: string,
|
|
524
|
+
): SQLiteDatabase {
|
|
525
|
+
const { onInit, ...openOptions } = options ?? {};
|
|
526
|
+
const databasePath = createDatabasePath(databaseName, directory);
|
|
527
|
+
expoSQLite.ensureDatabasePathExistsSync(databasePath);
|
|
528
|
+
const nativeDatabase = new expoSQLite.NativeDatabase(
|
|
529
|
+
databasePath,
|
|
530
|
+
flattenOpenOptions(openOptions),
|
|
531
|
+
);
|
|
532
|
+
nativeDatabase.initSync();
|
|
533
|
+
const database = new SQLiteDatabase(
|
|
534
|
+
databasePath,
|
|
535
|
+
openOptions,
|
|
536
|
+
nativeDatabase,
|
|
537
|
+
);
|
|
538
|
+
if (onInit) {
|
|
539
|
+
const result = onInit(database);
|
|
540
|
+
if (result instanceof Promise) {
|
|
541
|
+
throw new Error(
|
|
542
|
+
'openDatabaseSync: onInit returned a Promise — pass a synchronous callback, or use openDatabaseAsync.',
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return database;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Given `Uint8Array` data, [deserializes it to an in-memory database](https://sqlite.org/c3ref/deserialize.html).
|
|
551
|
+
* @param serializedData The binary array from `SQLiteDatabase.serializeAsync()`.
|
|
552
|
+
*/
|
|
553
|
+
export async function deserializeDatabaseAsync(
|
|
554
|
+
serializedData: Uint8Array,
|
|
555
|
+
options?: ISQLiteOpenOptions,
|
|
556
|
+
): Promise<SQLiteDatabase> {
|
|
557
|
+
const openOptions = options ?? {};
|
|
558
|
+
const nativeDatabase = new expoSQLite.NativeDatabase(
|
|
559
|
+
':memory:',
|
|
560
|
+
flattenOpenOptions(openOptions),
|
|
561
|
+
serializedData,
|
|
562
|
+
);
|
|
563
|
+
await nativeDatabase.initAsync();
|
|
564
|
+
return new SQLiteDatabase(':memory:', openOptions, nativeDatabase);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Given `Uint8Array` data, [deserializes it to an in-memory database](https://sqlite.org/c3ref/deserialize.html).
|
|
569
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
570
|
+
*/
|
|
571
|
+
export function deserializeDatabaseSync(
|
|
572
|
+
serializedData: Uint8Array,
|
|
573
|
+
options?: ISQLiteOpenOptions,
|
|
574
|
+
): SQLiteDatabase {
|
|
575
|
+
const openOptions = options ?? {};
|
|
576
|
+
const nativeDatabase = new expoSQLite.NativeDatabase(
|
|
577
|
+
':memory:',
|
|
578
|
+
flattenOpenOptions(openOptions),
|
|
579
|
+
serializedData,
|
|
580
|
+
);
|
|
581
|
+
nativeDatabase.initSync();
|
|
582
|
+
return new SQLiteDatabase(':memory:', openOptions, nativeDatabase);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/** Deletes a database file. */
|
|
586
|
+
export async function deleteDatabaseAsync(
|
|
587
|
+
databaseName: string,
|
|
588
|
+
directory?: string,
|
|
589
|
+
): Promise<void> {
|
|
590
|
+
const databasePath = createDatabasePath(databaseName, directory);
|
|
591
|
+
return await expoSQLite.deleteDatabaseAsync(databasePath);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Deletes a database file.
|
|
596
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
597
|
+
*/
|
|
598
|
+
export function deleteDatabaseSync(
|
|
599
|
+
databaseName: string,
|
|
600
|
+
directory?: string,
|
|
601
|
+
): void {
|
|
602
|
+
const databasePath = createDatabasePath(databaseName, directory);
|
|
603
|
+
return expoSQLite.deleteDatabaseSync(databasePath);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Backs up a database to another database.
|
|
608
|
+
* @see https://www.sqlite.org/c3ref/backup_finish.html
|
|
609
|
+
*/
|
|
610
|
+
export function backupDatabaseAsync(options: {
|
|
611
|
+
sourceDatabase: SQLiteDatabase;
|
|
612
|
+
sourceDatabaseName?: string;
|
|
613
|
+
destDatabase: SQLiteDatabase;
|
|
614
|
+
destDatabaseName?: string;
|
|
615
|
+
}): Promise<void> {
|
|
616
|
+
const { sourceDatabase, sourceDatabaseName, destDatabase, destDatabaseName } =
|
|
617
|
+
options;
|
|
618
|
+
return expoSQLite.backupDatabaseAsync(
|
|
619
|
+
destDatabase.nativeDatabase,
|
|
620
|
+
destDatabaseName ?? 'main',
|
|
621
|
+
sourceDatabase.nativeDatabase,
|
|
622
|
+
sourceDatabaseName ?? 'main',
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Backs up a database to another database.
|
|
628
|
+
* > **Note:** Running heavy tasks with this function can block the JavaScript thread.
|
|
629
|
+
* @see https://www.sqlite.org/c3ref/backup_finish.html
|
|
630
|
+
*/
|
|
631
|
+
export function backupDatabaseSync(options: {
|
|
632
|
+
sourceDatabase: SQLiteDatabase;
|
|
633
|
+
sourceDatabaseName?: string;
|
|
634
|
+
destDatabase: SQLiteDatabase;
|
|
635
|
+
destDatabaseName?: string;
|
|
636
|
+
}): void {
|
|
637
|
+
const { sourceDatabase, sourceDatabaseName, destDatabase, destDatabaseName } =
|
|
638
|
+
options;
|
|
639
|
+
return expoSQLite.backupDatabaseSync(
|
|
640
|
+
destDatabase.nativeDatabase,
|
|
641
|
+
destDatabaseName ?? 'main',
|
|
642
|
+
sourceDatabase.nativeDatabase,
|
|
643
|
+
sourceDatabaseName ?? 'main',
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Adds a listener for database changes.
|
|
649
|
+
* > **Note:** requires `enableChangeListener: true` in `ISQLiteOpenOptions` when opening.
|
|
650
|
+
*/
|
|
651
|
+
export function addDatabaseChangeListener(
|
|
652
|
+
listener: (event: IDatabaseChangeEvent) => void,
|
|
653
|
+
): EventSubscription {
|
|
654
|
+
return expoSQLite.addListener('onDatabaseChange', listener);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* A new connection specifically used by `withExclusiveTransactionAsync`.
|
|
659
|
+
* @hidden not exposing all the database methods to the public API surface
|
|
660
|
+
*/
|
|
661
|
+
class SQLiteTransaction extends SQLiteDatabase {
|
|
662
|
+
public static async createAsync(
|
|
663
|
+
db: SQLiteDatabase,
|
|
664
|
+
): Promise<SQLiteTransaction> {
|
|
665
|
+
const options: ISQLiteOpenOptions = {
|
|
666
|
+
...db.options,
|
|
667
|
+
useNewConnection: true,
|
|
668
|
+
};
|
|
669
|
+
const nativeDatabase = new expoSQLite.NativeDatabase(
|
|
670
|
+
db.databasePath,
|
|
671
|
+
flattenOpenOptions(options),
|
|
672
|
+
);
|
|
673
|
+
await nativeDatabase.initAsync();
|
|
674
|
+
return new SQLiteTransaction(db.databasePath, options, nativeDatabase);
|
|
675
|
+
}
|
|
676
|
+
}
|