expo-sqlite 11.3.0 → 11.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/sqlite/SQLExceptions.kt +15 -0
- package/android/src/main/java/expo/modules/sqlite/SQLRecords.kt +11 -0
- package/android/src/main/java/expo/modules/sqlite/SQLiteHelpers.kt +1 -2
- package/android/src/main/java/expo/modules/sqlite/SQLiteModule.kt +38 -42
- package/build/SQLite.d.ts +60 -2
- package/build/SQLite.d.ts.map +1 -1
- package/build/SQLite.js +79 -4
- package/build/SQLite.js.map +1 -1
- package/build/SQLite.types.d.ts +12 -4
- package/build/SQLite.types.d.ts.map +1 -1
- package/build/SQLite.types.js.map +1 -1
- package/expo-module.config.json +3 -0
- package/ios/SQLiteModule.swift +5 -1
- package/package.json +2 -2
- package/src/SQLite.ts +129 -8
- package/src/SQLite.types.ts +17 -5
- package/android/src/main/java/expo/modules/sqlite/SQLitePackage.kt +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,23 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 11.4.0 — 2023-07-28
|
|
14
|
+
|
|
15
|
+
### 🎉 New features
|
|
16
|
+
|
|
17
|
+
- Add synchronous method `closeSync`. ([#23757](https://github.com/expo/expo/pull/23757) by [@alanjhughes](https://github.com/alanjhughes))
|
|
18
|
+
|
|
19
|
+
### 🐛 Bug fixes
|
|
20
|
+
|
|
21
|
+
- Fixed missing `transaction()` and `readTransaction()` function types from `SQLiteDatabase`. ([#23751](https://github.com/expo/expo/pull/23751) by [@kudo](https://github.com/kudo))
|
|
22
|
+
|
|
23
|
+
## 11.3.1 — 2023-06-28
|
|
24
|
+
|
|
25
|
+
### 🎉 New features
|
|
26
|
+
|
|
27
|
+
- Migrated Android codebase to Expo Modules API. ([#23115](https://github.com/expo/expo/pull/23115) by [@alanjhughes](https://github.com/alanjhughes))
|
|
28
|
+
- Added experimental `Promise` based `execAsync` and `transactionAsync` functions. ([#23109](https://github.com/expo/expo/pull/23109) by [@kudo](https://github.com/kudo))
|
|
29
|
+
|
|
13
30
|
## 11.3.0 — 2023-06-21
|
|
14
31
|
|
|
15
32
|
### 🐛 Bug fixes
|
package/android/build.gradle
CHANGED
|
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
|
|
|
3
3
|
apply plugin: 'maven-publish'
|
|
4
4
|
|
|
5
5
|
group = 'host.exp.exponent'
|
|
6
|
-
version = '11.
|
|
6
|
+
version = '11.4.0'
|
|
7
7
|
|
|
8
8
|
buildscript {
|
|
9
9
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
@@ -67,7 +67,7 @@ android {
|
|
|
67
67
|
minSdkVersion safeExtGet("minSdkVersion", 21)
|
|
68
68
|
targetSdkVersion safeExtGet("targetSdkVersion", 33)
|
|
69
69
|
versionCode 18
|
|
70
|
-
versionName "11.
|
|
70
|
+
versionName "11.4.0"
|
|
71
71
|
}
|
|
72
72
|
lintOptions {
|
|
73
73
|
abortOnError false
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package expo.modules.sqlite
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.exception.CodedException
|
|
4
|
+
|
|
5
|
+
class OpenDatabaseException(name: String) :
|
|
6
|
+
CodedException("Unable to delete database '$name' that is currently open. Close it prior to deletion.")
|
|
7
|
+
|
|
8
|
+
class DatabaseNotFoundException(name: String) :
|
|
9
|
+
CodedException("Database '$name' not found")
|
|
10
|
+
|
|
11
|
+
class DeleteDatabaseException(name: String) :
|
|
12
|
+
CodedException("Unable to delete the database file for '$name' database")
|
|
13
|
+
|
|
14
|
+
class SQLiteException(message: String?, cause: Throwable?) :
|
|
15
|
+
CodedException(SQLiteModule::class.java.simpleName, message, cause)
|
|
@@ -2,7 +2,6 @@ package expo.modules.sqlite
|
|
|
2
2
|
|
|
3
3
|
import java.io.File
|
|
4
4
|
import java.io.IOException
|
|
5
|
-
import java.util.ArrayList
|
|
6
5
|
|
|
7
6
|
@Throws(IOException::class)
|
|
8
7
|
internal fun ensureDirExists(dir: File): File {
|
|
@@ -77,7 +76,7 @@ private fun startsWithCaseInsensitive(str: String, substr: String): Boolean {
|
|
|
77
76
|
return str.trimStart().startsWith(substr, true)
|
|
78
77
|
}
|
|
79
78
|
|
|
80
|
-
internal fun convertParamsToStringArray(paramArrayArg:
|
|
79
|
+
internal fun convertParamsToStringArray(paramArrayArg: List<Any?>): Array<String?> {
|
|
81
80
|
return paramArrayArg.map { param ->
|
|
82
81
|
when (param) {
|
|
83
82
|
is String -> unescapeBlob(param)
|
|
@@ -4,31 +4,30 @@ package expo.modules.sqlite
|
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.database.Cursor
|
|
6
6
|
import android.database.sqlite.SQLiteDatabase
|
|
7
|
-
import expo.modules.
|
|
8
|
-
import expo.modules.
|
|
9
|
-
import expo.modules.
|
|
7
|
+
import expo.modules.kotlin.exception.Exceptions
|
|
8
|
+
import expo.modules.kotlin.modules.Module
|
|
9
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
10
10
|
import java.io.File
|
|
11
11
|
import java.io.IOException
|
|
12
12
|
import java.util.*
|
|
13
13
|
|
|
14
|
-
private val
|
|
15
|
-
private val
|
|
16
|
-
private val EMPTY_COLUMNS = arrayOf<String?>()
|
|
14
|
+
private val EMPTY_ROWS = emptyArray<Array<Any?>>()
|
|
15
|
+
private val EMPTY_COLUMNS = emptyArray<String?>()
|
|
17
16
|
private val EMPTY_RESULT = SQLiteModule.SQLitePluginResult(EMPTY_ROWS, EMPTY_COLUMNS, 0, 0, null)
|
|
18
17
|
private val DATABASES: MutableMap<String, SQLiteDatabase?> = HashMap()
|
|
19
18
|
|
|
20
|
-
class SQLiteModule
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
class SQLiteModule : Module() {
|
|
20
|
+
private val context: Context
|
|
21
|
+
get() = appContext.reactContext ?: throw Exceptions.ReactContextLost()
|
|
22
|
+
|
|
23
|
+
override fun definition() = ModuleDefinition {
|
|
24
|
+
Name("ExpoSQLite")
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
fun exec(dbName: String, queries: ArrayList<ArrayList<Any>>, readOnly: Boolean, promise: Promise) {
|
|
27
|
-
try {
|
|
26
|
+
AsyncFunction("exec") { dbName: String, queries: List<Query>, readOnly: Boolean ->
|
|
28
27
|
val db = getDatabase(dbName)
|
|
29
28
|
val results = queries.map { sqlQuery ->
|
|
30
|
-
val sql = sqlQuery
|
|
31
|
-
val bindArgs = convertParamsToStringArray(sqlQuery
|
|
29
|
+
val sql = sqlQuery.sql
|
|
30
|
+
val bindArgs = convertParamsToStringArray(sqlQuery.args)
|
|
32
31
|
try {
|
|
33
32
|
if (isSelect(sql)) {
|
|
34
33
|
doSelectInBackgroundAndPossiblyThrow(sql, bindArgs, db)
|
|
@@ -43,37 +42,33 @@ class SQLiteModule(private val mContext: Context) : ExportedModule(mContext) {
|
|
|
43
42
|
SQLitePluginResult(EMPTY_ROWS, EMPTY_COLUMNS, 0, 0, e)
|
|
44
43
|
}
|
|
45
44
|
}
|
|
46
|
-
|
|
47
|
-
promise.resolve(data)
|
|
48
|
-
} catch (e: Exception) {
|
|
49
|
-
promise.reject("SQLiteError", e)
|
|
45
|
+
return@AsyncFunction pluginResultsToPrimitiveData(results)
|
|
50
46
|
}
|
|
51
|
-
}
|
|
52
47
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
?.close()
|
|
58
|
-
promise.resolve(null)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
@ExpoMethod
|
|
62
|
-
fun deleteAsync(dbName: String, promise: Promise) {
|
|
63
|
-
val errorCode = "SQLiteError"
|
|
64
|
-
if (DATABASES.containsKey(dbName)) {
|
|
65
|
-
promise.reject(errorCode, "Unable to delete database '$dbName' that is currently open. Close it prior to deletion.")
|
|
48
|
+
AsyncFunction("close") { dbName: String ->
|
|
49
|
+
DATABASES
|
|
50
|
+
.remove(dbName)
|
|
51
|
+
?.close()
|
|
66
52
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
53
|
+
|
|
54
|
+
Function("closeSync") { dbName: String ->
|
|
55
|
+
DATABASES
|
|
56
|
+
.remove(dbName)
|
|
57
|
+
?.close()
|
|
71
58
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
59
|
+
|
|
60
|
+
AsyncFunction("deleteAsync") { dbName: String ->
|
|
61
|
+
if (DATABASES.containsKey(dbName)) {
|
|
62
|
+
throw OpenDatabaseException(dbName)
|
|
63
|
+
}
|
|
64
|
+
val dbFile = File(pathForDatabaseName(dbName))
|
|
65
|
+
if (!dbFile.exists()) {
|
|
66
|
+
throw DatabaseNotFoundException(dbName)
|
|
67
|
+
}
|
|
68
|
+
if (!dbFile.delete()) {
|
|
69
|
+
throw DeleteDatabaseException(dbName)
|
|
70
|
+
}
|
|
75
71
|
}
|
|
76
|
-
promise.resolve(null)
|
|
77
72
|
}
|
|
78
73
|
|
|
79
74
|
// do a update/delete/insert operation
|
|
@@ -143,6 +138,7 @@ class SQLiteModule(private val mContext: Context) : ExportedModule(mContext) {
|
|
|
143
138
|
// convert byte[] to binary string; it's good enough, because
|
|
144
139
|
// WebSQL doesn't support blobs anyway
|
|
145
140
|
String(cursor.getBlob(index))
|
|
141
|
+
|
|
146
142
|
Cursor.FIELD_TYPE_STRING -> cursor.getString(index)
|
|
147
143
|
else -> null
|
|
148
144
|
}
|
|
@@ -150,7 +146,7 @@ class SQLiteModule(private val mContext: Context) : ExportedModule(mContext) {
|
|
|
150
146
|
|
|
151
147
|
@Throws(IOException::class)
|
|
152
148
|
private fun pathForDatabaseName(name: String): String {
|
|
153
|
-
val directory = File("${
|
|
149
|
+
val directory = File("${context.filesDir}${File.separator}SQLite")
|
|
154
150
|
ensureDirExists(directory)
|
|
155
151
|
return "$directory${File.separator}$name"
|
|
156
152
|
}
|
package/build/SQLite.d.ts
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
import './polyfillNextTick';
|
|
2
|
-
import {
|
|
2
|
+
import type { Query, ResultSet, ResultSetError, SQLiteCallback, SQLTransactionAsyncCallback, SQLTransactionAsync, SQLTransactionCallback, SQLTransactionErrorCallback } from './SQLite.types';
|
|
3
|
+
/** The database returned by `openDatabase()` */
|
|
4
|
+
export declare class SQLiteDatabase {
|
|
5
|
+
_name: string;
|
|
6
|
+
_closed: boolean;
|
|
7
|
+
constructor(name: string);
|
|
8
|
+
/**
|
|
9
|
+
* Executes the SQL statement and returns a callback resolving with the result.
|
|
10
|
+
*/
|
|
11
|
+
exec(queries: Query[], readOnly: boolean, callback: SQLiteCallback): void;
|
|
12
|
+
/**
|
|
13
|
+
* Executes the SQL statement and returns a Promise resolving with the result.
|
|
14
|
+
*/
|
|
15
|
+
execAsync(queries: Query[], readOnly: boolean): Promise<(ResultSetError | ResultSet)[]>;
|
|
16
|
+
/**
|
|
17
|
+
* @deprecated Use `closeAsync()` instead.
|
|
18
|
+
*/
|
|
19
|
+
close: () => Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Close the database.
|
|
22
|
+
*/
|
|
23
|
+
closeAsync(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Synchronously closes the database.
|
|
26
|
+
*/
|
|
27
|
+
closeSync(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Delete the database file.
|
|
30
|
+
* > The database has to be closed prior to deletion.
|
|
31
|
+
*/
|
|
32
|
+
deleteAsync(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Creates a new transaction with Promise support.
|
|
35
|
+
* @param asyncCallback A `SQLTransactionAsyncCallback` function that can perform SQL statements in a transaction.
|
|
36
|
+
* @param readOnly true if all the SQL statements in the callback are read only.
|
|
37
|
+
*/
|
|
38
|
+
transactionAsync(asyncCallback: SQLTransactionAsyncCallback, readOnly?: boolean): Promise<void>;
|
|
39
|
+
version: string;
|
|
40
|
+
/**
|
|
41
|
+
* Execute a database transaction.
|
|
42
|
+
* @param callback A function representing the transaction to perform. Takes a Transaction
|
|
43
|
+
* (see below) as its only parameter, on which it can add SQL statements to execute.
|
|
44
|
+
* @param errorCallback Called if an error occurred processing this transaction. Takes a single
|
|
45
|
+
* parameter describing the error.
|
|
46
|
+
* @param successCallback Called when the transaction has completed executing on the database.
|
|
47
|
+
*/
|
|
48
|
+
transaction(callback: SQLTransactionCallback, errorCallback?: SQLTransactionErrorCallback, successCallback?: () => void): void;
|
|
49
|
+
readTransaction(callback: SQLTransactionCallback, errorCallback?: SQLTransactionErrorCallback, successCallback?: () => void): void;
|
|
50
|
+
}
|
|
3
51
|
/**
|
|
4
52
|
* Open a database, creating it if it doesn't exist, and return a `Database` object. On disk,
|
|
5
53
|
* the database will be created under the app's [documents directory](./filesystem), i.e.
|
|
@@ -13,5 +61,15 @@ import { WebSQLDatabase } from './SQLite.types';
|
|
|
13
61
|
* @param callback
|
|
14
62
|
* @return
|
|
15
63
|
*/
|
|
16
|
-
export declare function openDatabase(name: string, version?: string, description?: string, size?: number, callback?: (db:
|
|
64
|
+
export declare function openDatabase(name: string, version?: string, description?: string, size?: number, callback?: (db: SQLiteDatabase) => void): SQLiteDatabase;
|
|
65
|
+
/**
|
|
66
|
+
* Internal data structure for the async transaction API.
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
export declare class ExpoSQLTransactionAsync implements SQLTransactionAsync {
|
|
70
|
+
private readonly db;
|
|
71
|
+
private readonly readOnly;
|
|
72
|
+
constructor(db: SQLiteDatabase, readOnly: boolean);
|
|
73
|
+
executeSqlAsync(sqlStatement: string, args?: (number | string)[]): Promise<ResultSetError | ResultSet>;
|
|
74
|
+
}
|
|
17
75
|
//# sourceMappingURL=SQLite.d.ts.map
|
package/build/SQLite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SQLite.d.ts","sourceRoot":"","sources":["../src/SQLite.ts"],"names":[],"mappings":"AAAA,OAAO,oBAAoB,CAAC;AAM5B,OAAO,
|
|
1
|
+
{"version":3,"file":"SQLite.d.ts","sourceRoot":"","sources":["../src/SQLite.ts"],"names":[],"mappings":"AAAA,OAAO,oBAAoB,CAAC;AAM5B,OAAO,KAAK,EACV,KAAK,EACL,SAAS,EACT,cAAc,EACd,cAAc,EACd,2BAA2B,EAC3B,mBAAmB,EACnB,sBAAsB,EACtB,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AAYxB,gDAAgD;AAChD,qBAAa,cAAc;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAS;gBAEb,IAAI,EAAE,MAAM;IAIxB;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI;IAgBzE;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,cAAc,GAAG,SAAS,CAAC,EAAE,CAAC;IAa7F;;OAEG;IACH,KAAK,QAKS,QAAQ,IAAI,CAAC,CALH;IAExB;;OAEG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B;;OAEG;IACH,SAAS,IAAI,IAAI;IAKjB;;;OAGG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5B;;;;OAIG;IACG,gBAAgB,CACpB,aAAa,EAAE,2BAA2B,EAC1C,QAAQ,GAAE,OAAe,GACxB,OAAO,CAAC,IAAI,CAAC;IAahB,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;;;OAOG;IAEH,WAAW,CACT,QAAQ,EAAE,sBAAsB,EAChC,aAAa,CAAC,EAAE,2BAA2B,EAC3C,eAAe,CAAC,EAAE,MAAM,IAAI,GAC3B,IAAI;IAGP,eAAe,CACb,QAAQ,EAAE,sBAAsB,EAChC,aAAa,CAAC,EAAE,2BAA2B,EAC3C,eAAe,CAAC,EAAE,MAAM,IAAI,GAC3B,IAAI;CACR;AA0CD;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,MAAc,EACvB,WAAW,GAAE,MAAa,EAC1B,IAAI,GAAE,MAAU,EAChB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,cAAc,KAAK,IAAI,GACtC,cAAc,CAYhB;AAED;;;GAGG;AACH,qBAAa,uBAAwB,YAAW,mBAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,EAAE;IAAkB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAA7C,EAAE,EAAE,cAAc,EAAmB,QAAQ,EAAE,OAAO;IAE7E,eAAe,CACnB,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GACzB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;CAOvC"}
|
package/build/SQLite.js
CHANGED
|
@@ -10,12 +10,16 @@ function zipObject(keys, values) {
|
|
|
10
10
|
}
|
|
11
11
|
return result;
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
/** The database returned by `openDatabase()` */
|
|
14
|
+
export class SQLiteDatabase {
|
|
14
15
|
_name;
|
|
15
16
|
_closed = false;
|
|
16
17
|
constructor(name) {
|
|
17
18
|
this._name = name;
|
|
18
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Executes the SQL statement and returns a callback resolving with the result.
|
|
22
|
+
*/
|
|
19
23
|
exec(queries, readOnly, callback) {
|
|
20
24
|
if (this._closed) {
|
|
21
25
|
throw new Error(`The SQLite database is closed`);
|
|
@@ -27,19 +31,71 @@ class SQLiteDatabase {
|
|
|
27
31
|
callback(error instanceof Error ? error : new Error(error));
|
|
28
32
|
});
|
|
29
33
|
}
|
|
30
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Executes the SQL statement and returns a Promise resolving with the result.
|
|
36
|
+
*/
|
|
37
|
+
async execAsync(queries, readOnly) {
|
|
38
|
+
if (this._closed) {
|
|
39
|
+
throw new Error(`The SQLite database is closed`);
|
|
40
|
+
}
|
|
41
|
+
const nativeResultSets = await ExpoSQLite.exec(this._name, queries.map(_serializeQuery), readOnly);
|
|
42
|
+
return nativeResultSets.map(_deserializeResultSet);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* @deprecated Use `closeAsync()` instead.
|
|
46
|
+
*/
|
|
47
|
+
close = this.closeAsync;
|
|
48
|
+
/**
|
|
49
|
+
* Close the database.
|
|
50
|
+
*/
|
|
51
|
+
closeAsync() {
|
|
31
52
|
this._closed = true;
|
|
32
53
|
return ExpoSQLite.close(this._name);
|
|
33
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Synchronously closes the database.
|
|
57
|
+
*/
|
|
58
|
+
closeSync() {
|
|
59
|
+
this._closed = true;
|
|
60
|
+
return ExpoSQLite.closeSync(this._name);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Delete the database file.
|
|
64
|
+
* > The database has to be closed prior to deletion.
|
|
65
|
+
*/
|
|
34
66
|
deleteAsync() {
|
|
35
67
|
if (!this._closed) {
|
|
36
68
|
throw new Error(`Unable to delete '${this._name}' database that is currently open. Close it prior to deletion.`);
|
|
37
69
|
}
|
|
38
70
|
return ExpoSQLite.deleteAsync(this._name);
|
|
39
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Creates a new transaction with Promise support.
|
|
74
|
+
* @param asyncCallback A `SQLTransactionAsyncCallback` function that can perform SQL statements in a transaction.
|
|
75
|
+
* @param readOnly true if all the SQL statements in the callback are read only.
|
|
76
|
+
*/
|
|
77
|
+
async transactionAsync(asyncCallback, readOnly = false) {
|
|
78
|
+
await this.execAsync([{ sql: 'BEGIN;', args: [] }], false);
|
|
79
|
+
try {
|
|
80
|
+
const transaction = new ExpoSQLTransactionAsync(this, readOnly);
|
|
81
|
+
await asyncCallback(transaction);
|
|
82
|
+
await this.execAsync([{ sql: 'END;', args: [] }], false);
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
await this.execAsync([{ sql: 'ROLLBACK;', args: [] }], false);
|
|
86
|
+
throw e;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// @ts-expect-error: properties that are added from websql
|
|
90
|
+
version;
|
|
40
91
|
}
|
|
41
92
|
function _serializeQuery(query) {
|
|
42
|
-
return
|
|
93
|
+
return Platform.OS === 'android'
|
|
94
|
+
? {
|
|
95
|
+
sql: query.sql,
|
|
96
|
+
args: query.args.map(_escapeBlob),
|
|
97
|
+
}
|
|
98
|
+
: [query.sql, query.args];
|
|
43
99
|
}
|
|
44
100
|
function _deserializeResultSet(nativeResult) {
|
|
45
101
|
const [errorMessage, insertId, rowsAffected, columns, rows] = nativeResult;
|
|
@@ -88,8 +144,27 @@ export function openDatabase(name, version = '1.0', description = name, size = 1
|
|
|
88
144
|
}
|
|
89
145
|
const db = _openExpoSQLiteDatabase(name, version, description, size, callback);
|
|
90
146
|
db.exec = db._db.exec.bind(db._db);
|
|
91
|
-
db.
|
|
147
|
+
db.execAsync = db._db.execAsync.bind(db._db);
|
|
148
|
+
db.closeAsync = db._db.closeAsync.bind(db._db);
|
|
149
|
+
db.closeSync = db._db.closeSync.bind(db._db);
|
|
92
150
|
db.deleteAsync = db._db.deleteAsync.bind(db._db);
|
|
151
|
+
db.transactionAsync = db._db.transactionAsync.bind(db._db);
|
|
93
152
|
return db;
|
|
94
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Internal data structure for the async transaction API.
|
|
156
|
+
* @internal
|
|
157
|
+
*/
|
|
158
|
+
export class ExpoSQLTransactionAsync {
|
|
159
|
+
db;
|
|
160
|
+
readOnly;
|
|
161
|
+
constructor(db, readOnly) {
|
|
162
|
+
this.db = db;
|
|
163
|
+
this.readOnly = readOnly;
|
|
164
|
+
}
|
|
165
|
+
async executeSqlAsync(sqlStatement, args) {
|
|
166
|
+
const resultSets = await this.db.execAsync([{ sql: sqlStatement, args: args ?? [] }], this.readOnly);
|
|
167
|
+
return resultSets[0];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
95
170
|
//# sourceMappingURL=SQLite.js.map
|
package/build/SQLite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SQLite.js","sourceRoot":"","sources":["../src/SQLite.ts"],"names":[],"mappings":"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","sourcesContent":["import './polyfillNextTick';\n\nimport customOpenDatabase from '@expo/websql/custom';\nimport { requireNativeModule } from 'expo-modules-core';\nimport { Platform } from 'react-native';\n\nimport { Query, ResultSet, ResultSetError, SQLiteCallback, WebSQLDatabase } from './SQLite.types';\n\nconst ExpoSQLite = requireNativeModule('ExpoSQLite');\n\nfunction zipObject(keys: string[], values: any[]) {\n const result = {};\n for (let i = 0; i < keys.length; i++) {\n result[keys[i]] = values[i];\n }\n return result;\n}\n\nclass SQLiteDatabase {\n _name: string;\n _closed: boolean = false;\n\n constructor(name: string) {\n this._name = name;\n }\n\n exec(queries: Query[], readOnly: boolean, callback: SQLiteCallback): void {\n if (this._closed) {\n throw new Error(`The SQLite database is closed`);\n }\n\n ExpoSQLite.exec(this._name, queries.map(_serializeQuery), readOnly).then(\n (nativeResultSets) => {\n callback(null, nativeResultSets.map(_deserializeResultSet));\n },\n (error) => {\n // TODO: make the native API consistently reject with an error, not a string or other type\n callback(error instanceof Error ? error : new Error(error));\n }\n );\n }\n\n close() {\n this._closed = true;\n return ExpoSQLite.close(this._name);\n }\n\n deleteAsync(): Promise<void> {\n if (!this._closed) {\n throw new Error(\n `Unable to delete '${this._name}' database that is currently open. Close it prior to deletion.`\n );\n }\n\n return ExpoSQLite.deleteAsync(this._name);\n }\n}\n\nfunction _serializeQuery(query: Query): [string, unknown[]] {\n return [query.sql, Platform.OS === 'android' ? query.args.map(_escapeBlob) : query.args];\n}\n\nfunction _deserializeResultSet(nativeResult): ResultSet | ResultSetError {\n const [errorMessage, insertId, rowsAffected, columns, rows] = nativeResult;\n // TODO: send more structured error information from the native module so we can better construct\n // a SQLException object\n if (errorMessage !== null) {\n return { error: new Error(errorMessage) } as ResultSetError;\n }\n\n return {\n insertId,\n rowsAffected,\n rows: rows.map((row) => zipObject(columns, row)),\n };\n}\n\nfunction _escapeBlob<T>(data: T): T {\n if (typeof data === 'string') {\n /* eslint-disable no-control-regex */\n return data\n .replace(/\\u0002/g, '\\u0002\\u0002')\n .replace(/\\u0001/g, '\\u0001\\u0002')\n .replace(/\\u0000/g, '\\u0001\\u0001') as any;\n /* eslint-enable no-control-regex */\n } else {\n return data;\n }\n}\n\nconst _openExpoSQLiteDatabase = customOpenDatabase(SQLiteDatabase);\n\n// @needsAudit @docsMissing\n/**\n * Open a database, creating it if it doesn't exist, and return a `Database` object. On disk,\n * the database will be created under the app's [documents directory](./filesystem), i.e.\n * `${FileSystem.documentDirectory}/SQLite/${name}`.\n * > The `version`, `description` and `size` arguments are ignored, but are accepted by the function\n * for compatibility with the WebSQL specification.\n * @param name Name of the database file to open.\n * @param version\n * @param description\n * @param size\n * @param callback\n * @return\n */\nexport function openDatabase(\n name: string,\n version: string = '1.0',\n description: string = name,\n size: number = 1,\n callback?: (db: WebSQLDatabase) => void\n): WebSQLDatabase {\n if (name === undefined) {\n throw new TypeError(`The database name must not be undefined`);\n }\n const db = _openExpoSQLiteDatabase(name, version, description, size, callback);\n db.exec = db._db.exec.bind(db._db);\n db.closeAsync = db._db.close.bind(db._db);\n db.deleteAsync = db._db.deleteAsync.bind(db._db);\n return db;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SQLite.js","sourceRoot":"","sources":["../src/SQLite.ts"],"names":[],"mappings":"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","sourcesContent":["import './polyfillNextTick';\n\nimport customOpenDatabase from '@expo/websql/custom';\nimport { requireNativeModule } from 'expo-modules-core';\nimport { Platform } from 'react-native';\n\nimport type {\n Query,\n ResultSet,\n ResultSetError,\n SQLiteCallback,\n SQLTransactionAsyncCallback,\n SQLTransactionAsync,\n SQLTransactionCallback,\n SQLTransactionErrorCallback,\n} from './SQLite.types';\n\nconst ExpoSQLite = requireNativeModule('ExpoSQLite');\n\nfunction zipObject(keys: string[], values: any[]) {\n const result = {};\n for (let i = 0; i < keys.length; i++) {\n result[keys[i]] = values[i];\n }\n return result;\n}\n\n/** The database returned by `openDatabase()` */\nexport class SQLiteDatabase {\n _name: string;\n _closed: boolean = false;\n\n constructor(name: string) {\n this._name = name;\n }\n\n /**\n * Executes the SQL statement and returns a callback resolving with the result.\n */\n exec(queries: Query[], readOnly: boolean, callback: SQLiteCallback): void {\n if (this._closed) {\n throw new Error(`The SQLite database is closed`);\n }\n\n ExpoSQLite.exec(this._name, queries.map(_serializeQuery), readOnly).then(\n (nativeResultSets) => {\n callback(null, nativeResultSets.map(_deserializeResultSet));\n },\n (error) => {\n // TODO: make the native API consistently reject with an error, not a string or other type\n callback(error instanceof Error ? error : new Error(error));\n }\n );\n }\n\n /**\n * Executes the SQL statement and returns a Promise resolving with the result.\n */\n async execAsync(queries: Query[], readOnly: boolean): Promise<(ResultSetError | ResultSet)[]> {\n if (this._closed) {\n throw new Error(`The SQLite database is closed`);\n }\n\n const nativeResultSets = await ExpoSQLite.exec(\n this._name,\n queries.map(_serializeQuery),\n readOnly\n );\n return nativeResultSets.map(_deserializeResultSet);\n }\n\n /**\n * @deprecated Use `closeAsync()` instead.\n */\n close = this.closeAsync;\n\n /**\n * Close the database.\n */\n closeAsync(): Promise<void> {\n this._closed = true;\n return ExpoSQLite.close(this._name);\n }\n\n /**\n * Synchronously closes the database.\n */\n closeSync(): void {\n this._closed = true;\n return ExpoSQLite.closeSync(this._name);\n }\n\n /**\n * Delete the database file.\n * > The database has to be closed prior to deletion.\n */\n deleteAsync(): Promise<void> {\n if (!this._closed) {\n throw new Error(\n `Unable to delete '${this._name}' database that is currently open. Close it prior to deletion.`\n );\n }\n\n return ExpoSQLite.deleteAsync(this._name);\n }\n\n /**\n * Creates a new transaction with Promise support.\n * @param asyncCallback A `SQLTransactionAsyncCallback` function that can perform SQL statements in a transaction.\n * @param readOnly true if all the SQL statements in the callback are read only.\n */\n async transactionAsync(\n asyncCallback: SQLTransactionAsyncCallback,\n readOnly: boolean = false\n ): Promise<void> {\n await this.execAsync([{ sql: 'BEGIN;', args: [] }], false);\n try {\n const transaction = new ExpoSQLTransactionAsync(this, readOnly);\n await asyncCallback(transaction);\n await this.execAsync([{ sql: 'END;', args: [] }], false);\n } catch (e: unknown) {\n await this.execAsync([{ sql: 'ROLLBACK;', args: [] }], false);\n throw e;\n }\n }\n\n // @ts-expect-error: properties that are added from websql\n version: string;\n\n /**\n * Execute a database transaction.\n * @param callback A function representing the transaction to perform. Takes a Transaction\n * (see below) as its only parameter, on which it can add SQL statements to execute.\n * @param errorCallback Called if an error occurred processing this transaction. Takes a single\n * parameter describing the error.\n * @param successCallback Called when the transaction has completed executing on the database.\n */\n // @ts-expect-error: properties that are added from websql\n transaction(\n callback: SQLTransactionCallback,\n errorCallback?: SQLTransactionErrorCallback,\n successCallback?: () => void\n ): void;\n\n // @ts-expect-error: properties that are added from websql\n readTransaction(\n callback: SQLTransactionCallback,\n errorCallback?: SQLTransactionErrorCallback,\n successCallback?: () => void\n ): void;\n}\n\nfunction _serializeQuery(query: Query): Query | [string, any[]] {\n return Platform.OS === 'android'\n ? {\n sql: query.sql,\n args: query.args.map(_escapeBlob),\n }\n : [query.sql, query.args];\n}\n\nfunction _deserializeResultSet(nativeResult): ResultSet | ResultSetError {\n const [errorMessage, insertId, rowsAffected, columns, rows] = nativeResult;\n // TODO: send more structured error information from the native module so we can better construct\n // a SQLException object\n if (errorMessage !== null) {\n return { error: new Error(errorMessage) } as ResultSetError;\n }\n\n return {\n insertId,\n rowsAffected,\n rows: rows.map((row) => zipObject(columns, row)),\n };\n}\n\nfunction _escapeBlob<T>(data: T): T {\n if (typeof data === 'string') {\n /* eslint-disable no-control-regex */\n return data\n .replace(/\\u0002/g, '\\u0002\\u0002')\n .replace(/\\u0001/g, '\\u0001\\u0002')\n .replace(/\\u0000/g, '\\u0001\\u0001') as any;\n /* eslint-enable no-control-regex */\n } else {\n return data;\n }\n}\n\nconst _openExpoSQLiteDatabase = customOpenDatabase(SQLiteDatabase);\n\n// @needsAudit @docsMissing\n/**\n * Open a database, creating it if it doesn't exist, and return a `Database` object. On disk,\n * the database will be created under the app's [documents directory](./filesystem), i.e.\n * `${FileSystem.documentDirectory}/SQLite/${name}`.\n * > The `version`, `description` and `size` arguments are ignored, but are accepted by the function\n * for compatibility with the WebSQL specification.\n * @param name Name of the database file to open.\n * @param version\n * @param description\n * @param size\n * @param callback\n * @return\n */\nexport function openDatabase(\n name: string,\n version: string = '1.0',\n description: string = name,\n size: number = 1,\n callback?: (db: SQLiteDatabase) => void\n): SQLiteDatabase {\n if (name === undefined) {\n throw new TypeError(`The database name must not be undefined`);\n }\n const db = _openExpoSQLiteDatabase(name, version, description, size, callback);\n db.exec = db._db.exec.bind(db._db);\n db.execAsync = db._db.execAsync.bind(db._db);\n db.closeAsync = db._db.closeAsync.bind(db._db);\n db.closeSync = db._db.closeSync.bind(db._db);\n db.deleteAsync = db._db.deleteAsync.bind(db._db);\n db.transactionAsync = db._db.transactionAsync.bind(db._db);\n return db;\n}\n\n/**\n * Internal data structure for the async transaction API.\n * @internal\n */\nexport class ExpoSQLTransactionAsync implements SQLTransactionAsync {\n constructor(private readonly db: SQLiteDatabase, private readonly readOnly: boolean) {}\n\n async executeSqlAsync(\n sqlStatement: string,\n args?: (number | string)[]\n ): Promise<ResultSetError | ResultSet> {\n const resultSets = await this.db.execAsync(\n [{ sql: sqlStatement, args: args ?? [] }],\n this.readOnly\n );\n return resultSets[0];\n }\n}\n"]}
|
package/build/SQLite.types.d.ts
CHANGED
|
@@ -84,6 +84,7 @@ export declare class SQLError {
|
|
|
84
84
|
code: number;
|
|
85
85
|
message: string;
|
|
86
86
|
}
|
|
87
|
+
/** @deprecated Use `SQLiteDatabase` instead. */
|
|
87
88
|
export interface WebSQLDatabase extends Database {
|
|
88
89
|
exec(queries: Query[], readOnly: boolean, callback: SQLiteCallback): void;
|
|
89
90
|
/**
|
|
@@ -100,14 +101,14 @@ export type Query = {
|
|
|
100
101
|
sql: string;
|
|
101
102
|
args: unknown[];
|
|
102
103
|
};
|
|
103
|
-
export
|
|
104
|
+
export interface ResultSetError {
|
|
104
105
|
error: Error;
|
|
105
|
-
}
|
|
106
|
+
}
|
|
106
107
|
/**
|
|
107
108
|
* `ResultSet` objects are returned through second parameter of the `success` callback for the
|
|
108
109
|
* `tx.executeSql()` method on a `SQLTransaction` (see above).
|
|
109
110
|
*/
|
|
110
|
-
export
|
|
111
|
+
export interface ResultSet {
|
|
111
112
|
/**
|
|
112
113
|
* The row ID of the row that the SQL statement inserted into the database, if a row was inserted.
|
|
113
114
|
*/
|
|
@@ -119,6 +120,13 @@ export type ResultSet = {
|
|
|
119
120
|
rows: {
|
|
120
121
|
[column: string]: any;
|
|
121
122
|
}[];
|
|
122
|
-
}
|
|
123
|
+
}
|
|
123
124
|
export type SQLiteCallback = (error?: Error | null, resultSet?: (ResultSetError | ResultSet)[]) => void;
|
|
125
|
+
/** A transaction object to perform SQL statements in async mode. */
|
|
126
|
+
export interface SQLTransactionAsync {
|
|
127
|
+
/** Executes a SQL statement in async mode. */
|
|
128
|
+
executeSqlAsync(sqlStatement: string, args?: (number | string)[]): Promise<ResultSetError | ResultSet>;
|
|
129
|
+
}
|
|
130
|
+
/** A transaction callback with given `SQLTransactionAsync` object to perform SQL statements in async mode. */
|
|
131
|
+
export type SQLTransactionAsyncCallback = (transaction: SQLTransactionAsync) => Promise<void>;
|
|
124
132
|
//# sourceMappingURL=SQLite.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SQLite.types.d.ts","sourceRoot":"","sources":["../src/SQLite.types.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,MAAM;IACrB,YAAY,CAAC,EAAE,CACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,gBAAgB,CAAC,EAAE,gBAAgB,KAChC,QAAQ,CAAC;CACf;AAGD,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;AAG5D;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;;;OAOG;IACH,WAAW,CACT,QAAQ,EAAE,sBAAsB,EAChC,aAAa,CAAC,EAAE,2BAA2B,EAC3C,eAAe,CAAC,EAAE,MAAM,IAAI,GAC3B,IAAI,CAAC;IAER,eAAe,CACb,QAAQ,EAAE,sBAAsB,EAChC,aAAa,CAAC,EAAE,2BAA2B,EAC3C,eAAe,CAAC,EAAE,MAAM,IAAI,GAC3B,IAAI,CAAC;CACT;AAGD,MAAM,MAAM,sBAAsB,GAAG,CAAC,WAAW,EAAE,cAAc,KAAK,IAAI,CAAC;AAG3E,MAAM,MAAM,2BAA2B,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;AAGpE;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;;;;OAaG;IACH,UAAU,CACR,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,EACjC,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,aAAa,CAAC,EAAE,yBAAyB,GACxC,IAAI,CAAC;CACT;AAGD,MAAM,MAAM,oBAAoB,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,KAAK,IAAI,CAAC;AAGlG,MAAM,MAAM,yBAAyB,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC;AAGlG,MAAM,MAAM,YAAY,GAAG;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,mBAAmB,CAAC;CAC3B,CAAC;AAGF,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC;IACzB;;;OAGG;IACH,MAAM,EAAE,GAAG,EAAE,CAAC;CACf;AAGD,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC3B,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC;IAC9B,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC;IAE3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"SQLite.types.d.ts","sourceRoot":"","sources":["../src/SQLite.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SQLite.types.js","sourceRoot":"","sources":["../src/SQLite.types.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,8CAA8C;AAC9C,gDAAgD;AAChD,2DAA2D;AAC3D,EAAE;AACF,0EAA0E","sourcesContent":["// Definitions copied from `@types/websql` as we want\n// to expose a custom version of the API that:\n// - uses primitive `string` instead of `String`\n// - excludes some methods that are not exposed by our API.\n//\n// Original definitions by: TeamworkGuy2 <https://github.com/TeamworkGuy2>\n\n// @docsMissing\nexport interface Window {\n openDatabase?: (\n name: string,\n version: string,\n displayName: string,\n estimatedSize: number,\n creationCallback?: DatabaseCallback\n ) => Database;\n}\n\n// @docsMissing\nexport type DatabaseCallback = (database: Database) => void;\n\n// @needsAudit @docsMissing\n/**\n * `Database` objects are returned by calls to `SQLite.openDatabase()`. Such an object represents a\n * connection to a database on your device.\n */\nexport interface Database {\n version: string;\n\n /**\n * Execute a database transaction.\n * @param callback A function representing the transaction to perform. Takes a Transaction\n * (see below) as its only parameter, on which it can add SQL statements to execute.\n * @param errorCallback Called if an error occurred processing this transaction. Takes a single\n * parameter describing the error.\n * @param successCallback Called when the transaction has completed executing on the database.\n */\n transaction(\n callback: SQLTransactionCallback,\n errorCallback?: SQLTransactionErrorCallback,\n successCallback?: () => void\n ): void;\n\n readTransaction(\n callback: SQLTransactionCallback,\n errorCallback?: SQLTransactionErrorCallback,\n successCallback?: () => void\n ): void;\n}\n\n// @docsMissing\nexport type SQLTransactionCallback = (transaction: SQLTransaction) => void;\n\n// @docsMissing\nexport type SQLTransactionErrorCallback = (error: SQLError) => void;\n\n// @needsAudit\n/**\n * A `SQLTransaction` object is passed in as a parameter to the `callback` parameter for the\n * `db.transaction()` method on a `Database` (see above). It allows enqueuing SQL statements to\n * perform in a database transaction.\n */\nexport interface SQLTransaction {\n /**\n * Enqueue a SQL statement to execute in the transaction. Authors are strongly recommended to make\n * use of the `?` placeholder feature of the method to avoid against SQL injection attacks, and to\n * never construct SQL statements on the fly.\n * @param sqlStatement A string containing a database query to execute expressed as SQL. The string\n * may contain `?` placeholders, with values to be substituted listed in the `arguments` parameter.\n * @param args An array of values (numbers, strings or nulls) to substitute for `?` placeholders in the\n * SQL statement.\n * @param callback Called when the query is successfully completed during the transaction. Takes\n * two parameters: the transaction itself, and a `ResultSet` object (see below) with the results\n * of the query.\n * @param errorCallback Called if an error occurred executing this particular query in the\n * transaction. Takes two parameters: the transaction itself, and the error object.\n */\n executeSql(\n sqlStatement: string,\n args?: (number | string | null)[],\n callback?: SQLStatementCallback,\n errorCallback?: SQLStatementErrorCallback\n ): void;\n}\n\n// @docsMissing\nexport type SQLStatementCallback = (transaction: SQLTransaction, resultSet: SQLResultSet) => void;\n\n// @docsMissing\nexport type SQLStatementErrorCallback = (transaction: SQLTransaction, error: SQLError) => boolean;\n\n// @needsAudit\nexport type SQLResultSet = {\n /**\n * The row ID of the row that the SQL statement inserted into the database, if a row was inserted.\n */\n insertId?: number;\n /**\n * The number of rows that were changed by the SQL statement.\n */\n rowsAffected: number;\n rows: SQLResultSetRowList;\n};\n\n// @needsAudit\nexport interface SQLResultSetRowList {\n /**\n * The number of rows returned by the query.\n */\n length: number;\n /**\n * Returns the row with the given `index`. If there is no such row, returns `null`.\n * @param index Index of row to get.\n */\n item(index: number): any;\n /**\n * The actual array of rows returned by the query. Can be used directly instead of\n * getting rows through rows.item().\n */\n _array: any[];\n}\n\n// @docsMissing\nexport declare class SQLError {\n static UNKNOWN_ERR: number;\n static DATABASE_ERR: number;\n static VERSION_ERR: number;\n static TOO_LARGE_ERR: number;\n static QUOTA_ERR: number;\n static SYNTAX_ERR: number;\n static CONSTRAINT_ERR: number;\n static TIMEOUT_ERR: number;\n\n code: number;\n message: string;\n}\n\n
|
|
1
|
+
{"version":3,"file":"SQLite.types.js","sourceRoot":"","sources":["../src/SQLite.types.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,8CAA8C;AAC9C,gDAAgD;AAChD,2DAA2D;AAC3D,EAAE;AACF,0EAA0E","sourcesContent":["// Definitions copied from `@types/websql` as we want\n// to expose a custom version of the API that:\n// - uses primitive `string` instead of `String`\n// - excludes some methods that are not exposed by our API.\n//\n// Original definitions by: TeamworkGuy2 <https://github.com/TeamworkGuy2>\n\n// @docsMissing\nexport interface Window {\n openDatabase?: (\n name: string,\n version: string,\n displayName: string,\n estimatedSize: number,\n creationCallback?: DatabaseCallback\n ) => Database;\n}\n\n// @docsMissing\nexport type DatabaseCallback = (database: Database) => void;\n\n// @needsAudit @docsMissing\n/**\n * `Database` objects are returned by calls to `SQLite.openDatabase()`. Such an object represents a\n * connection to a database on your device.\n */\nexport interface Database {\n version: string;\n\n /**\n * Execute a database transaction.\n * @param callback A function representing the transaction to perform. Takes a Transaction\n * (see below) as its only parameter, on which it can add SQL statements to execute.\n * @param errorCallback Called if an error occurred processing this transaction. Takes a single\n * parameter describing the error.\n * @param successCallback Called when the transaction has completed executing on the database.\n */\n transaction(\n callback: SQLTransactionCallback,\n errorCallback?: SQLTransactionErrorCallback,\n successCallback?: () => void\n ): void;\n\n readTransaction(\n callback: SQLTransactionCallback,\n errorCallback?: SQLTransactionErrorCallback,\n successCallback?: () => void\n ): void;\n}\n\n// @docsMissing\nexport type SQLTransactionCallback = (transaction: SQLTransaction) => void;\n\n// @docsMissing\nexport type SQLTransactionErrorCallback = (error: SQLError) => void;\n\n// @needsAudit\n/**\n * A `SQLTransaction` object is passed in as a parameter to the `callback` parameter for the\n * `db.transaction()` method on a `Database` (see above). It allows enqueuing SQL statements to\n * perform in a database transaction.\n */\nexport interface SQLTransaction {\n /**\n * Enqueue a SQL statement to execute in the transaction. Authors are strongly recommended to make\n * use of the `?` placeholder feature of the method to avoid against SQL injection attacks, and to\n * never construct SQL statements on the fly.\n * @param sqlStatement A string containing a database query to execute expressed as SQL. The string\n * may contain `?` placeholders, with values to be substituted listed in the `arguments` parameter.\n * @param args An array of values (numbers, strings or nulls) to substitute for `?` placeholders in the\n * SQL statement.\n * @param callback Called when the query is successfully completed during the transaction. Takes\n * two parameters: the transaction itself, and a `ResultSet` object (see below) with the results\n * of the query.\n * @param errorCallback Called if an error occurred executing this particular query in the\n * transaction. Takes two parameters: the transaction itself, and the error object.\n */\n executeSql(\n sqlStatement: string,\n args?: (number | string | null)[],\n callback?: SQLStatementCallback,\n errorCallback?: SQLStatementErrorCallback\n ): void;\n}\n\n// @docsMissing\nexport type SQLStatementCallback = (transaction: SQLTransaction, resultSet: SQLResultSet) => void;\n\n// @docsMissing\nexport type SQLStatementErrorCallback = (transaction: SQLTransaction, error: SQLError) => boolean;\n\n// @needsAudit\nexport type SQLResultSet = {\n /**\n * The row ID of the row that the SQL statement inserted into the database, if a row was inserted.\n */\n insertId?: number;\n /**\n * The number of rows that were changed by the SQL statement.\n */\n rowsAffected: number;\n rows: SQLResultSetRowList;\n};\n\n// @needsAudit\nexport interface SQLResultSetRowList {\n /**\n * The number of rows returned by the query.\n */\n length: number;\n /**\n * Returns the row with the given `index`. If there is no such row, returns `null`.\n * @param index Index of row to get.\n */\n item(index: number): any;\n /**\n * The actual array of rows returned by the query. Can be used directly instead of\n * getting rows through rows.item().\n */\n _array: any[];\n}\n\n// @docsMissing\nexport declare class SQLError {\n static UNKNOWN_ERR: number;\n static DATABASE_ERR: number;\n static VERSION_ERR: number;\n static TOO_LARGE_ERR: number;\n static QUOTA_ERR: number;\n static SYNTAX_ERR: number;\n static CONSTRAINT_ERR: number;\n static TIMEOUT_ERR: number;\n\n code: number;\n message: string;\n}\n\n/** @deprecated Use `SQLiteDatabase` instead. */\nexport interface WebSQLDatabase extends Database {\n exec(queries: Query[], readOnly: boolean, callback: SQLiteCallback): void;\n\n /**\n * Close the database.\n */\n closeAsync(): void;\n\n /**\n * Delete the database file.\n * > The database has to be closed prior to deletion.\n */\n deleteAsync(): Promise<void>;\n}\n\n// @docsMissing\nexport type Query = { sql: string; args: unknown[] };\n\n// @docsMissing\nexport interface ResultSetError {\n error: Error;\n}\n\n// @needsAudit\n/**\n * `ResultSet` objects are returned through second parameter of the `success` callback for the\n * `tx.executeSql()` method on a `SQLTransaction` (see above).\n */\nexport interface ResultSet {\n /**\n * The row ID of the row that the SQL statement inserted into the database, if a row was inserted.\n */\n insertId?: number;\n /**\n * The number of rows that were changed by the SQL statement.\n */\n rowsAffected: number;\n rows: { [column: string]: any }[];\n}\n\n// @docsMissing\nexport type SQLiteCallback = (\n error?: Error | null,\n resultSet?: (ResultSetError | ResultSet)[]\n) => void;\n\n/** A transaction object to perform SQL statements in async mode. */\nexport interface SQLTransactionAsync {\n /** Executes a SQL statement in async mode. */\n executeSqlAsync(\n sqlStatement: string,\n args?: (number | string)[]\n ): Promise<ResultSetError | ResultSet>;\n}\n\n/** A transaction callback with given `SQLTransactionAsync` object to perform SQL statements in async mode. */\nexport type SQLTransactionAsyncCallback = (transaction: SQLTransactionAsync) => Promise<void>;\n"]}
|
package/expo-module.config.json
CHANGED
package/ios/SQLiteModule.swift
CHANGED
|
@@ -31,6 +31,10 @@ public final class SQLiteModule: Module {
|
|
|
31
31
|
cachedDatabases.removeValue(forKey: dbName)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
Function("closeSync") { (dbName: String) in
|
|
35
|
+
cachedDatabases.removeValue(forKey: dbName)
|
|
36
|
+
}
|
|
37
|
+
|
|
34
38
|
AsyncFunction("deleteAsync") { (dbName: String) in
|
|
35
39
|
if cachedDatabases[dbName] != nil {
|
|
36
40
|
throw DeleteDatabaseException(dbName)
|
|
@@ -184,7 +188,7 @@ public final class SQLiteModule: Module {
|
|
|
184
188
|
}
|
|
185
189
|
|
|
186
190
|
let SQLITE_TRANSIENT = unsafeBitCast(OpaquePointer(bitPattern: -1), to: sqlite3_destructor_type.self)
|
|
187
|
-
|
|
191
|
+
|
|
188
192
|
let data = stringArg.data(using: NSUTF8StringEncoding)
|
|
189
193
|
sqlite3_bind_text(statement, index, stringArg.utf8String, Int32(data?.count ?? 0), SQLITE_TRANSIENT)
|
|
190
194
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-sqlite",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.4.0",
|
|
4
4
|
"description": "Provides access to a database that can be queried through a WebSQL-like API (https://www.w3.org/TR/webdatabase/). The database is persisted across restarts of your app.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"expo": "*"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "663654577a7068c641b5e9474efbc502e3f334ea"
|
|
48
48
|
}
|
package/src/SQLite.ts
CHANGED
|
@@ -4,7 +4,16 @@ import customOpenDatabase from '@expo/websql/custom';
|
|
|
4
4
|
import { requireNativeModule } from 'expo-modules-core';
|
|
5
5
|
import { Platform } from 'react-native';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import type {
|
|
8
|
+
Query,
|
|
9
|
+
ResultSet,
|
|
10
|
+
ResultSetError,
|
|
11
|
+
SQLiteCallback,
|
|
12
|
+
SQLTransactionAsyncCallback,
|
|
13
|
+
SQLTransactionAsync,
|
|
14
|
+
SQLTransactionCallback,
|
|
15
|
+
SQLTransactionErrorCallback,
|
|
16
|
+
} from './SQLite.types';
|
|
8
17
|
|
|
9
18
|
const ExpoSQLite = requireNativeModule('ExpoSQLite');
|
|
10
19
|
|
|
@@ -16,7 +25,8 @@ function zipObject(keys: string[], values: any[]) {
|
|
|
16
25
|
return result;
|
|
17
26
|
}
|
|
18
27
|
|
|
19
|
-
|
|
28
|
+
/** The database returned by `openDatabase()` */
|
|
29
|
+
export class SQLiteDatabase {
|
|
20
30
|
_name: string;
|
|
21
31
|
_closed: boolean = false;
|
|
22
32
|
|
|
@@ -24,6 +34,9 @@ class SQLiteDatabase {
|
|
|
24
34
|
this._name = name;
|
|
25
35
|
}
|
|
26
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Executes the SQL statement and returns a callback resolving with the result.
|
|
39
|
+
*/
|
|
27
40
|
exec(queries: Query[], readOnly: boolean, callback: SQLiteCallback): void {
|
|
28
41
|
if (this._closed) {
|
|
29
42
|
throw new Error(`The SQLite database is closed`);
|
|
@@ -40,11 +53,47 @@ class SQLiteDatabase {
|
|
|
40
53
|
);
|
|
41
54
|
}
|
|
42
55
|
|
|
43
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Executes the SQL statement and returns a Promise resolving with the result.
|
|
58
|
+
*/
|
|
59
|
+
async execAsync(queries: Query[], readOnly: boolean): Promise<(ResultSetError | ResultSet)[]> {
|
|
60
|
+
if (this._closed) {
|
|
61
|
+
throw new Error(`The SQLite database is closed`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const nativeResultSets = await ExpoSQLite.exec(
|
|
65
|
+
this._name,
|
|
66
|
+
queries.map(_serializeQuery),
|
|
67
|
+
readOnly
|
|
68
|
+
);
|
|
69
|
+
return nativeResultSets.map(_deserializeResultSet);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @deprecated Use `closeAsync()` instead.
|
|
74
|
+
*/
|
|
75
|
+
close = this.closeAsync;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Close the database.
|
|
79
|
+
*/
|
|
80
|
+
closeAsync(): Promise<void> {
|
|
44
81
|
this._closed = true;
|
|
45
82
|
return ExpoSQLite.close(this._name);
|
|
46
83
|
}
|
|
47
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Synchronously closes the database.
|
|
87
|
+
*/
|
|
88
|
+
closeSync(): void {
|
|
89
|
+
this._closed = true;
|
|
90
|
+
return ExpoSQLite.closeSync(this._name);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Delete the database file.
|
|
95
|
+
* > The database has to be closed prior to deletion.
|
|
96
|
+
*/
|
|
48
97
|
deleteAsync(): Promise<void> {
|
|
49
98
|
if (!this._closed) {
|
|
50
99
|
throw new Error(
|
|
@@ -54,10 +103,60 @@ class SQLiteDatabase {
|
|
|
54
103
|
|
|
55
104
|
return ExpoSQLite.deleteAsync(this._name);
|
|
56
105
|
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Creates a new transaction with Promise support.
|
|
109
|
+
* @param asyncCallback A `SQLTransactionAsyncCallback` function that can perform SQL statements in a transaction.
|
|
110
|
+
* @param readOnly true if all the SQL statements in the callback are read only.
|
|
111
|
+
*/
|
|
112
|
+
async transactionAsync(
|
|
113
|
+
asyncCallback: SQLTransactionAsyncCallback,
|
|
114
|
+
readOnly: boolean = false
|
|
115
|
+
): Promise<void> {
|
|
116
|
+
await this.execAsync([{ sql: 'BEGIN;', args: [] }], false);
|
|
117
|
+
try {
|
|
118
|
+
const transaction = new ExpoSQLTransactionAsync(this, readOnly);
|
|
119
|
+
await asyncCallback(transaction);
|
|
120
|
+
await this.execAsync([{ sql: 'END;', args: [] }], false);
|
|
121
|
+
} catch (e: unknown) {
|
|
122
|
+
await this.execAsync([{ sql: 'ROLLBACK;', args: [] }], false);
|
|
123
|
+
throw e;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// @ts-expect-error: properties that are added from websql
|
|
128
|
+
version: string;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Execute a database transaction.
|
|
132
|
+
* @param callback A function representing the transaction to perform. Takes a Transaction
|
|
133
|
+
* (see below) as its only parameter, on which it can add SQL statements to execute.
|
|
134
|
+
* @param errorCallback Called if an error occurred processing this transaction. Takes a single
|
|
135
|
+
* parameter describing the error.
|
|
136
|
+
* @param successCallback Called when the transaction has completed executing on the database.
|
|
137
|
+
*/
|
|
138
|
+
// @ts-expect-error: properties that are added from websql
|
|
139
|
+
transaction(
|
|
140
|
+
callback: SQLTransactionCallback,
|
|
141
|
+
errorCallback?: SQLTransactionErrorCallback,
|
|
142
|
+
successCallback?: () => void
|
|
143
|
+
): void;
|
|
144
|
+
|
|
145
|
+
// @ts-expect-error: properties that are added from websql
|
|
146
|
+
readTransaction(
|
|
147
|
+
callback: SQLTransactionCallback,
|
|
148
|
+
errorCallback?: SQLTransactionErrorCallback,
|
|
149
|
+
successCallback?: () => void
|
|
150
|
+
): void;
|
|
57
151
|
}
|
|
58
152
|
|
|
59
|
-
function _serializeQuery(query: Query): [string,
|
|
60
|
-
return
|
|
153
|
+
function _serializeQuery(query: Query): Query | [string, any[]] {
|
|
154
|
+
return Platform.OS === 'android'
|
|
155
|
+
? {
|
|
156
|
+
sql: query.sql,
|
|
157
|
+
args: query.args.map(_escapeBlob),
|
|
158
|
+
}
|
|
159
|
+
: [query.sql, query.args];
|
|
61
160
|
}
|
|
62
161
|
|
|
63
162
|
function _deserializeResultSet(nativeResult): ResultSet | ResultSetError {
|
|
@@ -109,14 +208,36 @@ export function openDatabase(
|
|
|
109
208
|
version: string = '1.0',
|
|
110
209
|
description: string = name,
|
|
111
210
|
size: number = 1,
|
|
112
|
-
callback?: (db:
|
|
113
|
-
):
|
|
211
|
+
callback?: (db: SQLiteDatabase) => void
|
|
212
|
+
): SQLiteDatabase {
|
|
114
213
|
if (name === undefined) {
|
|
115
214
|
throw new TypeError(`The database name must not be undefined`);
|
|
116
215
|
}
|
|
117
216
|
const db = _openExpoSQLiteDatabase(name, version, description, size, callback);
|
|
118
217
|
db.exec = db._db.exec.bind(db._db);
|
|
119
|
-
db.
|
|
218
|
+
db.execAsync = db._db.execAsync.bind(db._db);
|
|
219
|
+
db.closeAsync = db._db.closeAsync.bind(db._db);
|
|
220
|
+
db.closeSync = db._db.closeSync.bind(db._db);
|
|
120
221
|
db.deleteAsync = db._db.deleteAsync.bind(db._db);
|
|
222
|
+
db.transactionAsync = db._db.transactionAsync.bind(db._db);
|
|
121
223
|
return db;
|
|
122
224
|
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Internal data structure for the async transaction API.
|
|
228
|
+
* @internal
|
|
229
|
+
*/
|
|
230
|
+
export class ExpoSQLTransactionAsync implements SQLTransactionAsync {
|
|
231
|
+
constructor(private readonly db: SQLiteDatabase, private readonly readOnly: boolean) {}
|
|
232
|
+
|
|
233
|
+
async executeSqlAsync(
|
|
234
|
+
sqlStatement: string,
|
|
235
|
+
args?: (number | string)[]
|
|
236
|
+
): Promise<ResultSetError | ResultSet> {
|
|
237
|
+
const resultSets = await this.db.execAsync(
|
|
238
|
+
[{ sql: sqlStatement, args: args ?? [] }],
|
|
239
|
+
this.readOnly
|
|
240
|
+
);
|
|
241
|
+
return resultSets[0];
|
|
242
|
+
}
|
|
243
|
+
}
|
package/src/SQLite.types.ts
CHANGED
|
@@ -135,7 +135,7 @@ export declare class SQLError {
|
|
|
135
135
|
message: string;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
/** @deprecated Use `SQLiteDatabase` instead. */
|
|
139
139
|
export interface WebSQLDatabase extends Database {
|
|
140
140
|
exec(queries: Query[], readOnly: boolean, callback: SQLiteCallback): void;
|
|
141
141
|
|
|
@@ -155,16 +155,16 @@ export interface WebSQLDatabase extends Database {
|
|
|
155
155
|
export type Query = { sql: string; args: unknown[] };
|
|
156
156
|
|
|
157
157
|
// @docsMissing
|
|
158
|
-
export
|
|
158
|
+
export interface ResultSetError {
|
|
159
159
|
error: Error;
|
|
160
|
-
}
|
|
160
|
+
}
|
|
161
161
|
|
|
162
162
|
// @needsAudit
|
|
163
163
|
/**
|
|
164
164
|
* `ResultSet` objects are returned through second parameter of the `success` callback for the
|
|
165
165
|
* `tx.executeSql()` method on a `SQLTransaction` (see above).
|
|
166
166
|
*/
|
|
167
|
-
export
|
|
167
|
+
export interface ResultSet {
|
|
168
168
|
/**
|
|
169
169
|
* The row ID of the row that the SQL statement inserted into the database, if a row was inserted.
|
|
170
170
|
*/
|
|
@@ -174,10 +174,22 @@ export type ResultSet = {
|
|
|
174
174
|
*/
|
|
175
175
|
rowsAffected: number;
|
|
176
176
|
rows: { [column: string]: any }[];
|
|
177
|
-
}
|
|
177
|
+
}
|
|
178
178
|
|
|
179
179
|
// @docsMissing
|
|
180
180
|
export type SQLiteCallback = (
|
|
181
181
|
error?: Error | null,
|
|
182
182
|
resultSet?: (ResultSetError | ResultSet)[]
|
|
183
183
|
) => void;
|
|
184
|
+
|
|
185
|
+
/** A transaction object to perform SQL statements in async mode. */
|
|
186
|
+
export interface SQLTransactionAsync {
|
|
187
|
+
/** Executes a SQL statement in async mode. */
|
|
188
|
+
executeSqlAsync(
|
|
189
|
+
sqlStatement: string,
|
|
190
|
+
args?: (number | string)[]
|
|
191
|
+
): Promise<ResultSetError | ResultSet>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** A transaction callback with given `SQLTransactionAsync` object to perform SQL statements in async mode. */
|
|
195
|
+
export type SQLTransactionAsyncCallback = (transaction: SQLTransactionAsync) => Promise<void>;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
package expo.modules.sqlite
|
|
2
|
-
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import expo.modules.core.BasePackage
|
|
5
|
-
import expo.modules.core.ExportedModule
|
|
6
|
-
|
|
7
|
-
class SQLitePackage : BasePackage() {
|
|
8
|
-
override fun createExportedModules(context: Context): List<ExportedModule> {
|
|
9
|
-
return listOf(SQLiteModule(context))
|
|
10
|
-
}
|
|
11
|
-
}
|