expo-sqlite 15.2.8 → 15.2.10
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 +15 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/sqlite/SQLiteModule.kt +39 -34
- package/build/Storage.d.ts +4 -4
- package/build/Storage.d.ts.map +1 -1
- package/build/Storage.js +70 -37
- package/build/Storage.js.map +1 -1
- package/expo-module.config.json +1 -7
- package/ios/NativeStatement.swift +1 -0
- package/ios/SQLiteModule.swift +7 -0
- package/package.json +6 -4
- package/src/Storage.ts +77 -43
- package/web/WorkerChannel.ts +16 -6
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8-sources.jar +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8-sources.jar.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8-sources.jar.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8-sources.jar.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8-sources.jar.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.aar +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.aar.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.aar.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.aar.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.aar.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.module +0 -87
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.module.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.module.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.module.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.module.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.pom +0 -35
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.pom.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.pom.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.pom.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.pom.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/maven-metadata.xml +0 -13
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/maven-metadata.xml.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/maven-metadata.xml.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/maven-metadata.xml.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/maven-metadata.xml.sha512 +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,21 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 15.2.10 — 2025-05-08
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- Fixed parallel issue for `Statement.executeAsync`. ([#36674](https://github.com/expo/expo/pull/36674) by [@kudo](https://github.com/kudo))
|
|
18
|
+
|
|
19
|
+
### 💡 Others
|
|
20
|
+
|
|
21
|
+
- Avoided synchronous API calls for `kv-store`. ([#36669](https://github.com/expo/expo/pull/36669) by [@kudo](https://github.com/kudo))
|
|
22
|
+
- Improved synchronous APIs on web. ([#36670](https://github.com/expo/expo/pull/36670) by [@kudo](https://github.com/kudo))
|
|
23
|
+
|
|
24
|
+
## 15.2.9 — 2025-04-30
|
|
25
|
+
|
|
26
|
+
_This version does not introduce any user-facing changes._
|
|
27
|
+
|
|
13
28
|
## 15.2.8 — 2025-04-30
|
|
14
29
|
|
|
15
30
|
### 📚 3rd party library updates
|
package/android/build.gradle
CHANGED
|
@@ -45,13 +45,13 @@ def reactNativeArchitectures() {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
group = 'host.exp.exponent'
|
|
48
|
-
version = '15.2.
|
|
48
|
+
version = '15.2.10'
|
|
49
49
|
|
|
50
50
|
android {
|
|
51
51
|
namespace "expo.modules.sqlite"
|
|
52
52
|
defaultConfig {
|
|
53
53
|
versionCode 18
|
|
54
|
-
versionName "15.2.
|
|
54
|
+
versionName "15.2.10"
|
|
55
55
|
buildConfigField "boolean", "USE_LIBSQL", project.ext.USE_LIBSQL.toString()
|
|
56
56
|
|
|
57
57
|
externalNativeBuild {
|
|
@@ -367,44 +367,49 @@ class SQLiteModule : Module() {
|
|
|
367
367
|
private fun run(statement: NativeStatement, database: NativeDatabase, bindParams: Map<String, Any>, bindBlobParams: Map<String, ByteArray>, shouldPassAsArray: Boolean): Map<String, Any> {
|
|
368
368
|
maybeThrowForClosedDatabase(database)
|
|
369
369
|
maybeThrowForFinalizedStatement(statement)
|
|
370
|
-
|
|
371
|
-
statement
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
val
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
370
|
+
|
|
371
|
+
// The statement with parameter bindings is stateful,
|
|
372
|
+
// we have to guard with a critical section for thread safety.
|
|
373
|
+
synchronized(statement) {
|
|
374
|
+
statement.ref.sqlite3_reset()
|
|
375
|
+
statement.ref.sqlite3_clear_bindings()
|
|
376
|
+
for ((key, param) in bindParams) {
|
|
377
|
+
val index = getBindParamIndex(statement, key, shouldPassAsArray)
|
|
378
|
+
if (index > 0) {
|
|
379
|
+
// expo-modules-core AnyTypeConverter casts JavaScript Number to Kotlin Double,
|
|
380
|
+
// here to cast as Long if the value is an integer.
|
|
381
|
+
val normalizedParam =
|
|
382
|
+
if (param is Double && param.toDouble() % 1.0 == 0.0) {
|
|
383
|
+
param.toLong()
|
|
384
|
+
} else {
|
|
385
|
+
param
|
|
386
|
+
}
|
|
387
|
+
statement.ref.bindStatementParam(index, normalizedParam)
|
|
388
|
+
}
|
|
384
389
|
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
+
for ((key, param) in bindBlobParams) {
|
|
391
|
+
val index = getBindParamIndex(statement, key, shouldPassAsArray)
|
|
392
|
+
if (index > 0) {
|
|
393
|
+
statement.ref.bindStatementParam(index, param)
|
|
394
|
+
}
|
|
390
395
|
}
|
|
391
|
-
}
|
|
392
396
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
}
|
|
397
|
-
val firstRowValues: SQLiteColumnValues =
|
|
398
|
-
if (ret == NativeDatabaseBinding.SQLITE_ROW) {
|
|
399
|
-
statement.ref.getColumnValues()
|
|
400
|
-
} else {
|
|
401
|
-
arrayListOf()
|
|
397
|
+
val ret = statement.ref.sqlite3_step()
|
|
398
|
+
if (ret != NativeDatabaseBinding.SQLITE_ROW && ret != NativeDatabaseBinding.SQLITE_DONE) {
|
|
399
|
+
throw SQLiteErrorException(database.ref.convertSqlLiteErrorToString())
|
|
402
400
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
401
|
+
val firstRowValues: SQLiteColumnValues =
|
|
402
|
+
if (ret == NativeDatabaseBinding.SQLITE_ROW) {
|
|
403
|
+
statement.ref.getColumnValues()
|
|
404
|
+
} else {
|
|
405
|
+
arrayListOf()
|
|
406
|
+
}
|
|
407
|
+
return mapOf(
|
|
408
|
+
"lastInsertRowId" to database.ref.sqlite3_last_insert_rowid().toInt(),
|
|
409
|
+
"changes" to database.ref.sqlite3_changes(),
|
|
410
|
+
"firstRowValues" to firstRowValues
|
|
411
|
+
)
|
|
412
|
+
}
|
|
408
413
|
}
|
|
409
414
|
|
|
410
415
|
@Throws(AccessClosedResourceException::class, InvalidConvertibleException::class, SQLiteErrorException::class)
|
package/build/Storage.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @hidden
|
|
3
|
-
*/
|
|
4
|
-
export declare function checkValidInput(...input: unknown[]): void;
|
|
5
1
|
/**
|
|
6
2
|
* 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.
|
|
7
3
|
* @param prevValue The previous value associated with the key, or `null` if the key was not set.
|
|
@@ -14,6 +10,7 @@ export type SQLiteStorageSetItemUpdateFunction = (prevValue: string | null) => s
|
|
|
14
10
|
export declare class SQLiteStorage {
|
|
15
11
|
private readonly databaseName;
|
|
16
12
|
private db;
|
|
13
|
+
private readonly awaitLock;
|
|
17
14
|
constructor(databaseName: string);
|
|
18
15
|
/**
|
|
19
16
|
* Retrieves the value associated with the given key asynchronously.
|
|
@@ -111,12 +108,15 @@ export declare class SQLiteStorage {
|
|
|
111
108
|
* Alias for [`closeAsync()`](#closeasync-1) method.
|
|
112
109
|
*/
|
|
113
110
|
close(): Promise<void>;
|
|
111
|
+
private getDbAsync;
|
|
114
112
|
private getDbSync;
|
|
113
|
+
private maybeMigrateDbAsync;
|
|
115
114
|
private maybeMigrateDbSync;
|
|
116
115
|
/**
|
|
117
116
|
* Recursively merge two JSON objects.
|
|
118
117
|
*/
|
|
119
118
|
private static mergeDeep;
|
|
119
|
+
private checkValidInput;
|
|
120
120
|
}
|
|
121
121
|
/**
|
|
122
122
|
* 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).
|
package/build/Storage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Storage.d.ts","sourceRoot":"","sources":["../src/Storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Storage.d.ts","sourceRoot":"","sources":["../src/Storage.ts"],"names":[],"mappings":"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"}
|
package/build/Storage.js
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
* @hidden
|
|
4
|
-
*/
|
|
5
|
-
export function checkValidInput(...input) {
|
|
6
|
-
const [key, value] = input;
|
|
7
|
-
if (typeof key !== 'string') {
|
|
8
|
-
throw new Error(`[SQLiteStorage] Using ${typeof key} type for key is not supported. Use string instead. Key passed: ${key}`);
|
|
9
|
-
}
|
|
10
|
-
if (input.length > 1 && typeof value !== 'string' && typeof value !== 'function') {
|
|
11
|
-
throw new Error(`[SQLiteStorage] Using ${typeof value} type for value is not supported. Use string instead. Key passed: ${key}. Value passed : ${value}`);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
1
|
+
import AwaitLock from 'await-lock';
|
|
2
|
+
import { openDatabaseAsync, openDatabaseSync } from './index';
|
|
14
3
|
const DATABASE_VERSION = 1;
|
|
15
4
|
const STATEMENT_GET = 'SELECT value FROM storage WHERE key = ?;';
|
|
16
5
|
const STATEMENT_SET = 'INSERT INTO storage (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value;';
|
|
@@ -24,6 +13,7 @@ const MIGRATION_STATEMENT_0 = 'CREATE TABLE IF NOT EXISTS storage (key TEXT PRIM
|
|
|
24
13
|
export class SQLiteStorage {
|
|
25
14
|
databaseName;
|
|
26
15
|
db = null;
|
|
16
|
+
awaitLock = new AwaitLock();
|
|
27
17
|
constructor(databaseName) {
|
|
28
18
|
this.databaseName = databaseName;
|
|
29
19
|
}
|
|
@@ -32,8 +22,8 @@ export class SQLiteStorage {
|
|
|
32
22
|
* Retrieves the value associated with the given key asynchronously.
|
|
33
23
|
*/
|
|
34
24
|
async getItemAsync(key) {
|
|
35
|
-
checkValidInput(key);
|
|
36
|
-
const db = this.
|
|
25
|
+
this.checkValidInput(key);
|
|
26
|
+
const db = await this.getDbAsync();
|
|
37
27
|
const result = await db.getFirstAsync(STATEMENT_GET, key);
|
|
38
28
|
return result?.value ?? null;
|
|
39
29
|
}
|
|
@@ -42,14 +32,14 @@ export class SQLiteStorage {
|
|
|
42
32
|
* If a function is provided, it computes the new value based on the previous value.
|
|
43
33
|
*/
|
|
44
34
|
async setItemAsync(key, value) {
|
|
45
|
-
checkValidInput(key, value);
|
|
46
|
-
const db = this.
|
|
35
|
+
this.checkValidInput(key, value);
|
|
36
|
+
const db = await this.getDbAsync();
|
|
47
37
|
if (typeof value === 'function') {
|
|
48
38
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
49
39
|
const prevResult = await tx.getFirstAsync(STATEMENT_GET, key);
|
|
50
40
|
const prevValue = prevResult?.value ?? null;
|
|
51
41
|
const nextValue = value(prevValue);
|
|
52
|
-
checkValidInput(key, nextValue);
|
|
42
|
+
this.checkValidInput(key, nextValue);
|
|
53
43
|
await tx.runAsync(STATEMENT_SET, key, nextValue);
|
|
54
44
|
});
|
|
55
45
|
return;
|
|
@@ -60,8 +50,8 @@ export class SQLiteStorage {
|
|
|
60
50
|
* Removes the value associated with the given key asynchronously.
|
|
61
51
|
*/
|
|
62
52
|
async removeItemAsync(key) {
|
|
63
|
-
checkValidInput(key);
|
|
64
|
-
const db = this.
|
|
53
|
+
this.checkValidInput(key);
|
|
54
|
+
const db = await this.getDbAsync();
|
|
65
55
|
const result = await db.runAsync(STATEMENT_REMOVE, key);
|
|
66
56
|
return result.changes > 0;
|
|
67
57
|
}
|
|
@@ -69,7 +59,7 @@ export class SQLiteStorage {
|
|
|
69
59
|
* Retrieves all keys stored in the storage asynchronously.
|
|
70
60
|
*/
|
|
71
61
|
async getAllKeysAsync() {
|
|
72
|
-
const db = this.
|
|
62
|
+
const db = await this.getDbAsync();
|
|
73
63
|
const result = await db.getAllAsync(STATEMENT_GET_ALL_KEYS);
|
|
74
64
|
return result.map(({ key }) => key);
|
|
75
65
|
}
|
|
@@ -77,7 +67,7 @@ export class SQLiteStorage {
|
|
|
77
67
|
* Clears all key-value pairs from the storage asynchronously.
|
|
78
68
|
*/
|
|
79
69
|
async clearAsync() {
|
|
80
|
-
const db = this.
|
|
70
|
+
const db = await this.getDbAsync();
|
|
81
71
|
const result = await db.runAsync(STATEMENT_CLEAR);
|
|
82
72
|
return result.changes > 0;
|
|
83
73
|
}
|
|
@@ -85,9 +75,15 @@ export class SQLiteStorage {
|
|
|
85
75
|
* Closes the database connection asynchronously.
|
|
86
76
|
*/
|
|
87
77
|
async closeAsync() {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
this.db
|
|
78
|
+
await this.awaitLock.acquireAsync();
|
|
79
|
+
try {
|
|
80
|
+
if (this.db) {
|
|
81
|
+
await this.db.closeAsync();
|
|
82
|
+
this.db = null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
this.awaitLock.release();
|
|
91
87
|
}
|
|
92
88
|
}
|
|
93
89
|
//#endregion
|
|
@@ -96,7 +92,7 @@ export class SQLiteStorage {
|
|
|
96
92
|
* Retrieves the value associated with the given key synchronously.
|
|
97
93
|
*/
|
|
98
94
|
getItemSync(key) {
|
|
99
|
-
checkValidInput(key);
|
|
95
|
+
this.checkValidInput(key);
|
|
100
96
|
const db = this.getDbSync();
|
|
101
97
|
const result = db.getFirstSync(STATEMENT_GET, key);
|
|
102
98
|
return result?.value ?? null;
|
|
@@ -106,14 +102,14 @@ export class SQLiteStorage {
|
|
|
106
102
|
* If a function is provided, it computes the new value based on the previous value.
|
|
107
103
|
*/
|
|
108
104
|
setItemSync(key, value) {
|
|
109
|
-
checkValidInput(key, value);
|
|
105
|
+
this.checkValidInput(key, value);
|
|
110
106
|
const db = this.getDbSync();
|
|
111
107
|
if (typeof value === 'function') {
|
|
112
108
|
db.withTransactionSync(() => {
|
|
113
109
|
const prevResult = db.getFirstSync(STATEMENT_GET, key);
|
|
114
110
|
const prevValue = prevResult?.value ?? null;
|
|
115
111
|
const nextValue = value(prevValue);
|
|
116
|
-
checkValidInput(key, nextValue);
|
|
112
|
+
this.checkValidInput(key, nextValue);
|
|
117
113
|
db.runSync(STATEMENT_SET, key, nextValue);
|
|
118
114
|
});
|
|
119
115
|
return;
|
|
@@ -124,7 +120,7 @@ export class SQLiteStorage {
|
|
|
124
120
|
* Removes the value associated with the given key synchronously.
|
|
125
121
|
*/
|
|
126
122
|
removeItemSync(key) {
|
|
127
|
-
checkValidInput(key);
|
|
123
|
+
this.checkValidInput(key);
|
|
128
124
|
const db = this.getDbSync();
|
|
129
125
|
const result = db.runSync(STATEMENT_REMOVE, key);
|
|
130
126
|
return result.changes > 0;
|
|
@@ -191,7 +187,7 @@ export class SQLiteStorage {
|
|
|
191
187
|
* If the existing value is a JSON object, performs a deep merge.
|
|
192
188
|
*/
|
|
193
189
|
async mergeItem(key, value) {
|
|
194
|
-
checkValidInput(key, value);
|
|
190
|
+
this.checkValidInput(key, value);
|
|
195
191
|
await this.setItemAsync(key, (prevValue) => {
|
|
196
192
|
if (prevValue == null) {
|
|
197
193
|
return value;
|
|
@@ -207,7 +203,7 @@ export class SQLiteStorage {
|
|
|
207
203
|
*/
|
|
208
204
|
async multiGet(keys) {
|
|
209
205
|
return Promise.all(keys.map(async (key) => {
|
|
210
|
-
checkValidInput(key);
|
|
206
|
+
this.checkValidInput(key);
|
|
211
207
|
return [key, await this.getItemAsync(key)];
|
|
212
208
|
}));
|
|
213
209
|
}
|
|
@@ -215,10 +211,10 @@ export class SQLiteStorage {
|
|
|
215
211
|
* Sets multiple key-value pairs asynchronously.
|
|
216
212
|
*/
|
|
217
213
|
async multiSet(keyValuePairs) {
|
|
218
|
-
const db = this.
|
|
214
|
+
const db = await this.getDbAsync();
|
|
219
215
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
220
216
|
for (const [key, value] of keyValuePairs) {
|
|
221
|
-
checkValidInput(key, value);
|
|
217
|
+
this.checkValidInput(key, value);
|
|
222
218
|
await tx.runAsync(STATEMENT_SET, key, value);
|
|
223
219
|
}
|
|
224
220
|
});
|
|
@@ -227,10 +223,10 @@ export class SQLiteStorage {
|
|
|
227
223
|
* Removes the values associated with the given keys asynchronously.
|
|
228
224
|
*/
|
|
229
225
|
async multiRemove(keys) {
|
|
230
|
-
const db = this.
|
|
226
|
+
const db = await this.getDbAsync();
|
|
231
227
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
232
228
|
for (const key of keys) {
|
|
233
|
-
checkValidInput(key);
|
|
229
|
+
this.checkValidInput(key);
|
|
234
230
|
await tx.runAsync(STATEMENT_REMOVE, key);
|
|
235
231
|
}
|
|
236
232
|
});
|
|
@@ -240,10 +236,10 @@ export class SQLiteStorage {
|
|
|
240
236
|
* If existing values are JSON objects, performs a deep merge.
|
|
241
237
|
*/
|
|
242
238
|
async multiMerge(keyValuePairs) {
|
|
243
|
-
const db = this.
|
|
239
|
+
const db = await this.getDbAsync();
|
|
244
240
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
245
241
|
for (const [key, value] of keyValuePairs) {
|
|
246
|
-
checkValidInput(key, value);
|
|
242
|
+
this.checkValidInput(key, value);
|
|
247
243
|
const prevValue = await tx.getFirstAsync(STATEMENT_GET, key);
|
|
248
244
|
if (prevValue == null) {
|
|
249
245
|
await tx.runAsync(STATEMENT_SET, key, value);
|
|
@@ -264,6 +260,20 @@ export class SQLiteStorage {
|
|
|
264
260
|
}
|
|
265
261
|
//#endregion
|
|
266
262
|
//#region Internals
|
|
263
|
+
async getDbAsync() {
|
|
264
|
+
await this.awaitLock.acquireAsync();
|
|
265
|
+
try {
|
|
266
|
+
if (!this.db) {
|
|
267
|
+
const db = await openDatabaseAsync(this.databaseName);
|
|
268
|
+
await this.maybeMigrateDbAsync(db);
|
|
269
|
+
this.db = db;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
finally {
|
|
273
|
+
this.awaitLock.release();
|
|
274
|
+
}
|
|
275
|
+
return this.db;
|
|
276
|
+
}
|
|
267
277
|
getDbSync() {
|
|
268
278
|
if (!this.db) {
|
|
269
279
|
const db = openDatabaseSync(this.databaseName);
|
|
@@ -272,6 +282,20 @@ export class SQLiteStorage {
|
|
|
272
282
|
}
|
|
273
283
|
return this.db;
|
|
274
284
|
}
|
|
285
|
+
maybeMigrateDbAsync(db) {
|
|
286
|
+
return db.withTransactionAsync(async () => {
|
|
287
|
+
const result = await db.getFirstAsync('PRAGMA user_version');
|
|
288
|
+
let currentDbVersion = result?.user_version ?? 0;
|
|
289
|
+
if (currentDbVersion >= DATABASE_VERSION) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (currentDbVersion === 0) {
|
|
293
|
+
await db.execAsync(MIGRATION_STATEMENT_0);
|
|
294
|
+
currentDbVersion = 1;
|
|
295
|
+
}
|
|
296
|
+
await db.execAsync(`PRAGMA user_version = ${DATABASE_VERSION}`);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
275
299
|
maybeMigrateDbSync(db) {
|
|
276
300
|
db.withTransactionSync(() => {
|
|
277
301
|
const result = db.getFirstSync('PRAGMA user_version');
|
|
@@ -313,6 +337,15 @@ export class SQLiteStorage {
|
|
|
313
337
|
}
|
|
314
338
|
return output;
|
|
315
339
|
}
|
|
340
|
+
checkValidInput(...input) {
|
|
341
|
+
const [key, value] = input;
|
|
342
|
+
if (typeof key !== 'string') {
|
|
343
|
+
throw new Error(`[SQLiteStorage] Using ${typeof key} type for key is not supported. Use string instead. Key passed: ${key}`);
|
|
344
|
+
}
|
|
345
|
+
if (input.length > 1 && typeof value !== 'string' && typeof value !== 'function') {
|
|
346
|
+
throw new Error(`[SQLiteStorage] Using ${typeof value} type for value is not supported. Use string instead. Key passed: ${key}. Value passed : ${value}`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
316
349
|
}
|
|
317
350
|
/**
|
|
318
351
|
* 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).
|
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 * @hidden\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"]}
|
|
1
|
+
{"version":3,"file":"Storage.js","sourceRoot":"","sources":["../src/Storage.ts"],"names":[],"mappings":"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","sourcesContent":["import AwaitLock from 'await-lock';\n\nimport { 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 private readonly awaitLock = new AwaitLock();\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 this.checkValidInput(key);\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 this.checkValidInput(key, value);\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 this.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 this.checkValidInput(key);\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 await this.awaitLock.acquireAsync();\n try {\n if (this.db) {\n await this.db.closeAsync();\n this.db = null;\n }\n } finally {\n this.awaitLock.release();\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 this.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 this.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 this.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 this.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 this.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 this.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 = await this.getDbAsync();\n await db.withExclusiveTransactionAsync(async (tx) => {\n for (const [key, value] of keyValuePairs) {\n this.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 = await this.getDbAsync();\n await db.withExclusiveTransactionAsync(async (tx) => {\n for (const key of keys) {\n this.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 = await this.getDbAsync();\n await db.withExclusiveTransactionAsync(async (tx) => {\n for (const [key, value] of keyValuePairs) {\n this.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 async getDbAsync(): Promise<SQLiteDatabase> {\n await this.awaitLock.acquireAsync();\n try {\n if (!this.db) {\n const db = await openDatabaseAsync(this.databaseName);\n await this.maybeMigrateDbAsync(db);\n this.db = db;\n }\n } finally {\n this.awaitLock.release();\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 maybeMigrateDbAsync(db: SQLiteDatabase) {\n return db.withTransactionAsync(async () => {\n const result = await db.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 db.execAsync(MIGRATION_STATEMENT_0);\n currentDbVersion = 1;\n }\n await db.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 private 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 //#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/expo-module.config.json
CHANGED
|
@@ -5,12 +5,6 @@
|
|
|
5
5
|
},
|
|
6
6
|
"android": {
|
|
7
7
|
"modules": ["expo.modules.sqlite.SQLiteModule"],
|
|
8
|
-
"shouldUsePublicationScriptPath": "android/shouldUsePublication.groovy"
|
|
9
|
-
"publication": {
|
|
10
|
-
"groupId": "host.exp.exponent",
|
|
11
|
-
"artifactId": "expo.modules.sqlite",
|
|
12
|
-
"version": "15.2.8",
|
|
13
|
-
"repository": "local-maven-repo"
|
|
14
|
-
}
|
|
8
|
+
"shouldUsePublicationScriptPath": "android/shouldUsePublication.groovy"
|
|
15
9
|
}
|
|
16
10
|
}
|
package/ios/SQLiteModule.swift
CHANGED
|
@@ -371,6 +371,13 @@ public final class SQLiteModule: Module {
|
|
|
371
371
|
try maybeThrowForClosedDatabase(database)
|
|
372
372
|
try maybeThrowForFinalizedStatement(statement)
|
|
373
373
|
|
|
374
|
+
// The statement with parameter bindings is stateful,
|
|
375
|
+
// we have to guard with a critical section for thread safety.
|
|
376
|
+
statement.lock.wait()
|
|
377
|
+
defer {
|
|
378
|
+
statement.lock.signal()
|
|
379
|
+
}
|
|
380
|
+
|
|
374
381
|
exsqlite3_reset(statement.pointer)
|
|
375
382
|
exsqlite3_clear_bindings(statement.pointer)
|
|
376
383
|
for (key, param) in bindParams {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-sqlite",
|
|
3
|
-
"version": "15.2.
|
|
3
|
+
"version": "15.2.10",
|
|
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",
|
|
@@ -48,12 +48,14 @@
|
|
|
48
48
|
"jest": {
|
|
49
49
|
"preset": "expo-module-scripts"
|
|
50
50
|
},
|
|
51
|
-
"dependencies": {
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"await-lock": "^2.2.2"
|
|
53
|
+
},
|
|
52
54
|
"devDependencies": {
|
|
53
55
|
"@testing-library/react-native": "^13.1.0",
|
|
54
56
|
"@types/better-sqlite3": "^7.6.6",
|
|
55
57
|
"better-sqlite3": "^11.6.0",
|
|
56
|
-
"expo-module-scripts": "^4.1.
|
|
58
|
+
"expo-module-scripts": "^4.1.7",
|
|
57
59
|
"react-error-boundary": "^4.0.11"
|
|
58
60
|
},
|
|
59
61
|
"peerDependencies": {
|
|
@@ -61,5 +63,5 @@
|
|
|
61
63
|
"react": "*",
|
|
62
64
|
"react-native": "*"
|
|
63
65
|
},
|
|
64
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "49c9d53cf0a9fc8179d1c8f5268beadd141f70ca"
|
|
65
67
|
}
|
package/src/Storage.ts
CHANGED
|
@@ -1,23 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import AwaitLock from 'await-lock';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
* @hidden
|
|
5
|
-
*/
|
|
6
|
-
export function checkValidInput(...input: unknown[]) {
|
|
7
|
-
const [key, value] = input;
|
|
8
|
-
|
|
9
|
-
if (typeof key !== 'string') {
|
|
10
|
-
throw new Error(
|
|
11
|
-
`[SQLiteStorage] Using ${typeof key} type for key is not supported. Use string instead. Key passed: ${key}`
|
|
12
|
-
);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (input.length > 1 && typeof value !== 'string' && typeof value !== 'function') {
|
|
16
|
-
throw new Error(
|
|
17
|
-
`[SQLiteStorage] Using ${typeof value} type for value is not supported. Use string instead. Key passed: ${key}. Value passed : ${value}`
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
3
|
+
import { openDatabaseAsync, openDatabaseSync, type SQLiteDatabase } from './index';
|
|
21
4
|
|
|
22
5
|
/**
|
|
23
6
|
* 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.
|
|
@@ -42,6 +25,7 @@ const MIGRATION_STATEMENT_0 =
|
|
|
42
25
|
*/
|
|
43
26
|
export class SQLiteStorage {
|
|
44
27
|
private db: SQLiteDatabase | null = null;
|
|
28
|
+
private readonly awaitLock = new AwaitLock();
|
|
45
29
|
|
|
46
30
|
constructor(private readonly databaseName: string) {}
|
|
47
31
|
|
|
@@ -51,8 +35,8 @@ export class SQLiteStorage {
|
|
|
51
35
|
* Retrieves the value associated with the given key asynchronously.
|
|
52
36
|
*/
|
|
53
37
|
async getItemAsync(key: string): Promise<string | null> {
|
|
54
|
-
checkValidInput(key);
|
|
55
|
-
const db = this.
|
|
38
|
+
this.checkValidInput(key);
|
|
39
|
+
const db = await this.getDbAsync();
|
|
56
40
|
const result = await db.getFirstAsync<{ value: string }>(STATEMENT_GET, key);
|
|
57
41
|
return result?.value ?? null;
|
|
58
42
|
}
|
|
@@ -65,15 +49,15 @@ export class SQLiteStorage {
|
|
|
65
49
|
key: string,
|
|
66
50
|
value: string | SQLiteStorageSetItemUpdateFunction
|
|
67
51
|
): Promise<void> {
|
|
68
|
-
checkValidInput(key, value);
|
|
69
|
-
const db = this.
|
|
52
|
+
this.checkValidInput(key, value);
|
|
53
|
+
const db = await this.getDbAsync();
|
|
70
54
|
|
|
71
55
|
if (typeof value === 'function') {
|
|
72
56
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
73
57
|
const prevResult = await tx.getFirstAsync<{ value: string }>(STATEMENT_GET, key);
|
|
74
58
|
const prevValue = prevResult?.value ?? null;
|
|
75
59
|
const nextValue = value(prevValue);
|
|
76
|
-
checkValidInput(key, nextValue);
|
|
60
|
+
this.checkValidInput(key, nextValue);
|
|
77
61
|
await tx.runAsync(STATEMENT_SET, key, nextValue);
|
|
78
62
|
});
|
|
79
63
|
return;
|
|
@@ -86,8 +70,8 @@ export class SQLiteStorage {
|
|
|
86
70
|
* Removes the value associated with the given key asynchronously.
|
|
87
71
|
*/
|
|
88
72
|
async removeItemAsync(key: string): Promise<boolean> {
|
|
89
|
-
checkValidInput(key);
|
|
90
|
-
const db = this.
|
|
73
|
+
this.checkValidInput(key);
|
|
74
|
+
const db = await this.getDbAsync();
|
|
91
75
|
const result = await db.runAsync(STATEMENT_REMOVE, key);
|
|
92
76
|
return result.changes > 0;
|
|
93
77
|
}
|
|
@@ -96,7 +80,7 @@ export class SQLiteStorage {
|
|
|
96
80
|
* Retrieves all keys stored in the storage asynchronously.
|
|
97
81
|
*/
|
|
98
82
|
async getAllKeysAsync(): Promise<string[]> {
|
|
99
|
-
const db = this.
|
|
83
|
+
const db = await this.getDbAsync();
|
|
100
84
|
const result = await db.getAllAsync<{ key: string }>(STATEMENT_GET_ALL_KEYS);
|
|
101
85
|
return result.map(({ key }) => key);
|
|
102
86
|
}
|
|
@@ -105,7 +89,7 @@ export class SQLiteStorage {
|
|
|
105
89
|
* Clears all key-value pairs from the storage asynchronously.
|
|
106
90
|
*/
|
|
107
91
|
async clearAsync(): Promise<boolean> {
|
|
108
|
-
const db = this.
|
|
92
|
+
const db = await this.getDbAsync();
|
|
109
93
|
const result = await db.runAsync(STATEMENT_CLEAR);
|
|
110
94
|
return result.changes > 0;
|
|
111
95
|
}
|
|
@@ -114,9 +98,14 @@ export class SQLiteStorage {
|
|
|
114
98
|
* Closes the database connection asynchronously.
|
|
115
99
|
*/
|
|
116
100
|
async closeAsync(): Promise<void> {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.db
|
|
101
|
+
await this.awaitLock.acquireAsync();
|
|
102
|
+
try {
|
|
103
|
+
if (this.db) {
|
|
104
|
+
await this.db.closeAsync();
|
|
105
|
+
this.db = null;
|
|
106
|
+
}
|
|
107
|
+
} finally {
|
|
108
|
+
this.awaitLock.release();
|
|
120
109
|
}
|
|
121
110
|
}
|
|
122
111
|
|
|
@@ -128,7 +117,7 @@ export class SQLiteStorage {
|
|
|
128
117
|
* Retrieves the value associated with the given key synchronously.
|
|
129
118
|
*/
|
|
130
119
|
getItemSync(key: string): string | null {
|
|
131
|
-
checkValidInput(key);
|
|
120
|
+
this.checkValidInput(key);
|
|
132
121
|
const db = this.getDbSync();
|
|
133
122
|
const result = db.getFirstSync<{ value: string }>(STATEMENT_GET, key);
|
|
134
123
|
return result?.value ?? null;
|
|
@@ -139,7 +128,7 @@ export class SQLiteStorage {
|
|
|
139
128
|
* If a function is provided, it computes the new value based on the previous value.
|
|
140
129
|
*/
|
|
141
130
|
setItemSync(key: string, value: string | SQLiteStorageSetItemUpdateFunction): void {
|
|
142
|
-
checkValidInput(key, value);
|
|
131
|
+
this.checkValidInput(key, value);
|
|
143
132
|
const db = this.getDbSync();
|
|
144
133
|
|
|
145
134
|
if (typeof value === 'function') {
|
|
@@ -147,7 +136,7 @@ export class SQLiteStorage {
|
|
|
147
136
|
const prevResult = db.getFirstSync<{ value: string }>(STATEMENT_GET, key);
|
|
148
137
|
const prevValue = prevResult?.value ?? null;
|
|
149
138
|
const nextValue = value(prevValue);
|
|
150
|
-
checkValidInput(key, nextValue);
|
|
139
|
+
this.checkValidInput(key, nextValue);
|
|
151
140
|
db.runSync(STATEMENT_SET, key, nextValue);
|
|
152
141
|
});
|
|
153
142
|
return;
|
|
@@ -160,7 +149,7 @@ export class SQLiteStorage {
|
|
|
160
149
|
* Removes the value associated with the given key synchronously.
|
|
161
150
|
*/
|
|
162
151
|
removeItemSync(key: string): boolean {
|
|
163
|
-
checkValidInput(key);
|
|
152
|
+
this.checkValidInput(key);
|
|
164
153
|
const db = this.getDbSync();
|
|
165
154
|
const result = db.runSync(STATEMENT_REMOVE, key);
|
|
166
155
|
return result.changes > 0;
|
|
@@ -238,7 +227,7 @@ export class SQLiteStorage {
|
|
|
238
227
|
* If the existing value is a JSON object, performs a deep merge.
|
|
239
228
|
*/
|
|
240
229
|
async mergeItem(key: string, value: string): Promise<void> {
|
|
241
|
-
checkValidInput(key, value);
|
|
230
|
+
this.checkValidInput(key, value);
|
|
242
231
|
await this.setItemAsync(key, (prevValue) => {
|
|
243
232
|
if (prevValue == null) {
|
|
244
233
|
return value;
|
|
@@ -256,7 +245,7 @@ export class SQLiteStorage {
|
|
|
256
245
|
async multiGet(keys: string[]): Promise<[string, string | null][]> {
|
|
257
246
|
return Promise.all(
|
|
258
247
|
keys.map(async (key): Promise<[string, string | null]> => {
|
|
259
|
-
checkValidInput(key);
|
|
248
|
+
this.checkValidInput(key);
|
|
260
249
|
return [key, await this.getItemAsync(key)];
|
|
261
250
|
})
|
|
262
251
|
);
|
|
@@ -266,10 +255,10 @@ export class SQLiteStorage {
|
|
|
266
255
|
* Sets multiple key-value pairs asynchronously.
|
|
267
256
|
*/
|
|
268
257
|
async multiSet(keyValuePairs: [string, string][]): Promise<void> {
|
|
269
|
-
const db = this.
|
|
258
|
+
const db = await this.getDbAsync();
|
|
270
259
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
271
260
|
for (const [key, value] of keyValuePairs) {
|
|
272
|
-
checkValidInput(key, value);
|
|
261
|
+
this.checkValidInput(key, value);
|
|
273
262
|
await tx.runAsync(STATEMENT_SET, key, value);
|
|
274
263
|
}
|
|
275
264
|
});
|
|
@@ -279,10 +268,10 @@ export class SQLiteStorage {
|
|
|
279
268
|
* Removes the values associated with the given keys asynchronously.
|
|
280
269
|
*/
|
|
281
270
|
async multiRemove(keys: string[]): Promise<void> {
|
|
282
|
-
const db = this.
|
|
271
|
+
const db = await this.getDbAsync();
|
|
283
272
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
284
273
|
for (const key of keys) {
|
|
285
|
-
checkValidInput(key);
|
|
274
|
+
this.checkValidInput(key);
|
|
286
275
|
await tx.runAsync(STATEMENT_REMOVE, key);
|
|
287
276
|
}
|
|
288
277
|
});
|
|
@@ -293,10 +282,10 @@ export class SQLiteStorage {
|
|
|
293
282
|
* If existing values are JSON objects, performs a deep merge.
|
|
294
283
|
*/
|
|
295
284
|
async multiMerge(keyValuePairs: [string, string][]): Promise<void> {
|
|
296
|
-
const db = this.
|
|
285
|
+
const db = await this.getDbAsync();
|
|
297
286
|
await db.withExclusiveTransactionAsync(async (tx) => {
|
|
298
287
|
for (const [key, value] of keyValuePairs) {
|
|
299
|
-
checkValidInput(key, value);
|
|
288
|
+
this.checkValidInput(key, value);
|
|
300
289
|
const prevValue = await tx.getFirstAsync<{ value: string }>(STATEMENT_GET, key);
|
|
301
290
|
if (prevValue == null) {
|
|
302
291
|
await tx.runAsync(STATEMENT_SET, key, value);
|
|
@@ -321,6 +310,20 @@ export class SQLiteStorage {
|
|
|
321
310
|
|
|
322
311
|
//#region Internals
|
|
323
312
|
|
|
313
|
+
private async getDbAsync(): Promise<SQLiteDatabase> {
|
|
314
|
+
await this.awaitLock.acquireAsync();
|
|
315
|
+
try {
|
|
316
|
+
if (!this.db) {
|
|
317
|
+
const db = await openDatabaseAsync(this.databaseName);
|
|
318
|
+
await this.maybeMigrateDbAsync(db);
|
|
319
|
+
this.db = db;
|
|
320
|
+
}
|
|
321
|
+
} finally {
|
|
322
|
+
this.awaitLock.release();
|
|
323
|
+
}
|
|
324
|
+
return this.db;
|
|
325
|
+
}
|
|
326
|
+
|
|
324
327
|
private getDbSync(): SQLiteDatabase {
|
|
325
328
|
if (!this.db) {
|
|
326
329
|
const db = openDatabaseSync(this.databaseName);
|
|
@@ -330,6 +333,21 @@ export class SQLiteStorage {
|
|
|
330
333
|
return this.db;
|
|
331
334
|
}
|
|
332
335
|
|
|
336
|
+
private maybeMigrateDbAsync(db: SQLiteDatabase) {
|
|
337
|
+
return db.withTransactionAsync(async () => {
|
|
338
|
+
const result = await db.getFirstAsync<{ user_version: number }>('PRAGMA user_version');
|
|
339
|
+
let currentDbVersion = result?.user_version ?? 0;
|
|
340
|
+
if (currentDbVersion >= DATABASE_VERSION) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
if (currentDbVersion === 0) {
|
|
344
|
+
await db.execAsync(MIGRATION_STATEMENT_0);
|
|
345
|
+
currentDbVersion = 1;
|
|
346
|
+
}
|
|
347
|
+
await db.execAsync(`PRAGMA user_version = ${DATABASE_VERSION}`);
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
333
351
|
private maybeMigrateDbSync(db: SQLiteDatabase) {
|
|
334
352
|
db.withTransactionSync(() => {
|
|
335
353
|
const result = db.getFirstSync<{ user_version: number }>('PRAGMA user_version');
|
|
@@ -375,6 +393,22 @@ export class SQLiteStorage {
|
|
|
375
393
|
return output;
|
|
376
394
|
}
|
|
377
395
|
|
|
396
|
+
private checkValidInput(...input: unknown[]) {
|
|
397
|
+
const [key, value] = input;
|
|
398
|
+
|
|
399
|
+
if (typeof key !== 'string') {
|
|
400
|
+
throw new Error(
|
|
401
|
+
`[SQLiteStorage] Using ${typeof key} type for key is not supported. Use string instead. Key passed: ${key}`
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (input.length > 1 && typeof value !== 'string' && typeof value !== 'function') {
|
|
406
|
+
throw new Error(
|
|
407
|
+
`[SQLiteStorage] Using ${typeof value} type for value is not supported. Use string instead. Key passed: ${key}. Value passed : ${value}`
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
378
412
|
//#endregion
|
|
379
413
|
}
|
|
380
414
|
|
package/web/WorkerChannel.ts
CHANGED
|
@@ -37,7 +37,7 @@ export function sendWorkerResult({
|
|
|
37
37
|
const { lockBuffer, resultBuffer } = syncTrait;
|
|
38
38
|
const lock = new Int32Array(lockBuffer);
|
|
39
39
|
const resultArray = new Uint8Array(resultBuffer);
|
|
40
|
-
const resultJson =
|
|
40
|
+
const resultJson = error != null ? serialize({ error }) : serialize({ result });
|
|
41
41
|
const resultBytes = new TextEncoder().encode(resultJson);
|
|
42
42
|
const length = resultBytes.length;
|
|
43
43
|
resultArray.set(new Uint32Array([length]), 0);
|
|
@@ -117,13 +117,23 @@ export function invokeWorkerSync<T extends SQLiteWorkerMessageType & keyof Resul
|
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
let i = 0;
|
|
120
|
+
// @ts-expect-error: Remove this when TypeScript supports Atomics.pause
|
|
121
|
+
const useAtomicsPause = typeof Atomics.pause === 'function';
|
|
120
122
|
while (Atomics.load(lock, 0) === PENDING) {
|
|
121
|
-
// NOTE(kudo): Unfortunate busy loop,
|
|
122
|
-
// because we don't have a way for main thread to yield its execution to other callbacks.
|
|
123
|
-
// Maybe we can wait for [`Atomics.pause`](https://github.com/tc39/proposal-atomics-microwait) to be implemented.
|
|
124
123
|
++i;
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
|
|
125
|
+
if (useAtomicsPause) {
|
|
126
|
+
if (i > 1_000_000) {
|
|
127
|
+
throw new Error('Sync operation timeout');
|
|
128
|
+
}
|
|
129
|
+
// @ts-expect-error: Remove this when TypeScript supports Atomics.pause
|
|
130
|
+
Atomics.pause();
|
|
131
|
+
} else {
|
|
132
|
+
// NOTE(kudo): Unfortunate for the busy loop,
|
|
133
|
+
// because we don't have a way for main thread to yield its execution to other callbacks.
|
|
134
|
+
if (i > 1000_000_000) {
|
|
135
|
+
throw new Error('Sync operation timeout');
|
|
136
|
+
}
|
|
127
137
|
}
|
|
128
138
|
}
|
|
129
139
|
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
bb2978541a06d96c8c2180a09fe4aedc
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1e52a7388cd71d0ad044ecd2658b8f7a89496240
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
df4580eb041e8620081acf960e64263a63771e856a40cc5ee17fa654fe3672da
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
4917cf35bb225309902a2482186f53d3cdde720c66d66ecf0dfa7aa42684a6ac4af424f8ea0e2bc7f7095b6301c1560ccb1fe9b224d8179e86e73e2c0a4c96c1
|
package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.aar
DELETED
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
17a83d0d04765f8cadda48e88a48b683
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
373c2a5b48f8c86abf1a2c022bf19461e156f976
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
12c296c7b073a3619de123a5780a8f448c21d0ec477741729ae3e22969147991
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
c70d17eeafa0bb42f27a0e06919ee3e04a96a88ed852002640fc02d834602d86b622cefb08fa6e181d73758f9eb9f80c021f94161d8fae0ce5f6490261c3cd82
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"formatVersion": "1.1",
|
|
3
|
-
"component": {
|
|
4
|
-
"group": "host.exp.exponent",
|
|
5
|
-
"module": "expo.modules.sqlite",
|
|
6
|
-
"version": "15.2.8",
|
|
7
|
-
"attributes": {
|
|
8
|
-
"org.gradle.status": "release"
|
|
9
|
-
}
|
|
10
|
-
},
|
|
11
|
-
"createdBy": {
|
|
12
|
-
"gradle": {
|
|
13
|
-
"version": "8.13"
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"variants": [
|
|
17
|
-
{
|
|
18
|
-
"name": "releaseVariantReleaseApiPublication",
|
|
19
|
-
"attributes": {
|
|
20
|
-
"org.gradle.category": "library",
|
|
21
|
-
"org.gradle.dependency.bundling": "external",
|
|
22
|
-
"org.gradle.libraryelements": "aar",
|
|
23
|
-
"org.gradle.usage": "java-api"
|
|
24
|
-
},
|
|
25
|
-
"files": [
|
|
26
|
-
{
|
|
27
|
-
"name": "expo.modules.sqlite-15.2.8.aar",
|
|
28
|
-
"url": "expo.modules.sqlite-15.2.8.aar",
|
|
29
|
-
"size": 3758068,
|
|
30
|
-
"sha512": "c70d17eeafa0bb42f27a0e06919ee3e04a96a88ed852002640fc02d834602d86b622cefb08fa6e181d73758f9eb9f80c021f94161d8fae0ce5f6490261c3cd82",
|
|
31
|
-
"sha256": "12c296c7b073a3619de123a5780a8f448c21d0ec477741729ae3e22969147991",
|
|
32
|
-
"sha1": "373c2a5b48f8c86abf1a2c022bf19461e156f976",
|
|
33
|
-
"md5": "17a83d0d04765f8cadda48e88a48b683"
|
|
34
|
-
}
|
|
35
|
-
]
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"name": "releaseVariantReleaseRuntimePublication",
|
|
39
|
-
"attributes": {
|
|
40
|
-
"org.gradle.category": "library",
|
|
41
|
-
"org.gradle.dependency.bundling": "external",
|
|
42
|
-
"org.gradle.libraryelements": "aar",
|
|
43
|
-
"org.gradle.usage": "java-runtime"
|
|
44
|
-
},
|
|
45
|
-
"dependencies": [
|
|
46
|
-
{
|
|
47
|
-
"group": "org.jetbrains.kotlin",
|
|
48
|
-
"module": "kotlin-stdlib-jdk7",
|
|
49
|
-
"version": {
|
|
50
|
-
"requires": "2.0.21"
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
],
|
|
54
|
-
"files": [
|
|
55
|
-
{
|
|
56
|
-
"name": "expo.modules.sqlite-15.2.8.aar",
|
|
57
|
-
"url": "expo.modules.sqlite-15.2.8.aar",
|
|
58
|
-
"size": 3758068,
|
|
59
|
-
"sha512": "c70d17eeafa0bb42f27a0e06919ee3e04a96a88ed852002640fc02d834602d86b622cefb08fa6e181d73758f9eb9f80c021f94161d8fae0ce5f6490261c3cd82",
|
|
60
|
-
"sha256": "12c296c7b073a3619de123a5780a8f448c21d0ec477741729ae3e22969147991",
|
|
61
|
-
"sha1": "373c2a5b48f8c86abf1a2c022bf19461e156f976",
|
|
62
|
-
"md5": "17a83d0d04765f8cadda48e88a48b683"
|
|
63
|
-
}
|
|
64
|
-
]
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
"name": "releaseVariantReleaseSourcePublication",
|
|
68
|
-
"attributes": {
|
|
69
|
-
"org.gradle.category": "documentation",
|
|
70
|
-
"org.gradle.dependency.bundling": "external",
|
|
71
|
-
"org.gradle.docstype": "sources",
|
|
72
|
-
"org.gradle.usage": "java-runtime"
|
|
73
|
-
},
|
|
74
|
-
"files": [
|
|
75
|
-
{
|
|
76
|
-
"name": "expo.modules.sqlite-15.2.8-sources.jar",
|
|
77
|
-
"url": "expo.modules.sqlite-15.2.8-sources.jar",
|
|
78
|
-
"size": 11071,
|
|
79
|
-
"sha512": "4917cf35bb225309902a2482186f53d3cdde720c66d66ecf0dfa7aa42684a6ac4af424f8ea0e2bc7f7095b6301c1560ccb1fe9b224d8179e86e73e2c0a4c96c1",
|
|
80
|
-
"sha256": "df4580eb041e8620081acf960e64263a63771e856a40cc5ee17fa654fe3672da",
|
|
81
|
-
"sha1": "1e52a7388cd71d0ad044ecd2658b8f7a89496240",
|
|
82
|
-
"md5": "bb2978541a06d96c8c2180a09fe4aedc"
|
|
83
|
-
}
|
|
84
|
-
]
|
|
85
|
-
}
|
|
86
|
-
]
|
|
87
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
56ae0dd0cc3d17700730d494fadce084
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
e799389f28969ed5dbdbf0249ede84761ae646ff
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
6e100e76f2d2aa965f62c2fad77288bddff9869753ed5e8ccdfce17906806125
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
51467664d410566ae09beedec81353d9beca8e1fd09ffef3d7162032cc0e3b0788778d84d390e6074bb93ef938f23a5adf8a4a6bff7c28154c69a38dd59ca4cd
|
package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/15.2.8/expo.modules.sqlite-15.2.8.pom
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
3
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
4
|
-
<!-- This module was also published with a richer model, Gradle metadata, -->
|
|
5
|
-
<!-- which should be used instead. Do not delete the following line which -->
|
|
6
|
-
<!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
|
|
7
|
-
<!-- that they should prefer consuming it instead. -->
|
|
8
|
-
<!-- do_not_remove: published-with-gradle-metadata -->
|
|
9
|
-
<modelVersion>4.0.0</modelVersion>
|
|
10
|
-
<groupId>host.exp.exponent</groupId>
|
|
11
|
-
<artifactId>expo.modules.sqlite</artifactId>
|
|
12
|
-
<version>15.2.8</version>
|
|
13
|
-
<packaging>aar</packaging>
|
|
14
|
-
<name>expo.modules.sqlite</name>
|
|
15
|
-
<url>https://github.com/expo/expo</url>
|
|
16
|
-
<licenses>
|
|
17
|
-
<license>
|
|
18
|
-
<name>MIT License</name>
|
|
19
|
-
<url>https://github.com/expo/expo/blob/main/LICENSE</url>
|
|
20
|
-
</license>
|
|
21
|
-
</licenses>
|
|
22
|
-
<scm>
|
|
23
|
-
<connection>https://github.com/expo/expo.git</connection>
|
|
24
|
-
<developerConnection>https://github.com/expo/expo.git</developerConnection>
|
|
25
|
-
<url>https://github.com/expo/expo</url>
|
|
26
|
-
</scm>
|
|
27
|
-
<dependencies>
|
|
28
|
-
<dependency>
|
|
29
|
-
<groupId>org.jetbrains.kotlin</groupId>
|
|
30
|
-
<artifactId>kotlin-stdlib-jdk7</artifactId>
|
|
31
|
-
<version>2.0.21</version>
|
|
32
|
-
<scope>runtime</scope>
|
|
33
|
-
</dependency>
|
|
34
|
-
</dependencies>
|
|
35
|
-
</project>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
158a424ea2c64707a7502dd6c053ba6b
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
f2105f606d51a0265372320bc66e8336bf647a05
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
45a08465c72f5ceda3d441237f7c67107c35de4346f494564bbe8675231370dc
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
e915ce90a954d2b9d2da8ed0381fadc4b12c04023855483f256b935efd253cb909290d5b92a125249adfe7fac2ea9a0f2cbe45f838fa0349f954dd48261a16dd
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<metadata>
|
|
3
|
-
<groupId>host.exp.exponent</groupId>
|
|
4
|
-
<artifactId>expo.modules.sqlite</artifactId>
|
|
5
|
-
<versioning>
|
|
6
|
-
<latest>15.2.8</latest>
|
|
7
|
-
<release>15.2.8</release>
|
|
8
|
-
<versions>
|
|
9
|
-
<version>15.2.8</version>
|
|
10
|
-
</versions>
|
|
11
|
-
<lastUpdated>20250430004833</lastUpdated>
|
|
12
|
-
</versioning>
|
|
13
|
-
</metadata>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
34281fd770bcfdde100e2a826b84cf11
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
521b94cad30343107562622504b4bfb0e937031c
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
e492abde13ac3e8aad89adf146ddbee7429cd0db1db14908ac2925de2f8ad0c6
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
79efeb5cd7f3446b05cc5f58154f3ba85c92a28f8eb49f3ac2c6475756d6e13aabe136a0ba5a9caae3275ee22f4f191184dc92c9c2a9265b8d3f137816db31bf
|