@tanstack/expo-db-sqlite-persistence 0.2.23 → 0.2.25
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/README.md +3 -1
- package/dist/cjs/expo-sqlite-driver.cjs +12 -3
- package/dist/cjs/expo-sqlite-driver.cjs.map +1 -1
- package/dist/cjs/expo-sqlite-driver.d.cts +12 -8
- package/dist/esm/expo-sqlite-driver.d.ts +12 -8
- package/dist/esm/expo-sqlite-driver.js +12 -3
- package/dist/esm/expo-sqlite-driver.js.map +1 -1
- package/package.json +5 -4
- package/src/expo-sqlite-driver.ts +38 -24
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Thin SQLite persistence for Expo apps using the official `expo-sqlite` adapter.
|
|
4
4
|
|
|
5
|
+
Start with the [SQLite Persistence guide](../../docs/guides/sqlite-persistence.md) for Collection setup and lifecycle behavior.
|
|
6
|
+
|
|
5
7
|
## Public API
|
|
6
8
|
|
|
7
9
|
- `createExpoSQLitePersistence(...)`
|
|
@@ -45,7 +47,7 @@ export const todosCollection = createCollection(
|
|
|
45
47
|
## Notes
|
|
46
48
|
|
|
47
49
|
- This package targets the official `expo-sqlite` async database API.
|
|
48
|
-
- Requires `expo-sqlite` `^55.0.10` (documented as a peer dependency).
|
|
50
|
+
- Requires `expo-sqlite` `^55.0.10` or `^57.0.0` (documented as a peer dependency).
|
|
49
51
|
- `createExpoSQLitePersistence` is shared across collections.
|
|
50
52
|
- Mode defaults (`sync-present` vs `sync-absent`) are inferred from whether a
|
|
51
53
|
`sync` config is present in `persistedCollectionOptions`.
|
|
@@ -66,10 +66,12 @@ class ExpoSQLiteDriver {
|
|
|
66
66
|
async transactionWithDriver(fn) {
|
|
67
67
|
return this.enqueue(async () => {
|
|
68
68
|
const database = await this.getDatabase();
|
|
69
|
-
|
|
69
|
+
let result;
|
|
70
|
+
await database.withExclusiveTransactionAsync(async (transaction) => {
|
|
70
71
|
const transactionDriver = this.createTransactionDriver(transaction);
|
|
71
|
-
|
|
72
|
+
result = await fn(transactionDriver);
|
|
72
73
|
});
|
|
74
|
+
return result;
|
|
73
75
|
});
|
|
74
76
|
}
|
|
75
77
|
async close() {
|
|
@@ -125,7 +127,14 @@ class ExpoSQLiteDriver {
|
|
|
125
127
|
}
|
|
126
128
|
}
|
|
127
129
|
function normalizeParams(params) {
|
|
128
|
-
return params.
|
|
130
|
+
return params.map((value) => {
|
|
131
|
+
if (value === null || typeof value === `string` || typeof value === `number` || typeof value === `boolean` || value instanceof Uint8Array) {
|
|
132
|
+
return value;
|
|
133
|
+
}
|
|
134
|
+
throw new TypeError(
|
|
135
|
+
`Expo SQLite bind parameters must be strings, numbers, booleans, null, or Uint8Array values`
|
|
136
|
+
);
|
|
137
|
+
});
|
|
129
138
|
}
|
|
130
139
|
exports.ExpoSQLiteDriver = ExpoSQLiteDriver;
|
|
131
140
|
//# sourceMappingURL=expo-sqlite-driver.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expo-sqlite-driver.cjs","sources":["../../src/expo-sqlite-driver.ts"],"sourcesContent":["import { InvalidPersistedCollectionConfigError } from '@tanstack/db-sqlite-persistence-core'\nimport type { SQLiteDriver } from '@tanstack/db-sqlite-persistence-core'\n\nexport type ExpoSQLiteBindParams =\n | ReadonlyArray<unknown>\n | Record<string, unknown>\n\nexport type ExpoSQLiteRunResult = {\n changes: number\n lastInsertRowId: number\n}\n\nexport type ExpoSQLiteQueryable = {\n execAsync: (sql: string) => Promise<void>\n getAllAsync: <T>(\n sql: string,\n params?: ExpoSQLiteBindParams,\n ) => Promise<ReadonlyArray<T>>\n runAsync: (\n sql: string,\n params?: ExpoSQLiteBindParams,\n ) => Promise<ExpoSQLiteRunResult>\n}\n\nexport type ExpoSQLiteTransaction = ExpoSQLiteQueryable\n\nexport type ExpoSQLiteDatabaseLike = ExpoSQLiteQueryable & {\n withExclusiveTransactionAsync: <T>(\n task: (transaction: ExpoSQLiteTransaction) => Promise<T>,\n ) => Promise<T>\n closeAsync?: () => Promise<void>\n}\n\ntype ExpoSQLiteExistingDatabaseOptions = {\n database: ExpoSQLiteDatabaseLike\n}\n\ntype ExpoSQLiteOpenDatabaseOptions = {\n openDatabase: () => Promise<ExpoSQLiteDatabaseLike> | ExpoSQLiteDatabaseLike\n}\n\nexport type ExpoSQLiteDriverOptions =\n | ExpoSQLiteExistingDatabaseOptions\n | ExpoSQLiteOpenDatabaseOptions\n\nfunction hasExistingDatabase(\n options: ExpoSQLiteDriverOptions,\n): options is ExpoSQLiteExistingDatabaseOptions {\n return `database` in options\n}\n\nfunction assertTransactionCallbackHasDriverArg(\n fn: (transactionDriver: SQLiteDriver) => Promise<unknown>,\n): void {\n if (fn.length > 0) {\n return\n }\n\n throw new InvalidPersistedCollectionConfigError(\n `SQLiteDriver.transaction callback must accept the transaction driver argument`,\n )\n}\n\nfunction isExpoSQLiteDatabaseLike(\n value: unknown,\n): value is ExpoSQLiteDatabaseLike {\n return (\n typeof value === `object` &&\n value !== null &&\n typeof (value as ExpoSQLiteDatabaseLike).execAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).getAllAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).runAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).withExclusiveTransactionAsync ===\n `function`\n )\n}\n\nexport class ExpoSQLiteDriver implements SQLiteDriver {\n private readonly databasePromise: Promise<ExpoSQLiteDatabaseLike>\n private readonly ownsDatabase: boolean\n private queue: Promise<void> = Promise.resolve()\n private nextSavepointId = 1\n\n constructor(options: ExpoSQLiteDriverOptions) {\n if (hasExistingDatabase(options)) {\n if (!isExpoSQLiteDatabaseLike(options.database)) {\n throw new InvalidPersistedCollectionConfigError(\n `Expo SQLite database must provide execAsync/getAllAsync/runAsync/withExclusiveTransactionAsync`,\n )\n }\n\n this.databasePromise = Promise.resolve(options.database)\n this.ownsDatabase = false\n return\n }\n\n this.databasePromise = Promise.resolve(options.openDatabase()).then(\n (database) => {\n if (!isExpoSQLiteDatabaseLike(database)) {\n throw new InvalidPersistedCollectionConfigError(\n `Expo SQLite openDatabase() must resolve a database with execAsync/getAllAsync/runAsync/withExclusiveTransactionAsync`,\n )\n }\n\n return database\n },\n )\n this.ownsDatabase = true\n }\n\n async exec(sql: string): Promise<void> {\n await this.enqueue(async () => {\n const database = await this.getDatabase()\n await database.execAsync(sql)\n })\n }\n\n async query<T>(\n sql: string,\n params: ReadonlyArray<unknown> = [],\n ): Promise<ReadonlyArray<T>> {\n return this.enqueue(async () => {\n const database = await this.getDatabase()\n return database.getAllAsync<T>(sql, normalizeParams(params))\n })\n }\n\n async run(sql: string, params: ReadonlyArray<unknown> = []): Promise<void> {\n await this.enqueue(async () => {\n const database = await this.getDatabase()\n await database.runAsync(sql, normalizeParams(params))\n })\n }\n\n async transaction<T>(\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n assertTransactionCallbackHasDriverArg(fn)\n return this.transactionWithDriver(fn)\n }\n\n async transactionWithDriver<T>(\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n return this.enqueue(async () => {\n const database = await this.getDatabase()\n return database.withExclusiveTransactionAsync(async (transaction) => {\n const transactionDriver = this.createTransactionDriver(transaction)\n return fn(transactionDriver)\n })\n })\n }\n\n async close(): Promise<void> {\n const database = await this.getDatabase()\n if (!this.ownsDatabase || typeof database.closeAsync !== `function`) {\n return\n }\n\n await database.closeAsync()\n }\n\n async getDatabase(): Promise<ExpoSQLiteDatabaseLike> {\n return this.databasePromise\n }\n\n private enqueue<T>(operation: () => Promise<T>): Promise<T> {\n const queuedOperation = this.queue.then(operation, operation)\n this.queue = queuedOperation.then(\n () => undefined,\n () => undefined,\n )\n return queuedOperation\n }\n\n private createTransactionDriver(\n transaction: ExpoSQLiteTransaction,\n ): SQLiteDriver {\n const transactionDriver: SQLiteDriver = {\n exec: async (sql) => {\n await transaction.execAsync(sql)\n },\n query: async <T>(\n sql: string,\n params: ReadonlyArray<unknown> = [],\n ): Promise<ReadonlyArray<T>> => {\n return transaction.getAllAsync<T>(sql, normalizeParams(params))\n },\n run: async (sql: string, params: ReadonlyArray<unknown> = []) => {\n await transaction.runAsync(sql, normalizeParams(params))\n },\n transaction: async <T>(\n fn: (nestedTransactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> => {\n assertTransactionCallbackHasDriverArg(fn)\n return this.runNestedTransaction(transaction, transactionDriver, fn)\n },\n transactionWithDriver: async <T>(\n fn: (nestedTransactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> =>\n this.runNestedTransaction(transaction, transactionDriver, fn),\n }\n\n return transactionDriver\n }\n\n private async runNestedTransaction<T>(\n transaction: ExpoSQLiteTransaction,\n transactionDriver: SQLiteDriver,\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n const savepointName = `tsdb_sp_${this.nextSavepointId}`\n this.nextSavepointId++\n await transaction.execAsync(`SAVEPOINT ${savepointName}`)\n\n try {\n const result = await fn(transactionDriver)\n await transaction.execAsync(`RELEASE SAVEPOINT ${savepointName}`)\n return result\n } catch (error) {\n await transaction.execAsync(`ROLLBACK TO SAVEPOINT ${savepointName}`)\n await transaction.execAsync(`RELEASE SAVEPOINT ${savepointName}`)\n throw error\n }\n }\n}\n\nfunction normalizeParams(\n params: ReadonlyArray<unknown>,\n): ExpoSQLiteBindParams | undefined {\n return params.length > 0 ? [...params] : undefined\n}\n\nexport function createExpoSQLiteDriver(\n options: ExpoSQLiteDriverOptions,\n): ExpoSQLiteDriver {\n return new ExpoSQLiteDriver(options)\n}\n"],"names":["InvalidPersistedCollectionConfigError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"expo-sqlite-driver.cjs","sources":["../../src/expo-sqlite-driver.ts"],"sourcesContent":["import { InvalidPersistedCollectionConfigError } from '@tanstack/db-sqlite-persistence-core'\nimport type { SQLiteDriver } from '@tanstack/db-sqlite-persistence-core'\nimport type {\n SQLiteBindParams,\n SQLiteBindValue,\n SQLiteRunResult,\n} from 'expo-sqlite'\n\nexport type ExpoSQLiteBindParams = SQLiteBindParams\n\nexport type ExpoSQLiteRunResult = SQLiteRunResult\n\nexport type ExpoSQLiteQueryable = {\n execAsync: (sql: string) => Promise<void>\n getAllAsync: {\n <T>(sql: string, params: SQLiteBindParams): Promise<ReadonlyArray<T>>\n <T>(sql: string): Promise<ReadonlyArray<T>>\n }\n runAsync: {\n (sql: string, params: SQLiteBindParams): Promise<SQLiteRunResult>\n (sql: string): Promise<SQLiteRunResult>\n }\n}\n\nexport type ExpoSQLiteTransaction = ExpoSQLiteQueryable\n\nexport type ExpoSQLiteDatabaseLike = ExpoSQLiteQueryable & {\n withExclusiveTransactionAsync: (\n task: (transaction: ExpoSQLiteTransaction) => Promise<void>,\n ) => Promise<void>\n closeAsync?: () => Promise<void>\n}\n\ntype ExpoSQLiteExistingDatabaseOptions = {\n database: ExpoSQLiteDatabaseLike\n}\n\ntype ExpoSQLiteOpenDatabaseOptions = {\n openDatabase: () => Promise<ExpoSQLiteDatabaseLike> | ExpoSQLiteDatabaseLike\n}\n\nexport type ExpoSQLiteDriverOptions =\n | ExpoSQLiteExistingDatabaseOptions\n | ExpoSQLiteOpenDatabaseOptions\n\nfunction hasExistingDatabase(\n options: ExpoSQLiteDriverOptions,\n): options is ExpoSQLiteExistingDatabaseOptions {\n return `database` in options\n}\n\nfunction assertTransactionCallbackHasDriverArg(\n fn: (transactionDriver: SQLiteDriver) => Promise<unknown>,\n): void {\n if (fn.length > 0) {\n return\n }\n\n throw new InvalidPersistedCollectionConfigError(\n `SQLiteDriver.transaction callback must accept the transaction driver argument`,\n )\n}\n\nfunction isExpoSQLiteDatabaseLike(\n value: unknown,\n): value is ExpoSQLiteDatabaseLike {\n return (\n typeof value === `object` &&\n value !== null &&\n typeof (value as ExpoSQLiteDatabaseLike).execAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).getAllAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).runAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).withExclusiveTransactionAsync ===\n `function`\n )\n}\n\nexport class ExpoSQLiteDriver implements SQLiteDriver {\n private readonly databasePromise: Promise<ExpoSQLiteDatabaseLike>\n private readonly ownsDatabase: boolean\n private queue: Promise<void> = Promise.resolve()\n private nextSavepointId = 1\n\n constructor(options: ExpoSQLiteDriverOptions) {\n if (hasExistingDatabase(options)) {\n if (!isExpoSQLiteDatabaseLike(options.database)) {\n throw new InvalidPersistedCollectionConfigError(\n `Expo SQLite database must provide execAsync/getAllAsync/runAsync/withExclusiveTransactionAsync`,\n )\n }\n\n this.databasePromise = Promise.resolve(options.database)\n this.ownsDatabase = false\n return\n }\n\n this.databasePromise = Promise.resolve(options.openDatabase()).then(\n (database) => {\n if (!isExpoSQLiteDatabaseLike(database)) {\n throw new InvalidPersistedCollectionConfigError(\n `Expo SQLite openDatabase() must resolve a database with execAsync/getAllAsync/runAsync/withExclusiveTransactionAsync`,\n )\n }\n\n return database\n },\n )\n this.ownsDatabase = true\n }\n\n async exec(sql: string): Promise<void> {\n await this.enqueue(async () => {\n const database = await this.getDatabase()\n await database.execAsync(sql)\n })\n }\n\n async query<T>(\n sql: string,\n params: ReadonlyArray<unknown> = [],\n ): Promise<ReadonlyArray<T>> {\n return this.enqueue(async () => {\n const database = await this.getDatabase()\n return database.getAllAsync<T>(sql, normalizeParams(params))\n })\n }\n\n async run(sql: string, params: ReadonlyArray<unknown> = []): Promise<void> {\n await this.enqueue(async () => {\n const database = await this.getDatabase()\n await database.runAsync(sql, normalizeParams(params))\n })\n }\n\n async transaction<T>(\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n assertTransactionCallbackHasDriverArg(fn)\n return this.transactionWithDriver(fn)\n }\n\n async transactionWithDriver<T>(\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n return this.enqueue(async () => {\n const database = await this.getDatabase()\n let result: T | undefined\n await database.withExclusiveTransactionAsync(async (transaction) => {\n const transactionDriver = this.createTransactionDriver(transaction)\n result = await fn(transactionDriver)\n })\n return result as T\n })\n }\n\n async close(): Promise<void> {\n const database = await this.getDatabase()\n if (!this.ownsDatabase || typeof database.closeAsync !== `function`) {\n return\n }\n\n await database.closeAsync()\n }\n\n async getDatabase(): Promise<ExpoSQLiteDatabaseLike> {\n return this.databasePromise\n }\n\n private enqueue<T>(operation: () => Promise<T>): Promise<T> {\n const queuedOperation = this.queue.then(operation, operation)\n this.queue = queuedOperation.then(\n () => undefined,\n () => undefined,\n )\n return queuedOperation\n }\n\n private createTransactionDriver(\n transaction: ExpoSQLiteTransaction,\n ): SQLiteDriver {\n const transactionDriver: SQLiteDriver = {\n exec: async (sql) => {\n await transaction.execAsync(sql)\n },\n query: async <T>(\n sql: string,\n params: ReadonlyArray<unknown> = [],\n ): Promise<ReadonlyArray<T>> => {\n return transaction.getAllAsync<T>(sql, normalizeParams(params))\n },\n run: async (sql: string, params: ReadonlyArray<unknown> = []) => {\n await transaction.runAsync(sql, normalizeParams(params))\n },\n transaction: async <T>(\n fn: (nestedTransactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> => {\n assertTransactionCallbackHasDriverArg(fn)\n return this.runNestedTransaction(transaction, transactionDriver, fn)\n },\n transactionWithDriver: async <T>(\n fn: (nestedTransactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> =>\n this.runNestedTransaction(transaction, transactionDriver, fn),\n }\n\n return transactionDriver\n }\n\n private async runNestedTransaction<T>(\n transaction: ExpoSQLiteTransaction,\n transactionDriver: SQLiteDriver,\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n const savepointName = `tsdb_sp_${this.nextSavepointId}`\n this.nextSavepointId++\n await transaction.execAsync(`SAVEPOINT ${savepointName}`)\n\n try {\n const result = await fn(transactionDriver)\n await transaction.execAsync(`RELEASE SAVEPOINT ${savepointName}`)\n return result\n } catch (error) {\n await transaction.execAsync(`ROLLBACK TO SAVEPOINT ${savepointName}`)\n await transaction.execAsync(`RELEASE SAVEPOINT ${savepointName}`)\n throw error\n }\n }\n}\n\nfunction normalizeParams(params: ReadonlyArray<unknown>): SQLiteBindParams {\n return params.map((value) => {\n if (\n value === null ||\n typeof value === `string` ||\n typeof value === `number` ||\n typeof value === `boolean` ||\n value instanceof Uint8Array\n ) {\n return value satisfies SQLiteBindValue\n }\n\n throw new TypeError(\n `Expo SQLite bind parameters must be strings, numbers, booleans, null, or Uint8Array values`,\n )\n })\n}\n\nexport function createExpoSQLiteDriver(\n options: ExpoSQLiteDriverOptions,\n): ExpoSQLiteDriver {\n return new ExpoSQLiteDriver(options)\n}\n"],"names":["InvalidPersistedCollectionConfigError"],"mappings":"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"}
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { SQLiteDriver } from '@tanstack/db-sqlite-persistence-core';
|
|
2
|
-
|
|
3
|
-
export type
|
|
4
|
-
|
|
5
|
-
lastInsertRowId: number;
|
|
6
|
-
};
|
|
2
|
+
import { SQLiteBindParams, SQLiteRunResult } from 'expo-sqlite';
|
|
3
|
+
export type ExpoSQLiteBindParams = SQLiteBindParams;
|
|
4
|
+
export type ExpoSQLiteRunResult = SQLiteRunResult;
|
|
7
5
|
export type ExpoSQLiteQueryable = {
|
|
8
6
|
execAsync: (sql: string) => Promise<void>;
|
|
9
|
-
getAllAsync:
|
|
10
|
-
|
|
7
|
+
getAllAsync: {
|
|
8
|
+
<T>(sql: string, params: SQLiteBindParams): Promise<ReadonlyArray<T>>;
|
|
9
|
+
<T>(sql: string): Promise<ReadonlyArray<T>>;
|
|
10
|
+
};
|
|
11
|
+
runAsync: {
|
|
12
|
+
(sql: string, params: SQLiteBindParams): Promise<SQLiteRunResult>;
|
|
13
|
+
(sql: string): Promise<SQLiteRunResult>;
|
|
14
|
+
};
|
|
11
15
|
};
|
|
12
16
|
export type ExpoSQLiteTransaction = ExpoSQLiteQueryable;
|
|
13
17
|
export type ExpoSQLiteDatabaseLike = ExpoSQLiteQueryable & {
|
|
14
|
-
withExclusiveTransactionAsync:
|
|
18
|
+
withExclusiveTransactionAsync: (task: (transaction: ExpoSQLiteTransaction) => Promise<void>) => Promise<void>;
|
|
15
19
|
closeAsync?: () => Promise<void>;
|
|
16
20
|
};
|
|
17
21
|
type ExpoSQLiteExistingDatabaseOptions = {
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { SQLiteDriver } from '@tanstack/db-sqlite-persistence-core';
|
|
2
|
-
|
|
3
|
-
export type
|
|
4
|
-
|
|
5
|
-
lastInsertRowId: number;
|
|
6
|
-
};
|
|
2
|
+
import { SQLiteBindParams, SQLiteRunResult } from 'expo-sqlite';
|
|
3
|
+
export type ExpoSQLiteBindParams = SQLiteBindParams;
|
|
4
|
+
export type ExpoSQLiteRunResult = SQLiteRunResult;
|
|
7
5
|
export type ExpoSQLiteQueryable = {
|
|
8
6
|
execAsync: (sql: string) => Promise<void>;
|
|
9
|
-
getAllAsync:
|
|
10
|
-
|
|
7
|
+
getAllAsync: {
|
|
8
|
+
<T>(sql: string, params: SQLiteBindParams): Promise<ReadonlyArray<T>>;
|
|
9
|
+
<T>(sql: string): Promise<ReadonlyArray<T>>;
|
|
10
|
+
};
|
|
11
|
+
runAsync: {
|
|
12
|
+
(sql: string, params: SQLiteBindParams): Promise<SQLiteRunResult>;
|
|
13
|
+
(sql: string): Promise<SQLiteRunResult>;
|
|
14
|
+
};
|
|
11
15
|
};
|
|
12
16
|
export type ExpoSQLiteTransaction = ExpoSQLiteQueryable;
|
|
13
17
|
export type ExpoSQLiteDatabaseLike = ExpoSQLiteQueryable & {
|
|
14
|
-
withExclusiveTransactionAsync:
|
|
18
|
+
withExclusiveTransactionAsync: (task: (transaction: ExpoSQLiteTransaction) => Promise<void>) => Promise<void>;
|
|
15
19
|
closeAsync?: () => Promise<void>;
|
|
16
20
|
};
|
|
17
21
|
type ExpoSQLiteExistingDatabaseOptions = {
|
|
@@ -64,10 +64,12 @@ class ExpoSQLiteDriver {
|
|
|
64
64
|
async transactionWithDriver(fn) {
|
|
65
65
|
return this.enqueue(async () => {
|
|
66
66
|
const database = await this.getDatabase();
|
|
67
|
-
|
|
67
|
+
let result;
|
|
68
|
+
await database.withExclusiveTransactionAsync(async (transaction) => {
|
|
68
69
|
const transactionDriver = this.createTransactionDriver(transaction);
|
|
69
|
-
|
|
70
|
+
result = await fn(transactionDriver);
|
|
70
71
|
});
|
|
72
|
+
return result;
|
|
71
73
|
});
|
|
72
74
|
}
|
|
73
75
|
async close() {
|
|
@@ -123,7 +125,14 @@ class ExpoSQLiteDriver {
|
|
|
123
125
|
}
|
|
124
126
|
}
|
|
125
127
|
function normalizeParams(params) {
|
|
126
|
-
return params.
|
|
128
|
+
return params.map((value) => {
|
|
129
|
+
if (value === null || typeof value === `string` || typeof value === `number` || typeof value === `boolean` || value instanceof Uint8Array) {
|
|
130
|
+
return value;
|
|
131
|
+
}
|
|
132
|
+
throw new TypeError(
|
|
133
|
+
`Expo SQLite bind parameters must be strings, numbers, booleans, null, or Uint8Array values`
|
|
134
|
+
);
|
|
135
|
+
});
|
|
127
136
|
}
|
|
128
137
|
export {
|
|
129
138
|
ExpoSQLiteDriver
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expo-sqlite-driver.js","sources":["../../src/expo-sqlite-driver.ts"],"sourcesContent":["import { InvalidPersistedCollectionConfigError } from '@tanstack/db-sqlite-persistence-core'\nimport type { SQLiteDriver } from '@tanstack/db-sqlite-persistence-core'\n\nexport type ExpoSQLiteBindParams =\n | ReadonlyArray<unknown>\n | Record<string, unknown>\n\nexport type ExpoSQLiteRunResult = {\n changes: number\n lastInsertRowId: number\n}\n\nexport type ExpoSQLiteQueryable = {\n execAsync: (sql: string) => Promise<void>\n getAllAsync: <T>(\n sql: string,\n params?: ExpoSQLiteBindParams,\n ) => Promise<ReadonlyArray<T>>\n runAsync: (\n sql: string,\n params?: ExpoSQLiteBindParams,\n ) => Promise<ExpoSQLiteRunResult>\n}\n\nexport type ExpoSQLiteTransaction = ExpoSQLiteQueryable\n\nexport type ExpoSQLiteDatabaseLike = ExpoSQLiteQueryable & {\n withExclusiveTransactionAsync: <T>(\n task: (transaction: ExpoSQLiteTransaction) => Promise<T>,\n ) => Promise<T>\n closeAsync?: () => Promise<void>\n}\n\ntype ExpoSQLiteExistingDatabaseOptions = {\n database: ExpoSQLiteDatabaseLike\n}\n\ntype ExpoSQLiteOpenDatabaseOptions = {\n openDatabase: () => Promise<ExpoSQLiteDatabaseLike> | ExpoSQLiteDatabaseLike\n}\n\nexport type ExpoSQLiteDriverOptions =\n | ExpoSQLiteExistingDatabaseOptions\n | ExpoSQLiteOpenDatabaseOptions\n\nfunction hasExistingDatabase(\n options: ExpoSQLiteDriverOptions,\n): options is ExpoSQLiteExistingDatabaseOptions {\n return `database` in options\n}\n\nfunction assertTransactionCallbackHasDriverArg(\n fn: (transactionDriver: SQLiteDriver) => Promise<unknown>,\n): void {\n if (fn.length > 0) {\n return\n }\n\n throw new InvalidPersistedCollectionConfigError(\n `SQLiteDriver.transaction callback must accept the transaction driver argument`,\n )\n}\n\nfunction isExpoSQLiteDatabaseLike(\n value: unknown,\n): value is ExpoSQLiteDatabaseLike {\n return (\n typeof value === `object` &&\n value !== null &&\n typeof (value as ExpoSQLiteDatabaseLike).execAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).getAllAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).runAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).withExclusiveTransactionAsync ===\n `function`\n )\n}\n\nexport class ExpoSQLiteDriver implements SQLiteDriver {\n private readonly databasePromise: Promise<ExpoSQLiteDatabaseLike>\n private readonly ownsDatabase: boolean\n private queue: Promise<void> = Promise.resolve()\n private nextSavepointId = 1\n\n constructor(options: ExpoSQLiteDriverOptions) {\n if (hasExistingDatabase(options)) {\n if (!isExpoSQLiteDatabaseLike(options.database)) {\n throw new InvalidPersistedCollectionConfigError(\n `Expo SQLite database must provide execAsync/getAllAsync/runAsync/withExclusiveTransactionAsync`,\n )\n }\n\n this.databasePromise = Promise.resolve(options.database)\n this.ownsDatabase = false\n return\n }\n\n this.databasePromise = Promise.resolve(options.openDatabase()).then(\n (database) => {\n if (!isExpoSQLiteDatabaseLike(database)) {\n throw new InvalidPersistedCollectionConfigError(\n `Expo SQLite openDatabase() must resolve a database with execAsync/getAllAsync/runAsync/withExclusiveTransactionAsync`,\n )\n }\n\n return database\n },\n )\n this.ownsDatabase = true\n }\n\n async exec(sql: string): Promise<void> {\n await this.enqueue(async () => {\n const database = await this.getDatabase()\n await database.execAsync(sql)\n })\n }\n\n async query<T>(\n sql: string,\n params: ReadonlyArray<unknown> = [],\n ): Promise<ReadonlyArray<T>> {\n return this.enqueue(async () => {\n const database = await this.getDatabase()\n return database.getAllAsync<T>(sql, normalizeParams(params))\n })\n }\n\n async run(sql: string, params: ReadonlyArray<unknown> = []): Promise<void> {\n await this.enqueue(async () => {\n const database = await this.getDatabase()\n await database.runAsync(sql, normalizeParams(params))\n })\n }\n\n async transaction<T>(\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n assertTransactionCallbackHasDriverArg(fn)\n return this.transactionWithDriver(fn)\n }\n\n async transactionWithDriver<T>(\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n return this.enqueue(async () => {\n const database = await this.getDatabase()\n return database.withExclusiveTransactionAsync(async (transaction) => {\n const transactionDriver = this.createTransactionDriver(transaction)\n return fn(transactionDriver)\n })\n })\n }\n\n async close(): Promise<void> {\n const database = await this.getDatabase()\n if (!this.ownsDatabase || typeof database.closeAsync !== `function`) {\n return\n }\n\n await database.closeAsync()\n }\n\n async getDatabase(): Promise<ExpoSQLiteDatabaseLike> {\n return this.databasePromise\n }\n\n private enqueue<T>(operation: () => Promise<T>): Promise<T> {\n const queuedOperation = this.queue.then(operation, operation)\n this.queue = queuedOperation.then(\n () => undefined,\n () => undefined,\n )\n return queuedOperation\n }\n\n private createTransactionDriver(\n transaction: ExpoSQLiteTransaction,\n ): SQLiteDriver {\n const transactionDriver: SQLiteDriver = {\n exec: async (sql) => {\n await transaction.execAsync(sql)\n },\n query: async <T>(\n sql: string,\n params: ReadonlyArray<unknown> = [],\n ): Promise<ReadonlyArray<T>> => {\n return transaction.getAllAsync<T>(sql, normalizeParams(params))\n },\n run: async (sql: string, params: ReadonlyArray<unknown> = []) => {\n await transaction.runAsync(sql, normalizeParams(params))\n },\n transaction: async <T>(\n fn: (nestedTransactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> => {\n assertTransactionCallbackHasDriverArg(fn)\n return this.runNestedTransaction(transaction, transactionDriver, fn)\n },\n transactionWithDriver: async <T>(\n fn: (nestedTransactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> =>\n this.runNestedTransaction(transaction, transactionDriver, fn),\n }\n\n return transactionDriver\n }\n\n private async runNestedTransaction<T>(\n transaction: ExpoSQLiteTransaction,\n transactionDriver: SQLiteDriver,\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n const savepointName = `tsdb_sp_${this.nextSavepointId}`\n this.nextSavepointId++\n await transaction.execAsync(`SAVEPOINT ${savepointName}`)\n\n try {\n const result = await fn(transactionDriver)\n await transaction.execAsync(`RELEASE SAVEPOINT ${savepointName}`)\n return result\n } catch (error) {\n await transaction.execAsync(`ROLLBACK TO SAVEPOINT ${savepointName}`)\n await transaction.execAsync(`RELEASE SAVEPOINT ${savepointName}`)\n throw error\n }\n }\n}\n\nfunction normalizeParams(\n params: ReadonlyArray<unknown>,\n): ExpoSQLiteBindParams | undefined {\n return params.length > 0 ? [...params] : undefined\n}\n\nexport function createExpoSQLiteDriver(\n options: ExpoSQLiteDriverOptions,\n): ExpoSQLiteDriver {\n return new ExpoSQLiteDriver(options)\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"expo-sqlite-driver.js","sources":["../../src/expo-sqlite-driver.ts"],"sourcesContent":["import { InvalidPersistedCollectionConfigError } from '@tanstack/db-sqlite-persistence-core'\nimport type { SQLiteDriver } from '@tanstack/db-sqlite-persistence-core'\nimport type {\n SQLiteBindParams,\n SQLiteBindValue,\n SQLiteRunResult,\n} from 'expo-sqlite'\n\nexport type ExpoSQLiteBindParams = SQLiteBindParams\n\nexport type ExpoSQLiteRunResult = SQLiteRunResult\n\nexport type ExpoSQLiteQueryable = {\n execAsync: (sql: string) => Promise<void>\n getAllAsync: {\n <T>(sql: string, params: SQLiteBindParams): Promise<ReadonlyArray<T>>\n <T>(sql: string): Promise<ReadonlyArray<T>>\n }\n runAsync: {\n (sql: string, params: SQLiteBindParams): Promise<SQLiteRunResult>\n (sql: string): Promise<SQLiteRunResult>\n }\n}\n\nexport type ExpoSQLiteTransaction = ExpoSQLiteQueryable\n\nexport type ExpoSQLiteDatabaseLike = ExpoSQLiteQueryable & {\n withExclusiveTransactionAsync: (\n task: (transaction: ExpoSQLiteTransaction) => Promise<void>,\n ) => Promise<void>\n closeAsync?: () => Promise<void>\n}\n\ntype ExpoSQLiteExistingDatabaseOptions = {\n database: ExpoSQLiteDatabaseLike\n}\n\ntype ExpoSQLiteOpenDatabaseOptions = {\n openDatabase: () => Promise<ExpoSQLiteDatabaseLike> | ExpoSQLiteDatabaseLike\n}\n\nexport type ExpoSQLiteDriverOptions =\n | ExpoSQLiteExistingDatabaseOptions\n | ExpoSQLiteOpenDatabaseOptions\n\nfunction hasExistingDatabase(\n options: ExpoSQLiteDriverOptions,\n): options is ExpoSQLiteExistingDatabaseOptions {\n return `database` in options\n}\n\nfunction assertTransactionCallbackHasDriverArg(\n fn: (transactionDriver: SQLiteDriver) => Promise<unknown>,\n): void {\n if (fn.length > 0) {\n return\n }\n\n throw new InvalidPersistedCollectionConfigError(\n `SQLiteDriver.transaction callback must accept the transaction driver argument`,\n )\n}\n\nfunction isExpoSQLiteDatabaseLike(\n value: unknown,\n): value is ExpoSQLiteDatabaseLike {\n return (\n typeof value === `object` &&\n value !== null &&\n typeof (value as ExpoSQLiteDatabaseLike).execAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).getAllAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).runAsync === `function` &&\n typeof (value as ExpoSQLiteDatabaseLike).withExclusiveTransactionAsync ===\n `function`\n )\n}\n\nexport class ExpoSQLiteDriver implements SQLiteDriver {\n private readonly databasePromise: Promise<ExpoSQLiteDatabaseLike>\n private readonly ownsDatabase: boolean\n private queue: Promise<void> = Promise.resolve()\n private nextSavepointId = 1\n\n constructor(options: ExpoSQLiteDriverOptions) {\n if (hasExistingDatabase(options)) {\n if (!isExpoSQLiteDatabaseLike(options.database)) {\n throw new InvalidPersistedCollectionConfigError(\n `Expo SQLite database must provide execAsync/getAllAsync/runAsync/withExclusiveTransactionAsync`,\n )\n }\n\n this.databasePromise = Promise.resolve(options.database)\n this.ownsDatabase = false\n return\n }\n\n this.databasePromise = Promise.resolve(options.openDatabase()).then(\n (database) => {\n if (!isExpoSQLiteDatabaseLike(database)) {\n throw new InvalidPersistedCollectionConfigError(\n `Expo SQLite openDatabase() must resolve a database with execAsync/getAllAsync/runAsync/withExclusiveTransactionAsync`,\n )\n }\n\n return database\n },\n )\n this.ownsDatabase = true\n }\n\n async exec(sql: string): Promise<void> {\n await this.enqueue(async () => {\n const database = await this.getDatabase()\n await database.execAsync(sql)\n })\n }\n\n async query<T>(\n sql: string,\n params: ReadonlyArray<unknown> = [],\n ): Promise<ReadonlyArray<T>> {\n return this.enqueue(async () => {\n const database = await this.getDatabase()\n return database.getAllAsync<T>(sql, normalizeParams(params))\n })\n }\n\n async run(sql: string, params: ReadonlyArray<unknown> = []): Promise<void> {\n await this.enqueue(async () => {\n const database = await this.getDatabase()\n await database.runAsync(sql, normalizeParams(params))\n })\n }\n\n async transaction<T>(\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n assertTransactionCallbackHasDriverArg(fn)\n return this.transactionWithDriver(fn)\n }\n\n async transactionWithDriver<T>(\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n return this.enqueue(async () => {\n const database = await this.getDatabase()\n let result: T | undefined\n await database.withExclusiveTransactionAsync(async (transaction) => {\n const transactionDriver = this.createTransactionDriver(transaction)\n result = await fn(transactionDriver)\n })\n return result as T\n })\n }\n\n async close(): Promise<void> {\n const database = await this.getDatabase()\n if (!this.ownsDatabase || typeof database.closeAsync !== `function`) {\n return\n }\n\n await database.closeAsync()\n }\n\n async getDatabase(): Promise<ExpoSQLiteDatabaseLike> {\n return this.databasePromise\n }\n\n private enqueue<T>(operation: () => Promise<T>): Promise<T> {\n const queuedOperation = this.queue.then(operation, operation)\n this.queue = queuedOperation.then(\n () => undefined,\n () => undefined,\n )\n return queuedOperation\n }\n\n private createTransactionDriver(\n transaction: ExpoSQLiteTransaction,\n ): SQLiteDriver {\n const transactionDriver: SQLiteDriver = {\n exec: async (sql) => {\n await transaction.execAsync(sql)\n },\n query: async <T>(\n sql: string,\n params: ReadonlyArray<unknown> = [],\n ): Promise<ReadonlyArray<T>> => {\n return transaction.getAllAsync<T>(sql, normalizeParams(params))\n },\n run: async (sql: string, params: ReadonlyArray<unknown> = []) => {\n await transaction.runAsync(sql, normalizeParams(params))\n },\n transaction: async <T>(\n fn: (nestedTransactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> => {\n assertTransactionCallbackHasDriverArg(fn)\n return this.runNestedTransaction(transaction, transactionDriver, fn)\n },\n transactionWithDriver: async <T>(\n fn: (nestedTransactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> =>\n this.runNestedTransaction(transaction, transactionDriver, fn),\n }\n\n return transactionDriver\n }\n\n private async runNestedTransaction<T>(\n transaction: ExpoSQLiteTransaction,\n transactionDriver: SQLiteDriver,\n fn: (transactionDriver: SQLiteDriver) => Promise<T>,\n ): Promise<T> {\n const savepointName = `tsdb_sp_${this.nextSavepointId}`\n this.nextSavepointId++\n await transaction.execAsync(`SAVEPOINT ${savepointName}`)\n\n try {\n const result = await fn(transactionDriver)\n await transaction.execAsync(`RELEASE SAVEPOINT ${savepointName}`)\n return result\n } catch (error) {\n await transaction.execAsync(`ROLLBACK TO SAVEPOINT ${savepointName}`)\n await transaction.execAsync(`RELEASE SAVEPOINT ${savepointName}`)\n throw error\n }\n }\n}\n\nfunction normalizeParams(params: ReadonlyArray<unknown>): SQLiteBindParams {\n return params.map((value) => {\n if (\n value === null ||\n typeof value === `string` ||\n typeof value === `number` ||\n typeof value === `boolean` ||\n value instanceof Uint8Array\n ) {\n return value satisfies SQLiteBindValue\n }\n\n throw new TypeError(\n `Expo SQLite bind parameters must be strings, numbers, booleans, null, or Uint8Array values`,\n )\n })\n}\n\nexport function createExpoSQLiteDriver(\n options: ExpoSQLiteDriverOptions,\n): ExpoSQLiteDriver {\n return new ExpoSQLiteDriver(options)\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/expo-db-sqlite-persistence",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.25",
|
|
4
4
|
"description": "Expo SQLite persisted collection adapter for TanStack DB",
|
|
5
5
|
"author": "TanStack Team",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,16 +50,17 @@
|
|
|
50
50
|
"src"
|
|
51
51
|
],
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@tanstack/db-sqlite-persistence-core": "0.
|
|
53
|
+
"@tanstack/db-sqlite-persistence-core": "0.4.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"expo-sqlite": "^55.0.10",
|
|
56
|
+
"expo-sqlite": "^55.0.10 || ^57.0.0",
|
|
57
57
|
"typescript": ">=4.7"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@types/better-sqlite3": "^7.6.13",
|
|
61
61
|
"@vitest/coverage-istanbul": "^3.2.4",
|
|
62
|
-
"better-sqlite3": "^12.6.2"
|
|
62
|
+
"better-sqlite3": "^12.6.2",
|
|
63
|
+
"expo-sqlite-57": "npm:expo-sqlite@57.0.3"
|
|
63
64
|
},
|
|
64
65
|
"scripts": {
|
|
65
66
|
"build": "vite build",
|
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
import { InvalidPersistedCollectionConfigError } from '@tanstack/db-sqlite-persistence-core'
|
|
2
2
|
import type { SQLiteDriver } from '@tanstack/db-sqlite-persistence-core'
|
|
3
|
+
import type {
|
|
4
|
+
SQLiteBindParams,
|
|
5
|
+
SQLiteBindValue,
|
|
6
|
+
SQLiteRunResult,
|
|
7
|
+
} from 'expo-sqlite'
|
|
3
8
|
|
|
4
|
-
export type ExpoSQLiteBindParams =
|
|
5
|
-
| ReadonlyArray<unknown>
|
|
6
|
-
| Record<string, unknown>
|
|
9
|
+
export type ExpoSQLiteBindParams = SQLiteBindParams
|
|
7
10
|
|
|
8
|
-
export type ExpoSQLiteRunResult =
|
|
9
|
-
changes: number
|
|
10
|
-
lastInsertRowId: number
|
|
11
|
-
}
|
|
11
|
+
export type ExpoSQLiteRunResult = SQLiteRunResult
|
|
12
12
|
|
|
13
13
|
export type ExpoSQLiteQueryable = {
|
|
14
14
|
execAsync: (sql: string) => Promise<void>
|
|
15
|
-
getAllAsync:
|
|
16
|
-
sql: string,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
runAsync:
|
|
20
|
-
sql: string,
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
getAllAsync: {
|
|
16
|
+
<T>(sql: string, params: SQLiteBindParams): Promise<ReadonlyArray<T>>
|
|
17
|
+
<T>(sql: string): Promise<ReadonlyArray<T>>
|
|
18
|
+
}
|
|
19
|
+
runAsync: {
|
|
20
|
+
(sql: string, params: SQLiteBindParams): Promise<SQLiteRunResult>
|
|
21
|
+
(sql: string): Promise<SQLiteRunResult>
|
|
22
|
+
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export type ExpoSQLiteTransaction = ExpoSQLiteQueryable
|
|
26
26
|
|
|
27
27
|
export type ExpoSQLiteDatabaseLike = ExpoSQLiteQueryable & {
|
|
28
|
-
withExclusiveTransactionAsync:
|
|
29
|
-
task: (transaction: ExpoSQLiteTransaction) => Promise<
|
|
30
|
-
) => Promise<
|
|
28
|
+
withExclusiveTransactionAsync: (
|
|
29
|
+
task: (transaction: ExpoSQLiteTransaction) => Promise<void>,
|
|
30
|
+
) => Promise<void>
|
|
31
31
|
closeAsync?: () => Promise<void>
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -144,10 +144,12 @@ export class ExpoSQLiteDriver implements SQLiteDriver {
|
|
|
144
144
|
): Promise<T> {
|
|
145
145
|
return this.enqueue(async () => {
|
|
146
146
|
const database = await this.getDatabase()
|
|
147
|
-
|
|
147
|
+
let result: T | undefined
|
|
148
|
+
await database.withExclusiveTransactionAsync(async (transaction) => {
|
|
148
149
|
const transactionDriver = this.createTransactionDriver(transaction)
|
|
149
|
-
|
|
150
|
+
result = await fn(transactionDriver)
|
|
150
151
|
})
|
|
152
|
+
return result as T
|
|
151
153
|
})
|
|
152
154
|
}
|
|
153
155
|
|
|
@@ -225,10 +227,22 @@ export class ExpoSQLiteDriver implements SQLiteDriver {
|
|
|
225
227
|
}
|
|
226
228
|
}
|
|
227
229
|
|
|
228
|
-
function normalizeParams(
|
|
229
|
-
params
|
|
230
|
-
|
|
231
|
-
|
|
230
|
+
function normalizeParams(params: ReadonlyArray<unknown>): SQLiteBindParams {
|
|
231
|
+
return params.map((value) => {
|
|
232
|
+
if (
|
|
233
|
+
value === null ||
|
|
234
|
+
typeof value === `string` ||
|
|
235
|
+
typeof value === `number` ||
|
|
236
|
+
typeof value === `boolean` ||
|
|
237
|
+
value instanceof Uint8Array
|
|
238
|
+
) {
|
|
239
|
+
return value satisfies SQLiteBindValue
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
throw new TypeError(
|
|
243
|
+
`Expo SQLite bind parameters must be strings, numbers, booleans, null, or Uint8Array values`,
|
|
244
|
+
)
|
|
245
|
+
})
|
|
232
246
|
}
|
|
233
247
|
|
|
234
248
|
export function createExpoSQLiteDriver(
|