expo-sqlite 15.0.3 → 15.0.4

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 CHANGED
@@ -10,6 +10,18 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 15.0.4 — 2024-12-26
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - Fixed exceptions when converting empty blob data on iOS. ([#33564](https://github.com/expo/expo/pull/33564) by [@kudo](https://github.com/kudo))
18
+ - 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
+ - Fixed `database is locked` error from parallel `kv-store` operations. ([#33834](https://github.com/expo/expo/pull/33834) by [@kudo](https://github.com/kudo))
20
+
21
+ ### 💡 Others
22
+
23
+ - Removed unused `SQLite3Wrapper` code for legacy implementation on Android. ([#33565](https://github.com/expo/expo/pull/33565) by [@kudo](https://github.com/kudo))
24
+
13
25
  ## 15.0.3 — 2024-11-12
14
26
 
15
27
  ### 🐛 Bug fixes
@@ -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.3'
6
+ version = '15.0.4'
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.3"
56
+ versionName "15.0.4"
57
57
 
58
58
  externalNativeBuild {
59
59
  cmake {
@@ -4,12 +4,10 @@
4
4
 
5
5
  #include "NativeDatabaseBinding.h"
6
6
  #include "NativeStatementBinding.h"
7
- #include "SQLite3Wrapper.h"
8
7
 
9
8
  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
10
9
  return facebook::jni::initialize(vm, [] {
11
10
  expo::NativeDatabaseBinding::registerNatives();
12
11
  expo::NativeStatementBinding::registerNatives();
13
- expo::SQLite3Wrapper::registerNatives();
14
12
  });
15
13
  }
@@ -107,9 +107,7 @@ export declare class SQLiteStorage {
107
107
  * Alias for [`closeAsync()`](#closeasync-1) method.
108
108
  */
109
109
  close(): Promise<void>;
110
- private getDbAsync;
111
110
  private getDbSync;
112
- private maybeMigrateDbAsync;
113
111
  private maybeMigrateDbSync;
114
112
  /**
115
113
  * Recursively merge two JSON objects.
@@ -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;IAMvD;;;OAGG;IACG,YAAY,CAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,kCAAkC,GACjD,OAAO,CAAC,IAAI,CAAC;IAgBhB;;OAEG;IACG,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMpD;;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;IAMvC;;;OAGG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,kCAAkC,GAAG,IAAI;IAgBlF;;OAEG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAMpC;;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;IAY1D;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAclE;;OAEG;IACG,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAShE;;OAEG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD;;;OAGG;IACG,UAAU,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlE;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAQd,UAAU;IASxB,OAAO,CAAC,SAAS;YASH,mBAAmB;IAejC,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"}
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;IAMvD;;;OAGG;IACG,YAAY,CAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,kCAAkC,GACjD,OAAO,CAAC,IAAI,CAAC;IAgBhB;;OAEG;IACG,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMpD;;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;IAMvC;;;OAGG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,kCAAkC,GAAG,IAAI;IAgBlF;;OAEG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAMpC;;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;IAY1D;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAclE;;OAEG;IACG,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAShE;;OAEG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD;;;OAGG;IACG,UAAU,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlE;;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,4 @@
1
- import { openDatabaseAsync, openDatabaseSync } from './index';
1
+ import { openDatabaseSync } from './index';
2
2
  const DATABASE_VERSION = 1;
3
3
  const STATEMENT_GET = 'SELECT value FROM storage WHERE key = ?;';
4
4
  const STATEMENT_SET = 'INSERT INTO storage (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value;';
@@ -20,7 +20,7 @@ export class SQLiteStorage {
20
20
  * Retrieves the value associated with the given key asynchronously.
21
21
  */
22
22
  async getItemAsync(key) {
23
- const db = await this.getDbAsync();
23
+ const db = this.getDbSync();
24
24
  const result = await db.getFirstAsync(STATEMENT_GET, key);
25
25
  return result?.value ?? null;
26
26
  }
@@ -29,7 +29,7 @@ export class SQLiteStorage {
29
29
  * If a function is provided, it computes the new value based on the previous value.
30
30
  */
31
31
  async setItemAsync(key, value) {
32
- const db = await this.getDbAsync();
32
+ const db = this.getDbSync();
33
33
  if (typeof value === 'function') {
34
34
  await db.withExclusiveTransactionAsync(async (tx) => {
35
35
  const prevResult = await tx.getFirstAsync(STATEMENT_GET, key);
@@ -45,7 +45,7 @@ export class SQLiteStorage {
45
45
  * Removes the value associated with the given key asynchronously.
46
46
  */
47
47
  async removeItemAsync(key) {
48
- const db = await this.getDbAsync();
48
+ const db = this.getDbSync();
49
49
  const result = await db.runAsync(STATEMENT_REMOVE, key);
50
50
  return result.changes > 0;
51
51
  }
@@ -53,7 +53,7 @@ export class SQLiteStorage {
53
53
  * Retrieves all keys stored in the storage asynchronously.
54
54
  */
55
55
  async getAllKeysAsync() {
56
- const db = await this.getDbAsync();
56
+ const db = this.getDbSync();
57
57
  const result = await db.getAllAsync(STATEMENT_GET_ALL_KEYS);
58
58
  return result.map(({ key }) => key);
59
59
  }
@@ -61,7 +61,7 @@ export class SQLiteStorage {
61
61
  * Clears all key-value pairs from the storage asynchronously.
62
62
  */
63
63
  async clearAsync() {
64
- const db = await this.getDbAsync();
64
+ const db = this.getDbSync();
65
65
  const result = await db.runAsync(STATEMENT_CLEAR);
66
66
  return result.changes > 0;
67
67
  }
@@ -146,13 +146,13 @@ export class SQLiteStorage {
146
146
  * Alias for [`setItemAsync()`](#setitemasynckey-value).
147
147
  */
148
148
  async setItem(key, value) {
149
- this.setItemAsync(key, value);
149
+ await this.setItemAsync(key, value);
150
150
  }
151
151
  /**
152
152
  * Alias for [`removeItemAsync()`](#removeitemasynckey) method.
153
153
  */
154
154
  async removeItem(key) {
155
- this.removeItemAsync(key);
155
+ await this.removeItemAsync(key);
156
156
  }
157
157
  /**
158
158
  * Alias for [`getAllKeysAsync()`](#getallkeysasync) method.
@@ -164,7 +164,7 @@ export class SQLiteStorage {
164
164
  * Alias for [`clearAsync()`](#clearasync) method.
165
165
  */
166
166
  async clear() {
167
- this.clearAsync();
167
+ await this.clearAsync();
168
168
  }
169
169
  /**
170
170
  * Merges the given value with the existing value for the given key asynchronously.
@@ -185,7 +185,7 @@ export class SQLiteStorage {
185
185
  * Retrieves the values associated with the given keys asynchronously.
186
186
  */
187
187
  async multiGet(keys) {
188
- const db = await this.getDbAsync();
188
+ const db = this.getDbSync();
189
189
  let result = [];
190
190
  await db.withExclusiveTransactionAsync(async (tx) => {
191
191
  result = await Promise.all(keys.map(async (key) => {
@@ -199,7 +199,7 @@ export class SQLiteStorage {
199
199
  * Sets multiple key-value pairs asynchronously.
200
200
  */
201
201
  async multiSet(keyValuePairs) {
202
- const db = await this.getDbAsync();
202
+ const db = this.getDbSync();
203
203
  await db.withExclusiveTransactionAsync(async (tx) => {
204
204
  for (const [key, value] of keyValuePairs) {
205
205
  await tx.runAsync(STATEMENT_SET, key, value);
@@ -210,7 +210,7 @@ export class SQLiteStorage {
210
210
  * Removes the values associated with the given keys asynchronously.
211
211
  */
212
212
  async multiRemove(keys) {
213
- const db = await this.getDbAsync();
213
+ const db = this.getDbSync();
214
214
  await db.withExclusiveTransactionAsync(async (tx) => {
215
215
  for (const key of keys) {
216
216
  await tx.runAsync(STATEMENT_REMOVE, key);
@@ -222,7 +222,7 @@ export class SQLiteStorage {
222
222
  * If existing values are JSON objects, performs a deep merge.
223
223
  */
224
224
  async multiMerge(keyValuePairs) {
225
- const db = await this.getDbAsync();
225
+ const db = this.getDbSync();
226
226
  await db.withExclusiveTransactionAsync(async (tx) => {
227
227
  for (const [key, value] of keyValuePairs) {
228
228
  const prevValue = await tx.getFirstAsync(STATEMENT_GET, key);
@@ -241,18 +241,10 @@ export class SQLiteStorage {
241
241
  * Alias for [`closeAsync()`](#closeasync-1) method.
242
242
  */
243
243
  async close() {
244
- this.closeAsync();
244
+ await this.closeAsync();
245
245
  }
246
246
  //#endregion
247
247
  //#region Internals
248
- async getDbAsync() {
249
- if (!this.db) {
250
- const db = await openDatabaseAsync(this.databaseName);
251
- await this.maybeMigrateDbAsync(db);
252
- this.db = db;
253
- }
254
- return this.db;
255
- }
256
248
  getDbSync() {
257
249
  if (!this.db) {
258
250
  const db = openDatabaseSync(this.databaseName);
@@ -261,20 +253,6 @@ export class SQLiteStorage {
261
253
  }
262
254
  return this.db;
263
255
  }
264
- async maybeMigrateDbAsync(db) {
265
- await db.withExclusiveTransactionAsync(async (tx) => {
266
- const result = await tx.getFirstAsync('PRAGMA user_version');
267
- let currentDbVersion = result?.user_version ?? 0;
268
- if (currentDbVersion >= DATABASE_VERSION) {
269
- return;
270
- }
271
- if (currentDbVersion === 0) {
272
- await tx.execAsync(MIGRATION_STATEMENT_0);
273
- currentDbVersion = 1;
274
- }
275
- await tx.execAsync(`PRAGMA user_version = ${DATABASE_VERSION}`);
276
- });
277
- }
278
256
  maybeMigrateDbSync(db) {
279
257
  db.withTransactionSync(() => {
280
258
  const result = db.getFirstSync('PRAGMA user_version');
@@ -1 +1 @@
1
- {"version":3,"file":"Storage.js","sourceRoot":"","sources":["../src/Storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { openDatabaseAsync, 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 = await this.getDbAsync();\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 = await this.getDbAsync();\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 = await this.getDbAsync();\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 = await this.getDbAsync();\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 = await this.getDbAsync();\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 this.setItemAsync(key, value);\n }\n\n /**\n * Alias for [`removeItemAsync()`](#removeitemasynckey) method.\n */\n async removeItem(key: string): Promise<void> {\n 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 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 = await this.getDbAsync();\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 = await this.getDbAsync();\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 = await this.getDbAsync();\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 = await this.getDbAsync();\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 this.closeAsync();\n }\n\n //#endregion\n\n //#region Internals\n\n private async getDbAsync(): Promise<SQLiteDatabase> {\n if (!this.db) {\n const db = await openDatabaseAsync(this.databaseName);\n await this.maybeMigrateDbAsync(db);\n this.db = db;\n }\n return this.db;\n }\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 async maybeMigrateDbAsync(db: SQLiteDatabase) {\n await db.withExclusiveTransactionAsync(async (tx) => {\n const result = await tx.getFirstAsync<{ 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 await tx.execAsync(MIGRATION_STATEMENT_0);\n currentDbVersion = 1;\n }\n await tx.execAsync(`PRAGMA user_version = ${DATABASE_VERSION}`);\n });\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\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"]}
@@ -493,7 +493,7 @@ public final class SQLiteModule: Module {
493
493
  return String(cString: text)
494
494
  case SQLITE_BLOB:
495
495
  guard let blob = exsqlite3_column_blob(instance, index) else {
496
- throw InvalidConvertibleException("Null blob")
496
+ return Data()
497
497
  }
498
498
  let size = exsqlite3_column_bytes(instance, index)
499
499
  return Data(bytes: blob, count: Int(size))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-sqlite",
3
- "version": "15.0.3",
3
+ "version": "15.0.4",
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": "68c2c4f5a536c4eb7db9551188c7f667d9fa53c8"
64
+ "gitHead": "64d037d767a487f402ffd0d7d919aa7e848815ac"
65
65
  }
package/src/Storage.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { openDatabaseAsync, openDatabaseSync, type SQLiteDatabase } from './index';
1
+ import { openDatabaseSync, type SQLiteDatabase } from './index';
2
2
 
3
3
  /**
4
4
  * 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.
@@ -32,7 +32,7 @@ export class SQLiteStorage {
32
32
  * Retrieves the value associated with the given key asynchronously.
33
33
  */
34
34
  async getItemAsync(key: string): Promise<string | null> {
35
- const db = await this.getDbAsync();
35
+ const db = this.getDbSync();
36
36
  const result = await db.getFirstAsync<{ value: string }>(STATEMENT_GET, key);
37
37
  return result?.value ?? null;
38
38
  }
@@ -45,7 +45,7 @@ export class SQLiteStorage {
45
45
  key: string,
46
46
  value: string | SQLiteStorageSetItemUpdateFunction
47
47
  ): Promise<void> {
48
- const db = await this.getDbAsync();
48
+ const db = this.getDbSync();
49
49
 
50
50
  if (typeof value === 'function') {
51
51
  await db.withExclusiveTransactionAsync(async (tx) => {
@@ -64,7 +64,7 @@ export class SQLiteStorage {
64
64
  * Removes the value associated with the given key asynchronously.
65
65
  */
66
66
  async removeItemAsync(key: string): Promise<boolean> {
67
- const db = await this.getDbAsync();
67
+ const db = this.getDbSync();
68
68
  const result = await db.runAsync(STATEMENT_REMOVE, key);
69
69
  return result.changes > 0;
70
70
  }
@@ -73,7 +73,7 @@ export class SQLiteStorage {
73
73
  * Retrieves all keys stored in the storage asynchronously.
74
74
  */
75
75
  async getAllKeysAsync(): Promise<string[]> {
76
- const db = await this.getDbAsync();
76
+ const db = this.getDbSync();
77
77
  const result = await db.getAllAsync<{ key: string }>(STATEMENT_GET_ALL_KEYS);
78
78
  return result.map(({ key }) => key);
79
79
  }
@@ -82,7 +82,7 @@ export class SQLiteStorage {
82
82
  * Clears all key-value pairs from the storage asynchronously.
83
83
  */
84
84
  async clearAsync(): Promise<boolean> {
85
- const db = await this.getDbAsync();
85
+ const db = this.getDbSync();
86
86
  const result = await db.runAsync(STATEMENT_CLEAR);
87
87
  return result.changes > 0;
88
88
  }
@@ -182,14 +182,14 @@ export class SQLiteStorage {
182
182
  * Alias for [`setItemAsync()`](#setitemasynckey-value).
183
183
  */
184
184
  async setItem(key: string, value: string | SQLiteStorageSetItemUpdateFunction): Promise<void> {
185
- this.setItemAsync(key, value);
185
+ await this.setItemAsync(key, value);
186
186
  }
187
187
 
188
188
  /**
189
189
  * Alias for [`removeItemAsync()`](#removeitemasynckey) method.
190
190
  */
191
191
  async removeItem(key: string): Promise<void> {
192
- this.removeItemAsync(key);
192
+ await this.removeItemAsync(key);
193
193
  }
194
194
 
195
195
  /**
@@ -203,7 +203,7 @@ export class SQLiteStorage {
203
203
  * Alias for [`clearAsync()`](#clearasync) method.
204
204
  */
205
205
  async clear(): Promise<void> {
206
- this.clearAsync();
206
+ await this.clearAsync();
207
207
  }
208
208
 
209
209
  /**
@@ -226,7 +226,7 @@ export class SQLiteStorage {
226
226
  * Retrieves the values associated with the given keys asynchronously.
227
227
  */
228
228
  async multiGet(keys: string[]): Promise<[string, string | null][]> {
229
- const db = await this.getDbAsync();
229
+ const db = this.getDbSync();
230
230
  let result: [string, string | null][] = [];
231
231
  await db.withExclusiveTransactionAsync(async (tx) => {
232
232
  result = await Promise.all(
@@ -243,7 +243,7 @@ export class SQLiteStorage {
243
243
  * Sets multiple key-value pairs asynchronously.
244
244
  */
245
245
  async multiSet(keyValuePairs: [string, string][]): Promise<void> {
246
- const db = await this.getDbAsync();
246
+ const db = this.getDbSync();
247
247
  await db.withExclusiveTransactionAsync(async (tx) => {
248
248
  for (const [key, value] of keyValuePairs) {
249
249
  await tx.runAsync(STATEMENT_SET, key, value);
@@ -255,7 +255,7 @@ export class SQLiteStorage {
255
255
  * Removes the values associated with the given keys asynchronously.
256
256
  */
257
257
  async multiRemove(keys: string[]): Promise<void> {
258
- const db = await this.getDbAsync();
258
+ const db = this.getDbSync();
259
259
  await db.withExclusiveTransactionAsync(async (tx) => {
260
260
  for (const key of keys) {
261
261
  await tx.runAsync(STATEMENT_REMOVE, key);
@@ -268,7 +268,7 @@ export class SQLiteStorage {
268
268
  * If existing values are JSON objects, performs a deep merge.
269
269
  */
270
270
  async multiMerge(keyValuePairs: [string, string][]): Promise<void> {
271
- const db = await this.getDbAsync();
271
+ const db = this.getDbSync();
272
272
  await db.withExclusiveTransactionAsync(async (tx) => {
273
273
  for (const [key, value] of keyValuePairs) {
274
274
  const prevValue = await tx.getFirstAsync<{ value: string }>(STATEMENT_GET, key);
@@ -288,22 +288,13 @@ export class SQLiteStorage {
288
288
  * Alias for [`closeAsync()`](#closeasync-1) method.
289
289
  */
290
290
  async close(): Promise<void> {
291
- this.closeAsync();
291
+ await this.closeAsync();
292
292
  }
293
293
 
294
294
  //#endregion
295
295
 
296
296
  //#region Internals
297
297
 
298
- private async getDbAsync(): Promise<SQLiteDatabase> {
299
- if (!this.db) {
300
- const db = await openDatabaseAsync(this.databaseName);
301
- await this.maybeMigrateDbAsync(db);
302
- this.db = db;
303
- }
304
- return this.db;
305
- }
306
-
307
298
  private getDbSync(): SQLiteDatabase {
308
299
  if (!this.db) {
309
300
  const db = openDatabaseSync(this.databaseName);
@@ -313,21 +304,6 @@ export class SQLiteStorage {
313
304
  return this.db;
314
305
  }
315
306
 
316
- private async maybeMigrateDbAsync(db: SQLiteDatabase) {
317
- await db.withExclusiveTransactionAsync(async (tx) => {
318
- const result = await tx.getFirstAsync<{ user_version: number }>('PRAGMA user_version');
319
- let currentDbVersion = result?.user_version ?? 0;
320
- if (currentDbVersion >= DATABASE_VERSION) {
321
- return;
322
- }
323
- if (currentDbVersion === 0) {
324
- await tx.execAsync(MIGRATION_STATEMENT_0);
325
- currentDbVersion = 1;
326
- }
327
- await tx.execAsync(`PRAGMA user_version = ${DATABASE_VERSION}`);
328
- });
329
- }
330
-
331
307
  private maybeMigrateDbSync(db: SQLiteDatabase) {
332
308
  db.withTransactionSync(() => {
333
309
  const result = db.getFirstSync<{ user_version: number }>('PRAGMA user_version');
@@ -1,223 +0,0 @@
1
- // Copyright 2015-present 650 Industries. All rights reserved.
2
-
3
- #include "SQLite3Wrapper.h"
4
-
5
- #include <android/log.h>
6
-
7
- namespace jni = facebook::jni;
8
-
9
- namespace expo {
10
-
11
- namespace {
12
-
13
- constexpr char TAG[] = "expo-sqlite";
14
-
15
- } // namespace
16
-
17
- // static
18
- void SQLite3Wrapper::registerNatives() {
19
- registerHybrid({
20
- makeNativeMethod("initHybrid", SQLite3Wrapper::initHybrid),
21
- makeNativeMethod("executeSql", SQLite3Wrapper::executeSql),
22
- makeNativeMethod("sqlite3_open", SQLite3Wrapper::sqlite3_open),
23
- makeNativeMethod("sqlite3_close", SQLite3Wrapper::sqlite3_close),
24
- });
25
- }
26
-
27
- jni::local_ref<jni::JList<jni::JObject>>
28
- SQLite3Wrapper::executeSql(const std::string &sql,
29
- jni::alias_ref<jni::JList<jni::JObject>> args,
30
- bool readOnly) {
31
- auto resultRows = jni::JArrayList<jni::JObject>::create();
32
- exsqlite3_stmt *statement = nullptr;
33
- int rowsAffected = 0;
34
- sqlite3_int64 insertId = 0;
35
- jni::local_ref<jni::JString> error;
36
-
37
- if (exsqlite3_prepare_v2(db, sql.c_str(), -1, &statement, nullptr) !=
38
- SQLITE_OK) {
39
- auto results = jni::JArrayList<jni::JObject>::create();
40
- results->add(convertSqlLiteErrorToString(db));
41
- return results;
42
- }
43
-
44
- bool queryIsReadOnly = exsqlite3_stmt_readonly(statement) > 0;
45
- if (readOnly && !queryIsReadOnly) {
46
- auto results = jni::JArrayList<jni::JObject>::create();
47
- std::string error("could not prepare ");
48
- error += sql;
49
- results->add(jni::make_jstring(error));
50
- return results;
51
- }
52
-
53
- int index = 1;
54
- for (const auto &arg : *args) {
55
- bindStatement(statement, arg, index++);
56
- }
57
-
58
- int columnCount = 0;
59
- auto columnNames = jni::JArrayList<jni::JString>::create();
60
- int columnType;
61
- bool fetchedColumns = false;
62
- jni::local_ref<jni::JObject> value;
63
- bool hasMore = true;
64
-
65
- while (hasMore) {
66
- switch (exsqlite3_step(statement)) {
67
- case SQLITE_ROW: {
68
- if (!fetchedColumns) {
69
- columnCount = exsqlite3_column_count(statement);
70
-
71
- for (int i = 0; i < columnCount; ++i) {
72
- const char *columnName = exsqlite3_column_name(statement, i);
73
- columnNames->add(jni::make_jstring(columnName));
74
- }
75
- fetchedColumns = true;
76
- }
77
-
78
- auto entry = jni::JArrayList<jni::JObject>::create();
79
-
80
- for (int i = 0; i < columnCount; ++i) {
81
- columnType = exsqlite3_column_type(statement, i);
82
- value = getSqlValue(columnType, statement, i);
83
- entry->add(value);
84
- }
85
- resultRows->add(entry);
86
- break;
87
- }
88
- case SQLITE_DONE: {
89
- hasMore = false;
90
- break;
91
- }
92
- default: {
93
- error = convertSqlLiteErrorToString(db);
94
- break;
95
- }
96
- }
97
- }
98
-
99
- if (!queryIsReadOnly) {
100
- rowsAffected = exsqlite3_changes(db);
101
- if (rowsAffected > 0) {
102
- insertId = exsqlite3_last_insert_rowid(db);
103
- }
104
- }
105
-
106
- exsqlite3_finalize(statement);
107
-
108
- if (error) {
109
- auto results = jni::JArrayList<jni::JObject>::create();
110
- results->add(error);
111
- return results;
112
- }
113
-
114
- auto results = jni::JArrayList<jni::JObject>::create();
115
- results->add(nullptr);
116
- results->add(jni::JLong::valueOf(insertId));
117
- results->add(jni::JInteger::valueOf(rowsAffected));
118
- results->add(columnNames);
119
- results->add(resultRows);
120
- return results;
121
- }
122
-
123
- int SQLite3Wrapper::sqlite3_open(const std::string &dbPath) {
124
- return ::exsqlite3_open(dbPath.c_str(), &db);
125
- }
126
-
127
- int SQLite3Wrapper::sqlite3_close() {
128
- int ret = ::exsqlite3_close(db);
129
- db = nullptr;
130
- return ret;
131
- }
132
-
133
- // static
134
- jni::local_ref<SQLite3Wrapper::jhybriddata>
135
- SQLite3Wrapper::initHybrid(jni::alias_ref<jhybridobject> jThis) {
136
- return makeCxxInstance(jThis);
137
- }
138
-
139
- // static
140
- jni::local_ref<jni::JString>
141
- SQLite3Wrapper::convertSqlLiteErrorToString(sqlite3 *db) {
142
- int code = exsqlite3_errcode(db);
143
- const char *message = exsqlite3_errmsg(db);
144
- std::string result("Error code ");
145
- result += code;
146
- result += ": ";
147
- result += message;
148
- return jni::make_jstring(result);
149
- }
150
-
151
- // static
152
- void SQLite3Wrapper::bindStatement(exsqlite3_stmt *statement,
153
- jni::alias_ref<jni::JObject> arg,
154
- int index) {
155
- static const auto integerClass = jni::JInteger::javaClassStatic();
156
- static const auto longClass = jni::JLong::javaClassStatic();
157
- static const auto doubleClass = jni::JDouble::javaClassStatic();
158
- static const auto stringClass = jni::JString::javaClassStatic();
159
-
160
- if (arg == nullptr) {
161
- exsqlite3_bind_null(statement, index);
162
- } else if (arg->isInstanceOf(integerClass)) {
163
- exsqlite3_bind_int(statement, index,
164
- jni::static_ref_cast<jni::JInteger>(arg)->value());
165
- } else if (arg->isInstanceOf(longClass)) {
166
- exsqlite3_bind_int64(statement, index,
167
- jni::static_ref_cast<jni::JLong>(arg)->value());
168
- } else if (arg->isInstanceOf(doubleClass)) {
169
- exsqlite3_bind_double(statement, index,
170
- jni::static_ref_cast<jni::JDouble>(arg)->value());
171
- } else {
172
- std::string stringArg;
173
- if (arg->isInstanceOf(stringClass)) {
174
- stringArg = jni::static_ref_cast<jni::JString>(arg)->toStdString();
175
- } else {
176
- stringArg = arg->toString();
177
- }
178
- exsqlite3_bind_text(statement, index, stringArg.c_str(), stringArg.length(),
179
- SQLITE_TRANSIENT);
180
- }
181
- }
182
-
183
- // static
184
- jni::local_ref<jni::JObject>
185
- SQLite3Wrapper::getSqlValue(int columnType, exsqlite3_stmt *statement,
186
- int index) {
187
- switch (columnType) {
188
- case SQLITE_INTEGER: {
189
- return jni::JLong::valueOf(exsqlite3_column_int64(statement, index));
190
- }
191
- case SQLITE_FLOAT: {
192
- return jni::JDouble::valueOf(exsqlite3_column_double(statement, index));
193
- }
194
- case SQLITE_BLOB: {
195
- JNIEnv *env = jni::Environment::current();
196
- return jni::adopt_local(env->NewString(
197
- reinterpret_cast<const jchar *>(exsqlite3_column_blob(statement, index)),
198
- static_cast<size_t>(exsqlite3_column_bytes(statement, index))));
199
- }
200
- case SQLITE_TEXT: {
201
- std::string text(
202
- reinterpret_cast<const char *>(exsqlite3_column_text(statement, index)),
203
- static_cast<size_t>(exsqlite3_column_bytes(statement, index)));
204
- return jni::make_jstring(text);
205
- }
206
- default: {
207
- return nullptr;
208
- }
209
- }
210
- }
211
-
212
- // static
213
- void SQLite3Wrapper::OnUpdateHook(void *arg, int action, char const *dbName,
214
- char const *tableName, sqlite3_int64 rowId) {
215
- SQLite3Wrapper *pThis = reinterpret_cast<SQLite3Wrapper *>(arg);
216
- static const auto method =
217
- jni::findClassStatic("expo/modules/sqlite/SQLite3Wrapper")
218
- ->getMethod<void(jint, jstring, jstring, jlong)>("onUpdate");
219
- method(pThis->javaPart_, action, jni::make_jstring(dbName).get(),
220
- jni::make_jstring(tableName).get(), rowId);
221
- }
222
-
223
- } // namespace expo
@@ -1,55 +0,0 @@
1
- // Copyright 2015-present 650 Industries. All rights reserved.
2
-
3
- #pragma once
4
-
5
- #include <fbjni/fbjni.h>
6
- #include <string>
7
-
8
- #include "sqlite3.h"
9
-
10
- namespace jni = facebook::jni;
11
-
12
- namespace expo {
13
-
14
- class SQLite3Wrapper : public jni::HybridClass<SQLite3Wrapper> {
15
- public:
16
- static constexpr auto kJavaDescriptor =
17
- "Lexpo/modules/sqlite/SQLite3Wrapper;";
18
-
19
- static void registerNatives();
20
-
21
- jni::local_ref<jni::JList<jni::JObject>>
22
- executeSql(const std::string &sql,
23
- jni::alias_ref<jni::JList<jni::JObject>> args, bool readOnly);
24
-
25
- // sqlite3 bindings
26
- int sqlite3_open(const std::string &dbPath);
27
- int sqlite3_close();
28
-
29
- private:
30
- explicit SQLite3Wrapper(jni::alias_ref<SQLite3Wrapper::jhybridobject> jThis)
31
- : javaPart_(jni::make_global(jThis)) {}
32
-
33
- private:
34
- static jni::local_ref<jhybriddata>
35
- initHybrid(jni::alias_ref<jhybridobject> jThis);
36
-
37
- static jni::local_ref<jni::JString> convertSqlLiteErrorToString(sqlite3 *db);
38
-
39
- static void bindStatement(exsqlite3_stmt *statement,
40
- jni::alias_ref<jni::JObject> arg, int index);
41
-
42
- static jni::local_ref<jni::JObject>
43
- getSqlValue(int columnType, exsqlite3_stmt *statement, int index);
44
-
45
- static void OnUpdateHook(void *arg, int action, char const *dbName,
46
- char const *tableName, sqlite3_int64 rowId);
47
-
48
- private:
49
- friend HybridBase;
50
-
51
- jni::global_ref<SQLite3Wrapper::javaobject> javaPart_;
52
- sqlite3 *db;
53
- };
54
-
55
- } // namespace expo
@@ -1,51 +0,0 @@
1
- package expo.modules.sqlite
2
-
3
- import com.facebook.jni.HybridData
4
- import expo.modules.core.interfaces.DoNotStrip
5
-
6
- @Suppress("KotlinJniMissingFunction")
7
- @DoNotStrip
8
- class SQLite3Wrapper private constructor() {
9
- @DoNotStrip
10
- private val mHybridData: HybridData
11
-
12
- init {
13
- mHybridData = initHybrid()
14
- }
15
-
16
- /**
17
- * Execute SQL commands
18
- */
19
- external fun executeSql(sql: String, args: List<Any?>, readOnly: Boolean): List<Any>
20
-
21
- // region sqlite3 bindings
22
-
23
- external fun sqlite3_open(dbPath: String): Int
24
- external fun sqlite3_close(): Int
25
-
26
- // endregion
27
-
28
- // region internals
29
-
30
- private external fun initHybrid(): HybridData
31
-
32
- // endregion
33
-
34
- companion object {
35
- init {
36
- System.loadLibrary("expo-sqlite")
37
- }
38
-
39
- @JvmStatic
40
- fun open(dbPath: String): SQLite3Wrapper? {
41
- val instance = SQLite3Wrapper()
42
- if (instance.sqlite3_open(dbPath) != SQLITE_OK) {
43
- return null
44
- }
45
- return instance
46
- }
47
-
48
- // These error code should be synced with sqlite3.h
49
- const val SQLITE_OK = 0
50
- }
51
- }