expo-sqlite 15.0.4 → 15.0.5
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/CHANGELOG.md +6 -0
- package/android/build.gradle +2 -2
- package/build/Storage.d.ts +1 -0
- package/build/Storage.d.ts.map +1 -1
- package/build/Storage.js +25 -9
- package/build/Storage.js.map +1 -1
- package/package.json +2 -2
- package/src/Storage.ts +34 -11
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 15.0.5 — 2024-12-30
|
|
14
|
+
|
|
15
|
+
_This version does not introduce any user-facing changes._
|
|
16
|
+
|
|
13
17
|
## 15.0.4 — 2024-12-26
|
|
14
18
|
|
|
15
19
|
### 🐛 Bug fixes
|
|
@@ -17,10 +21,12 @@
|
|
|
17
21
|
- Fixed exceptions when converting empty blob data on iOS. ([#33564](https://github.com/expo/expo/pull/33564) by [@kudo](https://github.com/kudo))
|
|
18
22
|
- Fixed `expo-sqlite/kv-store` async API not being well handled when using AsyncStorage compatible api ([#33847](https://github.com/expo/expo/pull/33847) by [@rtorrente](https://github.com/rtorrente))
|
|
19
23
|
- Fixed `database is locked` error from parallel `kv-store` operations. ([#33834](https://github.com/expo/expo/pull/33834) by [@kudo](https://github.com/kudo))
|
|
24
|
+
- Fixed `database is locked` error while using `kv-store multiGet` function. ([#33873](https://github.com/expo/expo/pull/33873) by [@rtorrente](https://github.com/rtorrente))
|
|
20
25
|
|
|
21
26
|
### 💡 Others
|
|
22
27
|
|
|
23
28
|
- Removed unused `SQLite3Wrapper` code for legacy implementation on Android. ([#33565](https://github.com/expo/expo/pull/33565) by [@kudo](https://github.com/kudo))
|
|
29
|
+
- Enforce input validations in `kv-store` operations. ([#33874](https://github.com/expo/expo/pull/33874) by [@rtorrente](https://github.com/rtorrente))
|
|
24
30
|
|
|
25
31
|
## 15.0.3 — 2024-11-12
|
|
26
32
|
|
package/android/build.gradle
CHANGED
|
@@ -3,7 +3,7 @@ import org.apache.tools.ant.taskdefs.condition.Os
|
|
|
3
3
|
apply plugin: 'com.android.library'
|
|
4
4
|
|
|
5
5
|
group = 'host.exp.exponent'
|
|
6
|
-
version = '15.0.
|
|
6
|
+
version = '15.0.5'
|
|
7
7
|
|
|
8
8
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
9
9
|
apply from: expoModulesCorePlugin
|
|
@@ -53,7 +53,7 @@ android {
|
|
|
53
53
|
namespace "expo.modules.sqlite"
|
|
54
54
|
defaultConfig {
|
|
55
55
|
versionCode 18
|
|
56
|
-
versionName "15.0.
|
|
56
|
+
versionName "15.0.5"
|
|
57
57
|
|
|
58
58
|
externalNativeBuild {
|
|
59
59
|
cmake {
|
package/build/Storage.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare function checkValidInput(...input: unknown[]): void;
|
|
1
2
|
/**
|
|
2
3
|
* Update function for the [`setItemAsync()`](#setitemasynckey-value) or [`setItemSync()`](#setitemsynckey-value) method. It computes the new value based on the previous value. The function returns the new value to set for the key.
|
|
3
4
|
* @param prevValue The previous value associated with the key, or `null` if the key was not set.
|
package/build/Storage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Storage.d.ts","sourceRoot":"","sources":["../src/Storage.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,MAAM,kCAAkC,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC;AAatF;;GAEG;AACH,qBAAa,aAAa;IAGZ,OAAO,CAAC,QAAQ,CAAC,YAAY;IAFzC,OAAO,CAAC,EAAE,CAA+B;gBAEZ,YAAY,EAAE,MAAM;IAIjD;;OAEG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"Storage.d.ts","sourceRoot":"","sources":["../src/Storage.ts"],"names":[],"mappings":"AAEA,wBAAgB,eAAe,CAAC,GAAG,KAAK,EAAE,OAAO,EAAE,QAclD;AAED;;;;GAIG;AACH,MAAM,MAAM,kCAAkC,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC;AAatF;;GAEG;AACH,qBAAa,aAAa;IAGZ,OAAO,CAAC,QAAQ,CAAC,YAAY;IAFzC,OAAO,CAAC,EAAE,CAA+B;gBAEZ,YAAY,EAAE,MAAM;IAIjD;;OAEG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAOvD;;;OAGG;IACG,YAAY,CAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,kCAAkC,GACjD,OAAO,CAAC,IAAI,CAAC;IAkBhB;;OAEG;IACG,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOpD;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAM1C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAMpC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAWjC;;OAEG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAOvC;;;OAGG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,kCAAkC,GAAG,IAAI;IAkBlF;;OAEG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAOpC;;OAEG;IACH,cAAc,IAAI,MAAM,EAAE;IAM1B;;OAEG;IACH,SAAS,IAAI,OAAO;IAMpB;;OAEG;IACH,SAAS,IAAI,IAAI;IAWjB;;OAEG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIlD;;OAEG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,kCAAkC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7F;;OAEG;IACG,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAIrC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;;OAGG;IACG,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa1D;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IASlE;;OAEG;IACG,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhE;;OAEG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhD;;;OAGG;IACG,UAAU,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBlE;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,kBAAkB;IAe1B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;CA4BzB;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,eAAyC,CAAC;AAEnE,eAAe,YAAY,CAAC;AAE5B;;GAEG;AACH,eAAO,MAAM,OAAO,eAAe,CAAC"}
|
package/build/Storage.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { openDatabaseSync } from './index';
|
|
2
|
+
export function checkValidInput(...input) {
|
|
3
|
+
const [key, value] = input;
|
|
4
|
+
if (typeof key !== 'string') {
|
|
5
|
+
throw new Error(`[SQLiteStorage] Using ${typeof key} type for key is not supported. Use string instead. Key passed: ${key}`);
|
|
6
|
+
}
|
|
7
|
+
if (input.length > 1 && typeof value !== 'string' && typeof value !== 'function') {
|
|
8
|
+
throw new Error(`[SQLiteStorage] Using ${typeof value} type for value is not supported. Use string instead. Key passed: ${key}. Value passed : ${value}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
2
11
|
const DATABASE_VERSION = 1;
|
|
3
12
|
const STATEMENT_GET = 'SELECT value FROM storage WHERE key = ?;';
|
|
4
13
|
const STATEMENT_SET = 'INSERT INTO storage (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value;';
|
|
@@ -20,6 +29,7 @@ export class SQLiteStorage {
|
|
|
20
29
|
* Retrieves the value associated with the given key asynchronously.
|
|
21
30
|
*/
|
|
22
31
|
async getItemAsync(key) {
|
|
32
|
+
checkValidInput(key);
|
|
23
33
|
const db = this.getDbSync();
|
|
24
34
|
const result = await db.getFirstAsync(STATEMENT_GET, key);
|
|
25
35
|
return result?.value ?? null;
|
|
@@ -29,12 +39,14 @@ export class SQLiteStorage {
|
|
|
29
39
|
* If a function is provided, it computes the new value based on the previous value.
|
|
30
40
|
*/
|
|
31
41
|
async setItemAsync(key, value) {
|
|
42
|
+
checkValidInput(key, value);
|
|
32
43
|
const db = this.getDbSync();
|
|
33
44
|
if (typeof value === 'function') {
|
|
34
45
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
35
46
|
const prevResult = await tx.getFirstAsync(STATEMENT_GET, key);
|
|
36
47
|
const prevValue = prevResult?.value ?? null;
|
|
37
48
|
const nextValue = value(prevValue);
|
|
49
|
+
checkValidInput(key, nextValue);
|
|
38
50
|
await tx.runAsync(STATEMENT_SET, key, nextValue);
|
|
39
51
|
});
|
|
40
52
|
return;
|
|
@@ -45,6 +57,7 @@ export class SQLiteStorage {
|
|
|
45
57
|
* Removes the value associated with the given key asynchronously.
|
|
46
58
|
*/
|
|
47
59
|
async removeItemAsync(key) {
|
|
60
|
+
checkValidInput(key);
|
|
48
61
|
const db = this.getDbSync();
|
|
49
62
|
const result = await db.runAsync(STATEMENT_REMOVE, key);
|
|
50
63
|
return result.changes > 0;
|
|
@@ -80,6 +93,7 @@ export class SQLiteStorage {
|
|
|
80
93
|
* Retrieves the value associated with the given key synchronously.
|
|
81
94
|
*/
|
|
82
95
|
getItemSync(key) {
|
|
96
|
+
checkValidInput(key);
|
|
83
97
|
const db = this.getDbSync();
|
|
84
98
|
const result = db.getFirstSync(STATEMENT_GET, key);
|
|
85
99
|
return result?.value ?? null;
|
|
@@ -89,12 +103,14 @@ export class SQLiteStorage {
|
|
|
89
103
|
* If a function is provided, it computes the new value based on the previous value.
|
|
90
104
|
*/
|
|
91
105
|
setItemSync(key, value) {
|
|
106
|
+
checkValidInput(key, value);
|
|
92
107
|
const db = this.getDbSync();
|
|
93
108
|
if (typeof value === 'function') {
|
|
94
109
|
db.withTransactionSync(() => {
|
|
95
110
|
const prevResult = db.getFirstSync(STATEMENT_GET, key);
|
|
96
111
|
const prevValue = prevResult?.value ?? null;
|
|
97
112
|
const nextValue = value(prevValue);
|
|
113
|
+
checkValidInput(key, nextValue);
|
|
98
114
|
db.runSync(STATEMENT_SET, key, nextValue);
|
|
99
115
|
});
|
|
100
116
|
return;
|
|
@@ -105,6 +121,7 @@ export class SQLiteStorage {
|
|
|
105
121
|
* Removes the value associated with the given key synchronously.
|
|
106
122
|
*/
|
|
107
123
|
removeItemSync(key) {
|
|
124
|
+
checkValidInput(key);
|
|
108
125
|
const db = this.getDbSync();
|
|
109
126
|
const result = db.runSync(STATEMENT_REMOVE, key);
|
|
110
127
|
return result.changes > 0;
|
|
@@ -171,6 +188,7 @@ export class SQLiteStorage {
|
|
|
171
188
|
* If the existing value is a JSON object, performs a deep merge.
|
|
172
189
|
*/
|
|
173
190
|
async mergeItem(key, value) {
|
|
191
|
+
checkValidInput(key, value);
|
|
174
192
|
await this.setItemAsync(key, (prevValue) => {
|
|
175
193
|
if (prevValue == null) {
|
|
176
194
|
return value;
|
|
@@ -185,15 +203,10 @@ export class SQLiteStorage {
|
|
|
185
203
|
* Retrieves the values associated with the given keys asynchronously.
|
|
186
204
|
*/
|
|
187
205
|
async multiGet(keys) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
const row = await tx.getFirstAsync(STATEMENT_GET, key);
|
|
193
|
-
return [key, row?.value ?? null];
|
|
194
|
-
}));
|
|
195
|
-
});
|
|
196
|
-
return result;
|
|
206
|
+
return Promise.all(keys.map(async (key) => {
|
|
207
|
+
checkValidInput(key);
|
|
208
|
+
return [key, await this.getItemAsync(key)];
|
|
209
|
+
}));
|
|
197
210
|
}
|
|
198
211
|
/**
|
|
199
212
|
* Sets multiple key-value pairs asynchronously.
|
|
@@ -202,6 +215,7 @@ export class SQLiteStorage {
|
|
|
202
215
|
const db = this.getDbSync();
|
|
203
216
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
204
217
|
for (const [key, value] of keyValuePairs) {
|
|
218
|
+
checkValidInput(key, value);
|
|
205
219
|
await tx.runAsync(STATEMENT_SET, key, value);
|
|
206
220
|
}
|
|
207
221
|
});
|
|
@@ -213,6 +227,7 @@ export class SQLiteStorage {
|
|
|
213
227
|
const db = this.getDbSync();
|
|
214
228
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
215
229
|
for (const key of keys) {
|
|
230
|
+
checkValidInput(key);
|
|
216
231
|
await tx.runAsync(STATEMENT_REMOVE, key);
|
|
217
232
|
}
|
|
218
233
|
});
|
|
@@ -225,6 +240,7 @@ export class SQLiteStorage {
|
|
|
225
240
|
const db = this.getDbSync();
|
|
226
241
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
227
242
|
for (const [key, value] of keyValuePairs) {
|
|
243
|
+
checkValidInput(key, value);
|
|
228
244
|
const prevValue = await tx.getFirstAsync(STATEMENT_GET, key);
|
|
229
245
|
if (prevValue == null) {
|
|
230
246
|
await tx.runAsync(STATEMENT_SET, key, value);
|
package/build/Storage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Storage.js","sourceRoot":"","sources":["../src/Storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { openDatabaseSync, type SQLiteDatabase } from './index';\n\n/**\n * Update function for the [`setItemAsync()`](#setitemasynckey-value) or [`setItemSync()`](#setitemsynckey-value) method. It computes the new value based on the previous value. The function returns the new value to set for the key.\n * @param prevValue The previous value associated with the key, or `null` if the key was not set.\n * @returns The new value to set for the key.\n */\nexport type SQLiteStorageSetItemUpdateFunction = (prevValue: string | null) => string;\n\nconst DATABASE_VERSION = 1;\nconst STATEMENT_GET = 'SELECT value FROM storage WHERE key = ?;';\nconst STATEMENT_SET =\n 'INSERT INTO storage (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value;';\nconst STATEMENT_REMOVE = 'DELETE FROM storage WHERE key = ?;';\nconst STATEMENT_GET_ALL_KEYS = 'SELECT key FROM storage;';\nconst STATEMENT_CLEAR = 'DELETE FROM storage;';\n\nconst MIGRATION_STATEMENT_0 =\n 'CREATE TABLE IF NOT EXISTS storage (key TEXT PRIMARY KEY NOT NULL, value TEXT);';\n\n/**\n * Key-value store backed by SQLite. This class accepts a `databaseName` parameter in its constructor, which is the name of the database file to use for the storage.\n */\nexport class SQLiteStorage {\n private db: SQLiteDatabase | null = null;\n\n constructor(private readonly databaseName: string) {}\n\n //#region Asynchronous API\n\n /**\n * Retrieves the value associated with the given key asynchronously.\n */\n async getItemAsync(key: string): Promise<string | null> {\n const db = this.getDbSync();\n const result = await db.getFirstAsync<{ value: string }>(STATEMENT_GET, key);\n return result?.value ?? null;\n }\n\n /**\n * Sets the value for the given key asynchronously.\n * If a function is provided, it computes the new value based on the previous value.\n */\n async setItemAsync(\n key: string,\n value: string | SQLiteStorageSetItemUpdateFunction\n ): Promise<void> {\n const db = this.getDbSync();\n\n if (typeof value === 'function') {\n await db.withExclusiveTransactionAsync(async (tx) => {\n const prevResult = await tx.getFirstAsync<{ value: string }>(STATEMENT_GET, key);\n const prevValue = prevResult?.value ?? null;\n const nextValue = value(prevValue);\n await tx.runAsync(STATEMENT_SET, key, nextValue);\n });\n return;\n }\n\n await db.runAsync(STATEMENT_SET, key, value);\n }\n\n /**\n * Removes the value associated with the given key asynchronously.\n */\n async removeItemAsync(key: string): Promise<boolean> {\n const db = this.getDbSync();\n const result = await db.runAsync(STATEMENT_REMOVE, key);\n return result.changes > 0;\n }\n\n /**\n * Retrieves all keys stored in the storage asynchronously.\n */\n async getAllKeysAsync(): Promise<string[]> {\n const db = this.getDbSync();\n const result = await db.getAllAsync<{ key: string }>(STATEMENT_GET_ALL_KEYS);\n return result.map(({ key }) => key);\n }\n\n /**\n * Clears all key-value pairs from the storage asynchronously.\n */\n async clearAsync(): Promise<boolean> {\n const db = this.getDbSync();\n const result = await db.runAsync(STATEMENT_CLEAR);\n return result.changes > 0;\n }\n\n /**\n * Closes the database connection asynchronously.\n */\n async closeAsync(): Promise<void> {\n if (this.db) {\n await this.db.closeAsync();\n this.db = null;\n }\n }\n\n //#endregion\n\n //#region Synchronous API\n\n /**\n * Retrieves the value associated with the given key synchronously.\n */\n getItemSync(key: string): string | null {\n const db = this.getDbSync();\n const result = db.getFirstSync<{ value: string }>(STATEMENT_GET, key);\n return result?.value ?? null;\n }\n\n /**\n * Sets the value for the given key synchronously.\n * If a function is provided, it computes the new value based on the previous value.\n */\n setItemSync(key: string, value: string | SQLiteStorageSetItemUpdateFunction): void {\n const db = this.getDbSync();\n\n if (typeof value === 'function') {\n db.withTransactionSync(() => {\n const prevResult = db.getFirstSync<{ value: string }>(STATEMENT_GET, key);\n const prevValue = prevResult?.value ?? null;\n const nextValue = value(prevValue);\n db.runSync(STATEMENT_SET, key, nextValue);\n });\n return;\n }\n\n db.runSync(STATEMENT_SET, key, value);\n }\n\n /**\n * Removes the value associated with the given key synchronously.\n */\n removeItemSync(key: string): boolean {\n const db = this.getDbSync();\n const result = db.runSync(STATEMENT_REMOVE, key);\n return result.changes > 0;\n }\n\n /**\n * Retrieves all keys stored in the storage synchronously.\n */\n getAllKeysSync(): string[] {\n const db = this.getDbSync();\n const result = db.getAllSync<{ key: string }>(STATEMENT_GET_ALL_KEYS);\n return result.map(({ key }) => key);\n }\n\n /**\n * Clears all key-value pairs from the storage synchronously.\n */\n clearSync(): boolean {\n const db = this.getDbSync();\n const result = db.runSync(STATEMENT_CLEAR);\n return result.changes > 0;\n }\n\n /**\n * Closes the database connection synchronously.\n */\n closeSync(): void {\n if (this.db) {\n this.db.closeSync();\n this.db = null;\n }\n }\n\n //#endregion\n\n //#region react-native-async-storage compatible API\n\n /**\n * Alias for [`getItemAsync()`](#getitemasynckey) method.\n */\n async getItem(key: string): Promise<string | null> {\n return this.getItemAsync(key);\n }\n\n /**\n * Alias for [`setItemAsync()`](#setitemasynckey-value).\n */\n async setItem(key: string, value: string | SQLiteStorageSetItemUpdateFunction): Promise<void> {\n await this.setItemAsync(key, value);\n }\n\n /**\n * Alias for [`removeItemAsync()`](#removeitemasynckey) method.\n */\n async removeItem(key: string): Promise<void> {\n await this.removeItemAsync(key);\n }\n\n /**\n * Alias for [`getAllKeysAsync()`](#getallkeysasync) method.\n */\n async getAllKeys(): Promise<string[]> {\n return this.getAllKeysAsync();\n }\n\n /**\n * Alias for [`clearAsync()`](#clearasync) method.\n */\n async clear(): Promise<void> {\n await this.clearAsync();\n }\n\n /**\n * Merges the given value with the existing value for the given key asynchronously.\n * If the existing value is a JSON object, performs a deep merge.\n */\n async mergeItem(key: string, value: string): Promise<void> {\n await this.setItemAsync(key, (prevValue) => {\n if (prevValue == null) {\n return value;\n }\n const prevJSON = JSON.parse(prevValue);\n const newJSON = JSON.parse(value);\n const mergedJSON = SQLiteStorage.mergeDeep(prevJSON, newJSON);\n return JSON.stringify(mergedJSON);\n });\n }\n\n /**\n * Retrieves the values associated with the given keys asynchronously.\n */\n async multiGet(keys: string[]): Promise<[string, string | null][]> {\n const db = this.getDbSync();\n let result: [string, string | null][] = [];\n await db.withExclusiveTransactionAsync(async (tx) => {\n result = await Promise.all(\n keys.map(async (key) => {\n const row = await tx.getFirstAsync<{ value: string }>(STATEMENT_GET, key);\n return [key, row?.value ?? null];\n })\n );\n });\n return result;\n }\n\n /**\n * Sets multiple key-value pairs asynchronously.\n */\n async multiSet(keyValuePairs: [string, string][]): Promise<void> {\n const db = this.getDbSync();\n await db.withExclusiveTransactionAsync(async (tx) => {\n for (const [key, value] of keyValuePairs) {\n await tx.runAsync(STATEMENT_SET, key, value);\n }\n });\n }\n\n /**\n * Removes the values associated with the given keys asynchronously.\n */\n async multiRemove(keys: string[]): Promise<void> {\n const db = this.getDbSync();\n await db.withExclusiveTransactionAsync(async (tx) => {\n for (const key of keys) {\n await tx.runAsync(STATEMENT_REMOVE, key);\n }\n });\n }\n\n /**\n * Merges multiple key-value pairs asynchronously.\n * If existing values are JSON objects, performs a deep merge.\n */\n async multiMerge(keyValuePairs: [string, string][]): Promise<void> {\n const db = this.getDbSync();\n await db.withExclusiveTransactionAsync(async (tx) => {\n for (const [key, value] of keyValuePairs) {\n const prevValue = await tx.getFirstAsync<{ value: string }>(STATEMENT_GET, key);\n if (prevValue == null) {\n await tx.runAsync(STATEMENT_SET, key, value);\n continue;\n }\n const prevJSON = JSON.parse(prevValue.value);\n const newJSON = JSON.parse(value);\n const mergedJSON = SQLiteStorage.mergeDeep(prevJSON, newJSON);\n await tx.runAsync(STATEMENT_SET, key, JSON.stringify(mergedJSON));\n }\n });\n }\n\n /**\n * Alias for [`closeAsync()`](#closeasync-1) method.\n */\n async close(): Promise<void> {\n await this.closeAsync();\n }\n\n //#endregion\n\n //#region Internals\n\n private getDbSync(): SQLiteDatabase {\n if (!this.db) {\n const db = openDatabaseSync(this.databaseName);\n this.maybeMigrateDbSync(db);\n this.db = db;\n }\n return this.db;\n }\n\n private maybeMigrateDbSync(db: SQLiteDatabase) {\n db.withTransactionSync(() => {\n const result = db.getFirstSync<{ user_version: number }>('PRAGMA user_version');\n let currentDbVersion = result?.user_version ?? 0;\n if (currentDbVersion >= DATABASE_VERSION) {\n return;\n }\n if (currentDbVersion === 0) {\n db.execSync(MIGRATION_STATEMENT_0);\n currentDbVersion = 1;\n }\n db.execSync(`PRAGMA user_version = ${DATABASE_VERSION}`);\n });\n }\n\n /**\n * Recursively merge two JSON objects.\n */\n private static mergeDeep(target: any, source: any): any {\n if (typeof target !== 'object' || target === null) {\n return source;\n }\n\n if (typeof source !== 'object' || source === null) {\n return target;\n }\n\n const output = { ...target };\n\n for (const key of Object.keys(source)) {\n if (source[key] instanceof Array) {\n if (!output[key]) {\n output[key] = [];\n }\n output[key] = output[key].concat(source[key]);\n } else if (typeof source[key] === 'object') {\n output[key] = this.mergeDeep(target[key], source[key]);\n } else {\n output[key] = source[key];\n }\n }\n\n return output;\n }\n\n //#endregion\n}\n\n/**\n * This default instance of the [`SQLiteStorage`](#sqlitestorage-1) class is used as a drop-in replacement for the `AsyncStorage` module from [`@react-native-async-storage/async-storage`](https://github.com/react-native-async-storage/async-storage).\n */\nexport const AsyncStorage = new SQLiteStorage('ExpoSQLiteStorage');\n\nexport default AsyncStorage;\n\n/**\n * Alias for [`AsyncStorage`](#sqliteasyncstorage), given the storage not only offers asynchronous methods.\n */\nexport const Storage = AsyncStorage;\n"]}
|
|
1
|
+
{"version":3,"file":"Storage.js","sourceRoot":"","sources":["../src/Storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { openDatabaseSync, type SQLiteDatabase } from './index';\n\nexport function checkValidInput(...input: unknown[]) {\n const [key, value] = input;\n\n if (typeof key !== 'string') {\n throw new Error(\n `[SQLiteStorage] Using ${typeof key} type for key is not supported. Use string instead. Key passed: ${key}`\n );\n }\n\n if (input.length > 1 && typeof value !== 'string' && typeof value !== 'function') {\n throw new Error(\n `[SQLiteStorage] Using ${typeof value} type for value is not supported. Use string instead. Key passed: ${key}. Value passed : ${value}`\n );\n }\n}\n\n/**\n * Update function for the [`setItemAsync()`](#setitemasynckey-value) or [`setItemSync()`](#setitemsynckey-value) method. It computes the new value based on the previous value. The function returns the new value to set for the key.\n * @param prevValue The previous value associated with the key, or `null` if the key was not set.\n * @returns The new value to set for the key.\n */\nexport type SQLiteStorageSetItemUpdateFunction = (prevValue: string | null) => string;\n\nconst DATABASE_VERSION = 1;\nconst STATEMENT_GET = 'SELECT value FROM storage WHERE key = ?;';\nconst STATEMENT_SET =\n 'INSERT INTO storage (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value;';\nconst STATEMENT_REMOVE = 'DELETE FROM storage WHERE key = ?;';\nconst STATEMENT_GET_ALL_KEYS = 'SELECT key FROM storage;';\nconst STATEMENT_CLEAR = 'DELETE FROM storage;';\n\nconst MIGRATION_STATEMENT_0 =\n 'CREATE TABLE IF NOT EXISTS storage (key TEXT PRIMARY KEY NOT NULL, value TEXT);';\n\n/**\n * Key-value store backed by SQLite. This class accepts a `databaseName` parameter in its constructor, which is the name of the database file to use for the storage.\n */\nexport class SQLiteStorage {\n private db: SQLiteDatabase | null = null;\n\n constructor(private readonly databaseName: string) {}\n\n //#region Asynchronous API\n\n /**\n * Retrieves the value associated with the given key asynchronously.\n */\n async getItemAsync(key: string): Promise<string | null> {\n checkValidInput(key);\n const db = this.getDbSync();\n const result = await db.getFirstAsync<{ value: string }>(STATEMENT_GET, key);\n return result?.value ?? null;\n }\n\n /**\n * Sets the value for the given key asynchronously.\n * If a function is provided, it computes the new value based on the previous value.\n */\n async setItemAsync(\n key: string,\n value: string | SQLiteStorageSetItemUpdateFunction\n ): Promise<void> {\n checkValidInput(key, value);\n const db = this.getDbSync();\n\n if (typeof value === 'function') {\n await db.withExclusiveTransactionAsync(async (tx) => {\n const prevResult = await tx.getFirstAsync<{ value: string }>(STATEMENT_GET, key);\n const prevValue = prevResult?.value ?? null;\n const nextValue = value(prevValue);\n checkValidInput(key, nextValue);\n await tx.runAsync(STATEMENT_SET, key, nextValue);\n });\n return;\n }\n\n await db.runAsync(STATEMENT_SET, key, value);\n }\n\n /**\n * Removes the value associated with the given key asynchronously.\n */\n async removeItemAsync(key: string): Promise<boolean> {\n checkValidInput(key);\n const db = this.getDbSync();\n const result = await db.runAsync(STATEMENT_REMOVE, key);\n return result.changes > 0;\n }\n\n /**\n * Retrieves all keys stored in the storage asynchronously.\n */\n async getAllKeysAsync(): Promise<string[]> {\n const db = this.getDbSync();\n const result = await db.getAllAsync<{ key: string }>(STATEMENT_GET_ALL_KEYS);\n return result.map(({ key }) => key);\n }\n\n /**\n * Clears all key-value pairs from the storage asynchronously.\n */\n async clearAsync(): Promise<boolean> {\n const db = this.getDbSync();\n const result = await db.runAsync(STATEMENT_CLEAR);\n return result.changes > 0;\n }\n\n /**\n * Closes the database connection asynchronously.\n */\n async closeAsync(): Promise<void> {\n if (this.db) {\n await this.db.closeAsync();\n this.db = null;\n }\n }\n\n //#endregion\n\n //#region Synchronous API\n\n /**\n * Retrieves the value associated with the given key synchronously.\n */\n getItemSync(key: string): string | null {\n checkValidInput(key);\n const db = this.getDbSync();\n const result = db.getFirstSync<{ value: string }>(STATEMENT_GET, key);\n return result?.value ?? null;\n }\n\n /**\n * Sets the value for the given key synchronously.\n * If a function is provided, it computes the new value based on the previous value.\n */\n setItemSync(key: string, value: string | SQLiteStorageSetItemUpdateFunction): void {\n checkValidInput(key, value);\n const db = this.getDbSync();\n\n if (typeof value === 'function') {\n db.withTransactionSync(() => {\n const prevResult = db.getFirstSync<{ value: string }>(STATEMENT_GET, key);\n const prevValue = prevResult?.value ?? null;\n const nextValue = value(prevValue);\n checkValidInput(key, nextValue);\n db.runSync(STATEMENT_SET, key, nextValue);\n });\n return;\n }\n\n db.runSync(STATEMENT_SET, key, value);\n }\n\n /**\n * Removes the value associated with the given key synchronously.\n */\n removeItemSync(key: string): boolean {\n checkValidInput(key);\n const db = this.getDbSync();\n const result = db.runSync(STATEMENT_REMOVE, key);\n return result.changes > 0;\n }\n\n /**\n * Retrieves all keys stored in the storage synchronously.\n */\n getAllKeysSync(): string[] {\n const db = this.getDbSync();\n const result = db.getAllSync<{ key: string }>(STATEMENT_GET_ALL_KEYS);\n return result.map(({ key }) => key);\n }\n\n /**\n * Clears all key-value pairs from the storage synchronously.\n */\n clearSync(): boolean {\n const db = this.getDbSync();\n const result = db.runSync(STATEMENT_CLEAR);\n return result.changes > 0;\n }\n\n /**\n * Closes the database connection synchronously.\n */\n closeSync(): void {\n if (this.db) {\n this.db.closeSync();\n this.db = null;\n }\n }\n\n //#endregion\n\n //#region react-native-async-storage compatible API\n\n /**\n * Alias for [`getItemAsync()`](#getitemasynckey) method.\n */\n async getItem(key: string): Promise<string | null> {\n return this.getItemAsync(key);\n }\n\n /**\n * Alias for [`setItemAsync()`](#setitemasynckey-value).\n */\n async setItem(key: string, value: string | SQLiteStorageSetItemUpdateFunction): Promise<void> {\n await this.setItemAsync(key, value);\n }\n\n /**\n * Alias for [`removeItemAsync()`](#removeitemasynckey) method.\n */\n async removeItem(key: string): Promise<void> {\n await this.removeItemAsync(key);\n }\n\n /**\n * Alias for [`getAllKeysAsync()`](#getallkeysasync) method.\n */\n async getAllKeys(): Promise<string[]> {\n return this.getAllKeysAsync();\n }\n\n /**\n * Alias for [`clearAsync()`](#clearasync) method.\n */\n async clear(): Promise<void> {\n await this.clearAsync();\n }\n\n /**\n * Merges the given value with the existing value for the given key asynchronously.\n * If the existing value is a JSON object, performs a deep merge.\n */\n async mergeItem(key: string, value: string): Promise<void> {\n checkValidInput(key, value);\n await this.setItemAsync(key, (prevValue) => {\n if (prevValue == null) {\n return value;\n }\n const prevJSON = JSON.parse(prevValue);\n const newJSON = JSON.parse(value);\n const mergedJSON = SQLiteStorage.mergeDeep(prevJSON, newJSON);\n return JSON.stringify(mergedJSON);\n });\n }\n\n /**\n * Retrieves the values associated with the given keys asynchronously.\n */\n async multiGet(keys: string[]): Promise<[string, string | null][]> {\n return Promise.all(\n keys.map(async (key): Promise<[string, string | null]> => {\n checkValidInput(key);\n return [key, await this.getItemAsync(key)];\n })\n );\n }\n\n /**\n * Sets multiple key-value pairs asynchronously.\n */\n async multiSet(keyValuePairs: [string, string][]): Promise<void> {\n const db = this.getDbSync();\n await db.withExclusiveTransactionAsync(async (tx) => {\n for (const [key, value] of keyValuePairs) {\n checkValidInput(key, value);\n await tx.runAsync(STATEMENT_SET, key, value);\n }\n });\n }\n\n /**\n * Removes the values associated with the given keys asynchronously.\n */\n async multiRemove(keys: string[]): Promise<void> {\n const db = this.getDbSync();\n await db.withExclusiveTransactionAsync(async (tx) => {\n for (const key of keys) {\n checkValidInput(key);\n await tx.runAsync(STATEMENT_REMOVE, key);\n }\n });\n }\n\n /**\n * Merges multiple key-value pairs asynchronously.\n * If existing values are JSON objects, performs a deep merge.\n */\n async multiMerge(keyValuePairs: [string, string][]): Promise<void> {\n const db = this.getDbSync();\n await db.withExclusiveTransactionAsync(async (tx) => {\n for (const [key, value] of keyValuePairs) {\n checkValidInput(key, value);\n const prevValue = await tx.getFirstAsync<{ value: string }>(STATEMENT_GET, key);\n if (prevValue == null) {\n await tx.runAsync(STATEMENT_SET, key, value);\n continue;\n }\n const prevJSON = JSON.parse(prevValue.value);\n const newJSON = JSON.parse(value);\n const mergedJSON = SQLiteStorage.mergeDeep(prevJSON, newJSON);\n await tx.runAsync(STATEMENT_SET, key, JSON.stringify(mergedJSON));\n }\n });\n }\n\n /**\n * Alias for [`closeAsync()`](#closeasync-1) method.\n */\n async close(): Promise<void> {\n await this.closeAsync();\n }\n\n //#endregion\n\n //#region Internals\n\n private getDbSync(): SQLiteDatabase {\n if (!this.db) {\n const db = openDatabaseSync(this.databaseName);\n this.maybeMigrateDbSync(db);\n this.db = db;\n }\n return this.db;\n }\n\n private maybeMigrateDbSync(db: SQLiteDatabase) {\n db.withTransactionSync(() => {\n const result = db.getFirstSync<{ user_version: number }>('PRAGMA user_version');\n let currentDbVersion = result?.user_version ?? 0;\n if (currentDbVersion >= DATABASE_VERSION) {\n return;\n }\n if (currentDbVersion === 0) {\n db.execSync(MIGRATION_STATEMENT_0);\n currentDbVersion = 1;\n }\n db.execSync(`PRAGMA user_version = ${DATABASE_VERSION}`);\n });\n }\n\n /**\n * Recursively merge two JSON objects.\n */\n private static mergeDeep(target: any, source: any): any {\n if (typeof target !== 'object' || target === null) {\n return source;\n }\n\n if (typeof source !== 'object' || source === null) {\n return target;\n }\n\n const output = { ...target };\n\n for (const key of Object.keys(source)) {\n if (source[key] instanceof Array) {\n if (!output[key]) {\n output[key] = [];\n }\n output[key] = output[key].concat(source[key]);\n } else if (typeof source[key] === 'object') {\n output[key] = this.mergeDeep(target[key], source[key]);\n } else {\n output[key] = source[key];\n }\n }\n\n return output;\n }\n\n //#endregion\n}\n\n/**\n * This default instance of the [`SQLiteStorage`](#sqlitestorage-1) class is used as a drop-in replacement for the `AsyncStorage` module from [`@react-native-async-storage/async-storage`](https://github.com/react-native-async-storage/async-storage).\n */\nexport const AsyncStorage = new SQLiteStorage('ExpoSQLiteStorage');\n\nexport default AsyncStorage;\n\n/**\n * Alias for [`AsyncStorage`](#sqliteasyncstorage), given the storage not only offers asynchronous methods.\n */\nexport const Storage = AsyncStorage;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-sqlite",
|
|
3
|
-
"version": "15.0.
|
|
3
|
+
"version": "15.0.5",
|
|
4
4
|
"description": "Provides access to a database using SQLite (https://www.sqlite.org/). The database is persisted across restarts of your app.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"react": "*",
|
|
62
62
|
"react-native": "*"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "03394549f5401074f21b09c1a648a789bdc35956"
|
|
65
65
|
}
|
package/src/Storage.ts
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import { openDatabaseSync, type SQLiteDatabase } from './index';
|
|
2
2
|
|
|
3
|
+
export function checkValidInput(...input: unknown[]) {
|
|
4
|
+
const [key, value] = input;
|
|
5
|
+
|
|
6
|
+
if (typeof key !== 'string') {
|
|
7
|
+
throw new Error(
|
|
8
|
+
`[SQLiteStorage] Using ${typeof key} type for key is not supported. Use string instead. Key passed: ${key}`
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (input.length > 1 && typeof value !== 'string' && typeof value !== 'function') {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`[SQLiteStorage] Using ${typeof value} type for value is not supported. Use string instead. Key passed: ${key}. Value passed : ${value}`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
3
19
|
/**
|
|
4
20
|
* Update function for the [`setItemAsync()`](#setitemasynckey-value) or [`setItemSync()`](#setitemsynckey-value) method. It computes the new value based on the previous value. The function returns the new value to set for the key.
|
|
5
21
|
* @param prevValue The previous value associated with the key, or `null` if the key was not set.
|
|
@@ -32,6 +48,7 @@ export class SQLiteStorage {
|
|
|
32
48
|
* Retrieves the value associated with the given key asynchronously.
|
|
33
49
|
*/
|
|
34
50
|
async getItemAsync(key: string): Promise<string | null> {
|
|
51
|
+
checkValidInput(key);
|
|
35
52
|
const db = this.getDbSync();
|
|
36
53
|
const result = await db.getFirstAsync<{ value: string }>(STATEMENT_GET, key);
|
|
37
54
|
return result?.value ?? null;
|
|
@@ -45,6 +62,7 @@ export class SQLiteStorage {
|
|
|
45
62
|
key: string,
|
|
46
63
|
value: string | SQLiteStorageSetItemUpdateFunction
|
|
47
64
|
): Promise<void> {
|
|
65
|
+
checkValidInput(key, value);
|
|
48
66
|
const db = this.getDbSync();
|
|
49
67
|
|
|
50
68
|
if (typeof value === 'function') {
|
|
@@ -52,6 +70,7 @@ export class SQLiteStorage {
|
|
|
52
70
|
const prevResult = await tx.getFirstAsync<{ value: string }>(STATEMENT_GET, key);
|
|
53
71
|
const prevValue = prevResult?.value ?? null;
|
|
54
72
|
const nextValue = value(prevValue);
|
|
73
|
+
checkValidInput(key, nextValue);
|
|
55
74
|
await tx.runAsync(STATEMENT_SET, key, nextValue);
|
|
56
75
|
});
|
|
57
76
|
return;
|
|
@@ -64,6 +83,7 @@ export class SQLiteStorage {
|
|
|
64
83
|
* Removes the value associated with the given key asynchronously.
|
|
65
84
|
*/
|
|
66
85
|
async removeItemAsync(key: string): Promise<boolean> {
|
|
86
|
+
checkValidInput(key);
|
|
67
87
|
const db = this.getDbSync();
|
|
68
88
|
const result = await db.runAsync(STATEMENT_REMOVE, key);
|
|
69
89
|
return result.changes > 0;
|
|
@@ -105,6 +125,7 @@ export class SQLiteStorage {
|
|
|
105
125
|
* Retrieves the value associated with the given key synchronously.
|
|
106
126
|
*/
|
|
107
127
|
getItemSync(key: string): string | null {
|
|
128
|
+
checkValidInput(key);
|
|
108
129
|
const db = this.getDbSync();
|
|
109
130
|
const result = db.getFirstSync<{ value: string }>(STATEMENT_GET, key);
|
|
110
131
|
return result?.value ?? null;
|
|
@@ -115,6 +136,7 @@ export class SQLiteStorage {
|
|
|
115
136
|
* If a function is provided, it computes the new value based on the previous value.
|
|
116
137
|
*/
|
|
117
138
|
setItemSync(key: string, value: string | SQLiteStorageSetItemUpdateFunction): void {
|
|
139
|
+
checkValidInput(key, value);
|
|
118
140
|
const db = this.getDbSync();
|
|
119
141
|
|
|
120
142
|
if (typeof value === 'function') {
|
|
@@ -122,6 +144,7 @@ export class SQLiteStorage {
|
|
|
122
144
|
const prevResult = db.getFirstSync<{ value: string }>(STATEMENT_GET, key);
|
|
123
145
|
const prevValue = prevResult?.value ?? null;
|
|
124
146
|
const nextValue = value(prevValue);
|
|
147
|
+
checkValidInput(key, nextValue);
|
|
125
148
|
db.runSync(STATEMENT_SET, key, nextValue);
|
|
126
149
|
});
|
|
127
150
|
return;
|
|
@@ -134,6 +157,7 @@ export class SQLiteStorage {
|
|
|
134
157
|
* Removes the value associated with the given key synchronously.
|
|
135
158
|
*/
|
|
136
159
|
removeItemSync(key: string): boolean {
|
|
160
|
+
checkValidInput(key);
|
|
137
161
|
const db = this.getDbSync();
|
|
138
162
|
const result = db.runSync(STATEMENT_REMOVE, key);
|
|
139
163
|
return result.changes > 0;
|
|
@@ -211,6 +235,7 @@ export class SQLiteStorage {
|
|
|
211
235
|
* If the existing value is a JSON object, performs a deep merge.
|
|
212
236
|
*/
|
|
213
237
|
async mergeItem(key: string, value: string): Promise<void> {
|
|
238
|
+
checkValidInput(key, value);
|
|
214
239
|
await this.setItemAsync(key, (prevValue) => {
|
|
215
240
|
if (prevValue == null) {
|
|
216
241
|
return value;
|
|
@@ -226,17 +251,12 @@ export class SQLiteStorage {
|
|
|
226
251
|
* Retrieves the values associated with the given keys asynchronously.
|
|
227
252
|
*/
|
|
228
253
|
async multiGet(keys: string[]): Promise<[string, string | null][]> {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
return [key, row?.value ?? null];
|
|
236
|
-
})
|
|
237
|
-
);
|
|
238
|
-
});
|
|
239
|
-
return result;
|
|
254
|
+
return Promise.all(
|
|
255
|
+
keys.map(async (key): Promise<[string, string | null]> => {
|
|
256
|
+
checkValidInput(key);
|
|
257
|
+
return [key, await this.getItemAsync(key)];
|
|
258
|
+
})
|
|
259
|
+
);
|
|
240
260
|
}
|
|
241
261
|
|
|
242
262
|
/**
|
|
@@ -246,6 +266,7 @@ export class SQLiteStorage {
|
|
|
246
266
|
const db = this.getDbSync();
|
|
247
267
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
248
268
|
for (const [key, value] of keyValuePairs) {
|
|
269
|
+
checkValidInput(key, value);
|
|
249
270
|
await tx.runAsync(STATEMENT_SET, key, value);
|
|
250
271
|
}
|
|
251
272
|
});
|
|
@@ -258,6 +279,7 @@ export class SQLiteStorage {
|
|
|
258
279
|
const db = this.getDbSync();
|
|
259
280
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
260
281
|
for (const key of keys) {
|
|
282
|
+
checkValidInput(key);
|
|
261
283
|
await tx.runAsync(STATEMENT_REMOVE, key);
|
|
262
284
|
}
|
|
263
285
|
});
|
|
@@ -271,6 +293,7 @@ export class SQLiteStorage {
|
|
|
271
293
|
const db = this.getDbSync();
|
|
272
294
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
273
295
|
for (const [key, value] of keyValuePairs) {
|
|
296
|
+
checkValidInput(key, value);
|
|
274
297
|
const prevValue = await tx.getFirstAsync<{ value: string }>(STATEMENT_GET, key);
|
|
275
298
|
if (prevValue == null) {
|
|
276
299
|
await tx.runAsync(STATEMENT_SET, key, value);
|