react-native-nitro-sqlite 9.8.1 → 10.0.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.
Files changed (145) hide show
  1. package/RNNitroSQLite.podspec +7 -3
  2. package/android/CMakeLists.txt +3 -2
  3. package/android/build.gradle +2 -0
  4. package/android/sqlite-flags.gradle +47 -0
  5. package/cpp/NitroSQLiteDatabaseConnections.cpp +306 -0
  6. package/cpp/NitroSQLiteDatabaseConnections.hpp +86 -0
  7. package/cpp/{databaseMigration.cpp → NitroSQLiteDatabaseMigration.cpp} +2 -2
  8. package/cpp/{sqliteExecuteBatch.cpp → NitroSQLiteExecuteBatch.cpp} +4 -4
  9. package/cpp/{sqliteExecuteBatch.hpp → NitroSQLiteExecuteBatch.hpp} +3 -6
  10. package/cpp/{importSqlFile.cpp → NitroSQLiteImportSqlFile.cpp} +4 -4
  11. package/cpp/{importSqlFile.hpp → NitroSQLiteImportSqlFile.hpp} +3 -3
  12. package/cpp/{macros.hpp → NitroSQLiteMacros.hpp} +3 -3
  13. package/cpp/NitroSQLiteOperations.cpp +396 -0
  14. package/cpp/NitroSQLiteOperations.hpp +72 -0
  15. package/cpp/{types.hpp → NitroSQLiteTypes.hpp} +3 -6
  16. package/cpp/{utils.hpp → NitroSQLiteUtils.hpp} +2 -2
  17. package/cpp/hybridObjects/HybridNitroSQLite.cpp +108 -22
  18. package/cpp/hybridObjects/HybridNitroSQLite.hpp +49 -5
  19. package/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.cpp +59 -0
  20. package/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.hpp +33 -0
  21. package/cpp/hybridObjects/HybridNitroSQLiteQueryResult.hpp +6 -4
  22. package/ios/OnLoad.mm +38 -2
  23. package/lib/commonjs/DatabaseQueue.js +52 -16
  24. package/lib/commonjs/DatabaseQueue.js.map +1 -1
  25. package/lib/commonjs/NitroSQLiteError.js +6 -7
  26. package/lib/commonjs/NitroSQLiteError.js.map +1 -1
  27. package/lib/commonjs/OnLoad.js +1 -1
  28. package/lib/commonjs/index.js +8 -3
  29. package/lib/commonjs/index.js.map +1 -1
  30. package/lib/commonjs/operations/execute.js +19 -4
  31. package/lib/commonjs/operations/execute.js.map +1 -1
  32. package/lib/commonjs/operations/executeBatch.js +19 -6
  33. package/lib/commonjs/operations/executeBatch.js.map +1 -1
  34. package/lib/commonjs/operations/prepare.js +54 -0
  35. package/lib/commonjs/operations/prepare.js.map +1 -0
  36. package/lib/commonjs/operations/session.js +106 -30
  37. package/lib/commonjs/operations/session.js.map +1 -1
  38. package/lib/commonjs/operations/transaction.js +30 -5
  39. package/lib/commonjs/operations/transaction.js.map +1 -1
  40. package/lib/commonjs/specs/NitroSQLitePreparedStatement.nitro.js +6 -0
  41. package/lib/commonjs/specs/NitroSQLitePreparedStatement.nitro.js.map +1 -0
  42. package/lib/commonjs/typeORM.js +10 -3
  43. package/lib/commonjs/typeORM.js.map +1 -1
  44. package/lib/commonjs/types.js +35 -9
  45. package/lib/commonjs/types.js.map +1 -1
  46. package/lib/module/DatabaseQueue.js +52 -16
  47. package/lib/module/DatabaseQueue.js.map +1 -1
  48. package/lib/module/NitroSQLiteError.js +6 -7
  49. package/lib/module/NitroSQLiteError.js.map +1 -1
  50. package/lib/module/OnLoad.js +1 -1
  51. package/lib/module/index.js +8 -3
  52. package/lib/module/index.js.map +1 -1
  53. package/lib/module/operations/execute.js +20 -5
  54. package/lib/module/operations/execute.js.map +1 -1
  55. package/lib/module/operations/executeBatch.js +20 -7
  56. package/lib/module/operations/executeBatch.js.map +1 -1
  57. package/lib/module/operations/prepare.js +49 -0
  58. package/lib/module/operations/prepare.js.map +1 -0
  59. package/lib/module/operations/session.js +107 -31
  60. package/lib/module/operations/session.js.map +1 -1
  61. package/lib/module/operations/transaction.js +30 -5
  62. package/lib/module/operations/transaction.js.map +1 -1
  63. package/lib/module/specs/NitroSQLitePreparedStatement.nitro.js +4 -0
  64. package/lib/module/specs/NitroSQLitePreparedStatement.nitro.js.map +1 -0
  65. package/lib/module/typeORM.js +11 -3
  66. package/lib/module/typeORM.js.map +1 -1
  67. package/lib/module/types.js +48 -9
  68. package/lib/module/types.js.map +1 -1
  69. package/lib/typescript/commonjs/DatabaseQueue.d.ts +15 -7
  70. package/lib/typescript/commonjs/DatabaseQueue.d.ts.map +1 -1
  71. package/lib/typescript/commonjs/NitroSQLiteError.d.ts +6 -7
  72. package/lib/typescript/commonjs/NitroSQLiteError.d.ts.map +1 -1
  73. package/lib/typescript/commonjs/index.d.ts +9 -2
  74. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  75. package/lib/typescript/commonjs/operations/execute.d.ts +17 -2
  76. package/lib/typescript/commonjs/operations/execute.d.ts.map +1 -1
  77. package/lib/typescript/commonjs/operations/executeBatch.d.ts +15 -2
  78. package/lib/typescript/commonjs/operations/executeBatch.d.ts.map +1 -1
  79. package/lib/typescript/commonjs/operations/prepare.d.ts +13 -0
  80. package/lib/typescript/commonjs/operations/prepare.d.ts.map +1 -0
  81. package/lib/typescript/commonjs/operations/session.d.ts +8 -0
  82. package/lib/typescript/commonjs/operations/session.d.ts.map +1 -1
  83. package/lib/typescript/commonjs/operations/transaction.d.ts +11 -1
  84. package/lib/typescript/commonjs/operations/transaction.d.ts.map +1 -1
  85. package/lib/typescript/commonjs/specs/NitroSQLite.nitro.d.ts +83 -2
  86. package/lib/typescript/commonjs/specs/NitroSQLite.nitro.d.ts.map +1 -1
  87. package/lib/typescript/commonjs/specs/NitroSQLitePreparedStatement.nitro.d.ts +26 -0
  88. package/lib/typescript/commonjs/specs/NitroSQLitePreparedStatement.nitro.d.ts.map +1 -0
  89. package/lib/typescript/commonjs/specs/NitroSQLiteQueryResult.nitro.d.ts +9 -15
  90. package/lib/typescript/commonjs/specs/NitroSQLiteQueryResult.nitro.d.ts.map +1 -1
  91. package/lib/typescript/commonjs/typeORM.d.ts +14 -3
  92. package/lib/typescript/commonjs/typeORM.d.ts.map +1 -1
  93. package/lib/typescript/commonjs/types.d.ts +124 -21
  94. package/lib/typescript/commonjs/types.d.ts.map +1 -1
  95. package/lib/typescript/module/DatabaseQueue.d.ts +15 -7
  96. package/lib/typescript/module/DatabaseQueue.d.ts.map +1 -1
  97. package/lib/typescript/module/NitroSQLiteError.d.ts +6 -7
  98. package/lib/typescript/module/NitroSQLiteError.d.ts.map +1 -1
  99. package/lib/typescript/module/index.d.ts +9 -2
  100. package/lib/typescript/module/index.d.ts.map +1 -1
  101. package/lib/typescript/module/operations/execute.d.ts +17 -2
  102. package/lib/typescript/module/operations/execute.d.ts.map +1 -1
  103. package/lib/typescript/module/operations/executeBatch.d.ts +15 -2
  104. package/lib/typescript/module/operations/executeBatch.d.ts.map +1 -1
  105. package/lib/typescript/module/operations/prepare.d.ts +13 -0
  106. package/lib/typescript/module/operations/prepare.d.ts.map +1 -0
  107. package/lib/typescript/module/operations/session.d.ts +8 -0
  108. package/lib/typescript/module/operations/session.d.ts.map +1 -1
  109. package/lib/typescript/module/operations/transaction.d.ts +11 -1
  110. package/lib/typescript/module/operations/transaction.d.ts.map +1 -1
  111. package/lib/typescript/module/specs/NitroSQLite.nitro.d.ts +83 -2
  112. package/lib/typescript/module/specs/NitroSQLite.nitro.d.ts.map +1 -1
  113. package/lib/typescript/module/specs/NitroSQLitePreparedStatement.nitro.d.ts +26 -0
  114. package/lib/typescript/module/specs/NitroSQLitePreparedStatement.nitro.d.ts.map +1 -0
  115. package/lib/typescript/module/specs/NitroSQLiteQueryResult.nitro.d.ts +9 -15
  116. package/lib/typescript/module/specs/NitroSQLiteQueryResult.nitro.d.ts.map +1 -1
  117. package/lib/typescript/module/typeORM.d.ts +14 -3
  118. package/lib/typescript/module/typeORM.d.ts.map +1 -1
  119. package/lib/typescript/module/types.d.ts +124 -21
  120. package/lib/typescript/module/types.d.ts.map +1 -1
  121. package/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake +1 -0
  122. package/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp +24 -0
  123. package/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.hpp +73 -0
  124. package/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.cpp +3 -0
  125. package/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.hpp +8 -2
  126. package/package.json +4 -2
  127. package/src/DatabaseQueue.ts +81 -25
  128. package/src/NitroSQLiteError.ts +6 -7
  129. package/src/OnLoad.ts +1 -1
  130. package/src/index.ts +7 -3
  131. package/src/operations/execute.ts +22 -3
  132. package/src/operations/executeBatch.ts +20 -5
  133. package/src/operations/prepare.ts +69 -0
  134. package/src/operations/session.ts +136 -45
  135. package/src/operations/transaction.ts +37 -4
  136. package/src/specs/NitroSQLite.nitro.ts +84 -2
  137. package/src/specs/NitroSQLitePreparedStatement.nitro.ts +28 -0
  138. package/src/specs/NitroSQLiteQueryResult.nitro.ts +9 -15
  139. package/src/typeORM.ts +14 -3
  140. package/src/types.ts +135 -21
  141. package/cpp/operations.cpp +0 -358
  142. package/cpp/operations.hpp +0 -56
  143. /package/android/{cpp-adapter.cpp → RNNitroSQLiteAdapter.cpp} +0 -0
  144. /package/cpp/{databaseMigration.hpp → NitroSQLiteDatabaseMigration.hpp} +0 -0
  145. /package/cpp/{logs.hpp → NitroSQLiteLogs.hpp} +0 -0
@@ -0,0 +1,73 @@
1
+ ///
2
+ /// HybridNitroSQLitePreparedStatementSpec.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/HybridObject.hpp>)
11
+ #include <NitroModules/HybridObject.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+
16
+ // Forward declaration of `HybridNitroSQLiteQueryResultSpec` to properly resolve imports.
17
+ namespace margelo::nitro::rnnitrosqlite { class HybridNitroSQLiteQueryResultSpec; }
18
+
19
+ #include <memory>
20
+ #include "HybridNitroSQLiteQueryResultSpec.hpp"
21
+ #include <NitroModules/Null.hpp>
22
+ #include <NitroModules/ArrayBuffer.hpp>
23
+ #include <string>
24
+ #include <variant>
25
+ #include <vector>
26
+ #include <optional>
27
+ #include <NitroModules/Promise.hpp>
28
+
29
+ namespace margelo::nitro::rnnitrosqlite {
30
+
31
+ using namespace margelo::nitro;
32
+
33
+ /**
34
+ * An abstract base class for `NitroSQLitePreparedStatement`
35
+ * Inherit this class to create instances of `HybridNitroSQLitePreparedStatementSpec` in C++.
36
+ * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.
37
+ * @example
38
+ * ```cpp
39
+ * class HybridNitroSQLitePreparedStatement: public HybridNitroSQLitePreparedStatementSpec {
40
+ * public:
41
+ * HybridNitroSQLitePreparedStatement(...): HybridObject(TAG) { ... }
42
+ * // ...
43
+ * };
44
+ * ```
45
+ */
46
+ class HybridNitroSQLitePreparedStatementSpec: public virtual HybridObject {
47
+ public:
48
+ // Constructor
49
+ explicit HybridNitroSQLitePreparedStatementSpec(): HybridObject(TAG) { }
50
+
51
+ // Destructor
52
+ ~HybridNitroSQLitePreparedStatementSpec() override = default;
53
+
54
+ public:
55
+ // Properties
56
+ virtual bool getIsFinalized() = 0;
57
+
58
+ public:
59
+ // Methods
60
+ virtual std::shared_ptr<HybridNitroSQLiteQueryResultSpec> execute(const std::optional<std::vector<std::variant<nitro::NullType, bool, std::shared_ptr<ArrayBuffer>, std::string, double>>>& params) = 0;
61
+ virtual std::shared_ptr<Promise<std::shared_ptr<HybridNitroSQLiteQueryResultSpec>>> executeAsync(const std::optional<std::vector<std::variant<nitro::NullType, bool, std::shared_ptr<ArrayBuffer>, std::string, double>>>& params) = 0;
62
+ virtual void finalize() = 0;
63
+
64
+ protected:
65
+ // Hybrid Setup
66
+ void loadHybridMethods() override;
67
+
68
+ protected:
69
+ // Tag for logging
70
+ static constexpr auto TAG = "NitroSQLitePreparedStatement";
71
+ };
72
+
73
+ } // namespace margelo::nitro::rnnitrosqlite
@@ -15,12 +15,15 @@ namespace margelo::nitro::rnnitrosqlite {
15
15
  // load custom methods/properties
16
16
  registerHybrids(this, [](Prototype& prototype) {
17
17
  prototype.registerHybridMethod("open", &HybridNitroSQLiteSpec::open);
18
+ prototype.registerHybridMethod("openConnection", &HybridNitroSQLiteSpec::openConnection);
19
+ prototype.registerHybridMethod("isConnectionOpen", &HybridNitroSQLiteSpec::isConnectionOpen);
18
20
  prototype.registerHybridMethod("close", &HybridNitroSQLiteSpec::close);
19
21
  prototype.registerHybridMethod("drop", &HybridNitroSQLiteSpec::drop);
20
22
  prototype.registerHybridMethod("attach", &HybridNitroSQLiteSpec::attach);
21
23
  prototype.registerHybridMethod("detach", &HybridNitroSQLiteSpec::detach);
22
24
  prototype.registerHybridMethod("execute", &HybridNitroSQLiteSpec::execute);
23
25
  prototype.registerHybridMethod("executeAsync", &HybridNitroSQLiteSpec::executeAsync);
26
+ prototype.registerHybridMethod("prepare", &HybridNitroSQLiteSpec::prepare);
24
27
  prototype.registerHybridMethod("executeBatch", &HybridNitroSQLiteSpec::executeBatch);
25
28
  prototype.registerHybridMethod("executeBatchAsync", &HybridNitroSQLiteSpec::executeBatchAsync);
26
29
  prototype.registerHybridMethod("loadFile", &HybridNitroSQLiteSpec::loadFile);
@@ -15,6 +15,8 @@
15
15
 
16
16
  // Forward declaration of `HybridNitroSQLiteQueryResultSpec` to properly resolve imports.
17
17
  namespace margelo::nitro::rnnitrosqlite { class HybridNitroSQLiteQueryResultSpec; }
18
+ // Forward declaration of `HybridNitroSQLitePreparedStatementSpec` to properly resolve imports.
19
+ namespace margelo::nitro::rnnitrosqlite { class HybridNitroSQLitePreparedStatementSpec; }
18
20
  // Forward declaration of `BatchQueryResult` to properly resolve imports.
19
21
  namespace margelo::nitro::rnnitrosqlite { struct BatchQueryResult; }
20
22
  // Forward declaration of `BatchQueryCommand` to properly resolve imports.
@@ -31,6 +33,7 @@ namespace margelo::nitro::rnnitrosqlite { struct FileLoadResult; }
31
33
  #include <variant>
32
34
  #include <vector>
33
35
  #include <NitroModules/Promise.hpp>
36
+ #include "HybridNitroSQLitePreparedStatementSpec.hpp"
34
37
  #include "BatchQueryResult.hpp"
35
38
  #include "BatchQueryCommand.hpp"
36
39
  #include "FileLoadResult.hpp"
@@ -66,13 +69,16 @@ namespace margelo::nitro::rnnitrosqlite {
66
69
 
67
70
  public:
68
71
  // Methods
69
- virtual void open(const std::string& dbName, const std::optional<std::string>& location) = 0;
72
+ virtual void open(const std::string& dbName, const std::optional<std::string>& location, std::optional<bool> readOnly) = 0;
73
+ virtual std::string openConnection(const std::string& dbName, const std::optional<std::string>& location, std::optional<bool> readOnly) = 0;
74
+ virtual bool isConnectionOpen(const std::string& connectionId) = 0;
70
75
  virtual void close(const std::string& dbName) = 0;
71
- virtual void drop(const std::string& dbName, const std::optional<std::string>& location) = 0;
76
+ virtual void drop(const std::string& dbName, const std::optional<std::string>& location, const std::optional<std::string>& connectionId) = 0;
72
77
  virtual void attach(const std::string& mainDbName, const std::string& dbNameToAttach, const std::string& alias, const std::optional<std::string>& location) = 0;
73
78
  virtual void detach(const std::string& mainDbName, const std::string& alias) = 0;
74
79
  virtual std::shared_ptr<HybridNitroSQLiteQueryResultSpec> execute(const std::string& dbName, const std::string& query, const std::optional<std::vector<std::variant<nitro::NullType, bool, std::shared_ptr<ArrayBuffer>, std::string, double>>>& params) = 0;
75
80
  virtual std::shared_ptr<Promise<std::shared_ptr<HybridNitroSQLiteQueryResultSpec>>> executeAsync(const std::string& dbName, const std::string& query, const std::optional<std::vector<std::variant<nitro::NullType, bool, std::shared_ptr<ArrayBuffer>, std::string, double>>>& params) = 0;
81
+ virtual std::shared_ptr<HybridNitroSQLitePreparedStatementSpec> prepare(const std::string& dbName, const std::string& query) = 0;
76
82
  virtual BatchQueryResult executeBatch(const std::string& dbName, const std::vector<BatchQueryCommand>& commands) = 0;
77
83
  virtual std::shared_ptr<Promise<BatchQueryResult>> executeBatchAsync(const std::string& dbName, const std::vector<BatchQueryCommand>& commands) = 0;
78
84
  virtual FileLoadResult loadFile(const std::string& dbName, const std::string& location) = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-sqlite",
3
- "version": "9.8.1",
3
+ "version": "10.0.0",
4
4
  "description": "Fast SQLite library for React Native built using Nitro Modules",
5
5
  "main": "./lib/module/index",
6
6
  "module": "./lib/module/index",
@@ -9,6 +9,7 @@
9
9
  "react-native": "./src/index",
10
10
  "exports": {
11
11
  ".": {
12
+ "react-native": "./src/index.ts",
12
13
  "import": {
13
14
  "types": "./lib/typescript/module/index.d.ts",
14
15
  "default": "./lib/module/index.js"
@@ -50,13 +51,14 @@
50
51
  "sqlite",
51
52
  "nitro-modules",
52
53
  "ios",
54
+ "macos",
53
55
  "android"
54
56
  ],
55
57
  "repository": {
56
58
  "type": "git",
57
59
  "url": "git+https://github.com/margelo/react-native-nitro-sqlite.git"
58
60
  },
59
- "author": "Margelo <hello@margelo.com> (https://github.com/margelo)",
61
+ "author": "Christoph Pader",
60
62
  "license": "MIT",
61
63
  "bugs": {
62
64
  "url": "https://github.com/margelo/react-native-nitro-sqlite/issues"
@@ -1,6 +1,7 @@
1
1
  import NitroSQLiteError from './NitroSQLiteError'
2
2
 
3
3
  export interface QueuedOperation {
4
+ kind: 'statement' | 'exclusive'
4
5
  /**
5
6
  * Starts the operation
6
7
  */
@@ -10,44 +11,56 @@ export interface QueuedOperation {
10
11
  export type DatabaseQueue = {
11
12
  queue: QueuedOperation[]
12
13
  inProgress: boolean
14
+ activeStatements: number
15
+ draining: boolean
13
16
  }
14
17
 
15
- const databaseQueues = new Map<string, DatabaseQueue>()
18
+ /** Identity of a managed connection's operation queue. Application code should
19
+ * omit the optional queue key on package helpers; connections choose it for you.
20
+ */
21
+ export type DatabaseQueueKey = string | symbol
16
22
 
17
- export function openDatabaseQueue(dbName: string) {
23
+ const databaseQueues = new Map<DatabaseQueueKey, DatabaseQueue>()
24
+
25
+ export function openDatabaseQueue(dbName: DatabaseQueueKey) {
18
26
  if (isDatabaseOpen(dbName)) {
19
27
  throw new NitroSQLiteError(
20
- `Database ${dbName} is already open. There is already a connection to the database.`,
28
+ `Database ${String(dbName)} is already open. There is already a connection to the database.`,
21
29
  )
22
30
  }
23
31
 
24
- databaseQueues.set(dbName, { queue: [], inProgress: false })
32
+ databaseQueues.set(dbName, {
33
+ queue: [],
34
+ inProgress: false,
35
+ activeStatements: 0,
36
+ draining: false,
37
+ })
25
38
  }
26
39
 
27
- export function closeDatabaseQueue(dbName: string) {
40
+ export function closeDatabaseQueue(dbName: DatabaseQueueKey) {
28
41
  const databaseQueue = getDatabaseQueue(dbName)
29
42
 
30
43
  if (databaseQueue.inProgress || databaseQueue.queue.length > 0) {
31
44
  throw new NitroSQLiteError(
32
- `Cannot close database ${dbName}. The database is busy with another operation.`,
45
+ `Cannot close database ${String(dbName)}. The database is busy with another operation.`,
33
46
  )
34
47
  }
35
48
 
36
49
  databaseQueues.delete(dbName)
37
50
  }
38
51
 
39
- export function isDatabaseOpen(dbName: string) {
52
+ export function isDatabaseOpen(dbName: DatabaseQueueKey) {
40
53
  return databaseQueues.has(dbName)
41
54
  }
42
55
 
43
- export function throwIfDatabaseIsNotOpen(dbName: string) {
56
+ export function throwIfDatabaseIsNotOpen(dbName: DatabaseQueueKey) {
44
57
  if (!isDatabaseOpen(dbName))
45
58
  throw new NitroSQLiteError(
46
- `Database ${dbName} is not open. There is no connection to the database.`,
59
+ `Database ${String(dbName)} is not open. There is no connection to the database.`,
47
60
  )
48
61
  }
49
62
 
50
- export function getDatabaseQueue(dbName: string) {
63
+ export function getDatabaseQueue(dbName: DatabaseQueueKey) {
51
64
  throwIfDatabaseIsNotOpen(dbName)
52
65
 
53
66
  const queue = databaseQueues.get(dbName)!
@@ -55,9 +68,24 @@ export function getDatabaseQueue(dbName: string) {
55
68
  }
56
69
 
57
70
  export function queueOperationAsync<Result>(
58
- dbName: string,
71
+ dbName: DatabaseQueueKey,
72
+ callback: () => Promise<Result>,
73
+ ): Promise<Result> {
74
+ return enqueueOperation(dbName, 'exclusive', callback)
75
+ }
76
+
77
+ export function queueStatementAsync<Result>(
78
+ dbName: DatabaseQueueKey,
79
+ callback: () => Promise<Result>,
80
+ ): Promise<Result> {
81
+ return enqueueOperation(dbName, 'statement', callback)
82
+ }
83
+
84
+ function enqueueOperation<Result>(
85
+ dbName: DatabaseQueueKey,
86
+ kind: QueuedOperation['kind'],
59
87
  callback: () => Promise<Result>,
60
- ) {
88
+ ): Promise<Result> {
61
89
  const databaseQueue = getDatabaseQueue(dbName)
62
90
 
63
91
  return new Promise<Result>((resolve, reject) => {
@@ -68,36 +96,63 @@ export function queueOperationAsync<Result>(
68
96
  } catch (error) {
69
97
  reject(error)
70
98
  } finally {
71
- databaseQueue.inProgress = false
72
- startOperationAsync(databaseQueue)
99
+ if (kind === 'statement') {
100
+ databaseQueue.activeStatements--
101
+ if (databaseQueue.activeStatements === 0) {
102
+ databaseQueue.inProgress = false
103
+ }
104
+ } else {
105
+ databaseQueue.inProgress = false
106
+ }
107
+ startNextOperations(databaseQueue)
73
108
  }
74
109
  }
75
110
 
76
111
  const operation: QueuedOperation = {
112
+ kind,
77
113
  start,
78
114
  }
79
115
 
80
116
  databaseQueue.queue.push(operation)
81
- startOperationAsync(databaseQueue)
117
+ startNextOperations(databaseQueue)
82
118
  })
83
119
  }
84
120
 
85
- function startOperationAsync(queue: DatabaseQueue) {
86
- // Queue is empty or in progress. Bail out.
87
- if (queue.inProgress || queue.queue.length === 0) {
121
+ function startNextOperations(queue: DatabaseQueue) {
122
+ if (queue.draining || (queue.inProgress && queue.activeStatements === 0)) {
88
123
  return
89
124
  }
90
125
 
91
- queue.inProgress = true
126
+ queue.draining = true
127
+ try {
128
+ while (queue.queue.length > 0) {
129
+ const exclusiveIndex = queue.queue.findIndex(
130
+ (operation) => operation.kind === 'exclusive',
131
+ )
132
+ const statementCount =
133
+ exclusiveIndex === -1 ? queue.queue.length : exclusiveIndex
134
+
135
+ if (statementCount > 0) {
136
+ const statements = queue.queue.splice(0, statementCount)
137
+ queue.inProgress = true
138
+ queue.activeStatements += statements.length
139
+ for (const statement of statements) statement.start()
140
+ continue
141
+ }
92
142
 
93
- const operation = queue.queue.shift()!
94
- setImmediate(() => {
95
- operation.start()
96
- })
143
+ if (queue.activeStatements > 0) return
144
+
145
+ queue.inProgress = true
146
+ queue.queue.shift()!.start()
147
+ return
148
+ }
149
+ } finally {
150
+ queue.draining = false
151
+ }
97
152
  }
98
153
 
99
154
  export function startOperationSync<Result>(
100
- dbName: string,
155
+ dbName: DatabaseQueueKey,
101
156
  callback: () => Result,
102
157
  ): Result {
103
158
  const databaseQueue = getDatabaseQueue(dbName)
@@ -105,7 +160,7 @@ export function startOperationSync<Result>(
105
160
  // Database is busy - cannot execute synchronously
106
161
  if (databaseQueue.inProgress || databaseQueue.queue.length > 0) {
107
162
  throw new NitroSQLiteError(
108
- `Cannot run synchronous operation on database. Database ${dbName} is busy with another operation.`,
163
+ `Cannot run synchronous operation on database. Database ${String(dbName)} is busy with another operation.`,
109
164
  )
110
165
  }
111
166
 
@@ -115,5 +170,6 @@ export function startOperationSync<Result>(
115
170
  return callback()
116
171
  } finally {
117
172
  databaseQueue.inProgress = false
173
+ startNextOperations(databaseQueue)
118
174
  }
119
175
  }
@@ -1,10 +1,8 @@
1
1
  const NITRO_SQLITE_ERROR_NAME = 'NitroSQLiteError' as const
2
2
 
3
- /**
4
- * Custom error class for NitroSQLite operations
5
- * Extends the native Error class with proper prototype chain and error handling
6
- */
3
+ /** Error thrown by managed NitroSQLite operations. Native errors are wrapped with this class. */
7
4
  export default class NitroSQLiteError extends Error {
5
+ /** Create an error with a message and optional cause. */
8
6
  constructor(message: string, options?: ErrorOptions) {
9
7
  super(message, options)
10
8
  this.name = NITRO_SQLITE_ERROR_NAME
@@ -13,9 +11,10 @@ export default class NitroSQLiteError extends Error {
13
11
  Object.setPrototypeOf(this, NitroSQLiteError.prototype)
14
12
  }
15
13
 
16
- /**
17
- * Converts an unknown error to a NitroSQLiteError
18
- * Preserves stack traces and error causes when available
14
+ /** Convert an unknown thrown value to `NitroSQLiteError`.
15
+ * Existing instances pass through; `Error` values keep their stack and cause.
16
+ * @param error Value to normalize.
17
+ * @returns A NitroSQLiteError instance.
19
18
  */
20
19
  static fromError(error: unknown): NitroSQLiteError {
21
20
  if (error instanceof NitroSQLiteError) {
package/src/OnLoad.ts CHANGED
@@ -1,2 +1,2 @@
1
- // NOOP on iOS
1
+ // Apple platforms initialize the database directory from OnLoad.mm.
2
2
  export const init = () => {}
package/src/index.ts CHANGED
@@ -2,21 +2,25 @@ import { transaction } from './operations/transaction'
2
2
  import { HybridNitroSQLite } from './nitro'
3
3
  import { open } from './operations/session'
4
4
  import { execute, executeAsync } from './operations/execute'
5
+ import { prepare } from './operations/prepare'
5
6
  import { init } from './OnLoad'
6
7
  import { executeBatch, executeBatchAsync } from './operations/executeBatch'
7
8
 
8
9
  init()
9
10
 
11
+ /** Database entry point. Prefer {@link open} for a managed connection.
12
+ * `native` exposes the Nitro object directly and bypasses the JavaScript queue.
13
+ */
10
14
  export const NitroSQLite = {
11
15
  ...HybridNitroSQLite,
12
16
  native: HybridNitroSQLite,
13
- // Overwrite native `open` function with session-based JS abstraction,
14
- // where the database name can be ommited once opened
17
+ // The managed open method returns a connection bound to its database name.
15
18
  open,
16
- // More JS abstractions, that perform type casting and validation.
19
+ // Managed query methods add typed rows and normalize errors.
17
20
  transaction,
18
21
  execute,
19
22
  executeAsync,
23
+ prepare,
20
24
  executeBatch,
21
25
  executeBatchAsync,
22
26
  }
@@ -4,10 +4,18 @@ import NitroSQLiteError from '../NitroSQLiteError'
4
4
  import type { NitroSQLiteQueryResult } from '../specs/NitroSQLiteQueryResult.nitro'
5
5
  import {
6
6
  isDatabaseOpen,
7
- queueOperationAsync,
7
+ queueStatementAsync,
8
8
  startOperationSync,
9
9
  } from '../DatabaseQueue'
10
+ import type { DatabaseQueueKey } from '../DatabaseQueue'
10
11
 
12
+ /** Execute one SQL statement synchronously by database name.
13
+ * Uses the managed queue when the database has an open managed connection.
14
+ * @param dbName Name of an open native database.
15
+ * @param query SQL statement with optional positional placeholders.
16
+ * @param params Values bound to the placeholders.
17
+ * @returns The query result with typed rows.
18
+ */
11
19
  export function execute<Row extends QueryResultRow = never>(
12
20
  dbName: string,
13
21
  query: string,
@@ -24,8 +32,11 @@ export function executeManaged<Row extends QueryResultRow = never>(
24
32
  dbName: string,
25
33
  query: string,
26
34
  params?: SQLiteQueryParams,
35
+ queueKey: DatabaseQueueKey = dbName,
27
36
  ): QueryResult<Row> {
28
- return startOperationSync(dbName, () => executeNative(dbName, query, params))
37
+ return startOperationSync(queueKey, () =>
38
+ executeNative(dbName, query, params),
39
+ )
29
40
  }
30
41
 
31
42
  export function executeNative<Row extends QueryResultRow = never>(
@@ -41,6 +52,13 @@ export function executeNative<Row extends QueryResultRow = never>(
41
52
  }
42
53
  }
43
54
 
55
+ /** Execute one SQL statement asynchronously by database name.
56
+ * Uses the managed queue when the database has an open managed connection.
57
+ * @param dbName Name of an open native database.
58
+ * @param query SQL statement with optional positional placeholders.
59
+ * @param params Values bound to the placeholders.
60
+ * @returns A promise of the query result with typed rows.
61
+ */
44
62
  export async function executeAsync<Row extends QueryResultRow = never>(
45
63
  dbName: string,
46
64
  query: string,
@@ -57,8 +75,9 @@ export async function executeAsyncManaged<Row extends QueryResultRow = never>(
57
75
  dbName: string,
58
76
  query: string,
59
77
  params?: SQLiteQueryParams,
78
+ queueKey: DatabaseQueueKey = dbName,
60
79
  ): Promise<QueryResult<Row>> {
61
- return queueOperationAsync(dbName, () =>
80
+ return queueStatementAsync(queueKey, () =>
62
81
  executeAsyncNative(dbName, query, params),
63
82
  )
64
83
  }
@@ -1,20 +1,28 @@
1
1
  import { HybridNitroSQLite } from '../nitro'
2
2
  import {
3
- queueOperationAsync,
3
+ queueStatementAsync,
4
4
  startOperationSync,
5
5
  throwIfDatabaseIsNotOpen,
6
6
  } from '../DatabaseQueue'
7
7
  import NitroSQLiteError from '../NitroSQLiteError'
8
8
  import type { BatchQueryCommand, BatchQueryResult } from '../types'
9
+ import type { DatabaseQueueKey } from '../DatabaseQueue'
9
10
 
11
+ /** Execute a batch synchronously in one exclusive transaction.
12
+ * Requires an open managed connection; throws if it is busy or the batch is empty.
13
+ * @param dbName Name of the open database.
14
+ * @param commands SQL commands and optional parameter sets.
15
+ * @returns Total affected row count.
16
+ */
10
17
  export function executeBatch(
11
18
  dbName: string,
12
19
  commands: BatchQueryCommand[],
20
+ queueKey: DatabaseQueueKey = dbName,
13
21
  ): BatchQueryResult {
14
- throwIfDatabaseIsNotOpen(dbName)
22
+ throwIfDatabaseIsNotOpen(queueKey)
15
23
 
16
24
  try {
17
- return startOperationSync(dbName, () =>
25
+ return startOperationSync(queueKey, () =>
18
26
  HybridNitroSQLite.executeBatch(dbName, commands),
19
27
  )
20
28
  } catch (error) {
@@ -22,13 +30,20 @@ export function executeBatch(
22
30
  }
23
31
  }
24
32
 
33
+ /** Queue a batch in one exclusive transaction.
34
+ * Requires an open managed connection; a failed command rolls back the batch.
35
+ * @param dbName Name of the open database.
36
+ * @param commands SQL commands and optional parameter sets.
37
+ * @returns A promise of the total affected row count.
38
+ */
25
39
  export async function executeBatchAsync(
26
40
  dbName: string,
27
41
  commands: BatchQueryCommand[],
42
+ queueKey: DatabaseQueueKey = dbName,
28
43
  ): Promise<BatchQueryResult> {
29
- throwIfDatabaseIsNotOpen(dbName)
44
+ throwIfDatabaseIsNotOpen(queueKey)
30
45
 
31
- return queueOperationAsync(dbName, async () => {
46
+ return queueStatementAsync(queueKey, async () => {
32
47
  try {
33
48
  return await HybridNitroSQLite.executeBatchAsync(dbName, commands)
34
49
  } catch (error) {
@@ -0,0 +1,69 @@
1
+ import { HybridNitroSQLite } from '../nitro'
2
+ import NitroSQLiteError from '../NitroSQLiteError'
3
+ import type {
4
+ PreparedStatement,
5
+ QueryResult,
6
+ QueryResultRow,
7
+ SQLiteQueryParams,
8
+ } from '../types'
9
+ import { buildJSQueryResult } from './execute'
10
+ import { queueOperationAsync, startOperationSync } from '../DatabaseQueue'
11
+ import type { DatabaseQueueKey } from '../DatabaseQueue'
12
+
13
+ /**
14
+ * Prepare one SQL statement on an open managed connection for repeated execution.
15
+ * Synchronous preparation throws if the connection is busy. Finalize the returned
16
+ * statement before closing the connection.
17
+ * @param dbName Database name or independent connection ID.
18
+ * @param query SQL statement with optional positional placeholders.
19
+ * @param queueKey Internal managed queue key; omit when using the public API.
20
+ * @returns A statement whose executions use the same connection queue.
21
+ */
22
+ export function prepare(
23
+ dbName: string,
24
+ query: string,
25
+ queueKey: DatabaseQueueKey = dbName,
26
+ ): PreparedStatement {
27
+ try {
28
+ const nativeStatement = startOperationSync(queueKey, () =>
29
+ HybridNitroSQLite.prepare(dbName, query),
30
+ )
31
+
32
+ return {
33
+ get isFinalized() {
34
+ return nativeStatement.isFinalized
35
+ },
36
+ execute: <Row extends QueryResultRow = QueryResultRow>(
37
+ params?: SQLiteQueryParams,
38
+ ): QueryResult<Row> => {
39
+ try {
40
+ return startOperationSync(queueKey, () =>
41
+ buildJSQueryResult(nativeStatement.execute(params)),
42
+ )
43
+ } catch (error) {
44
+ throw NitroSQLiteError.fromError(error)
45
+ }
46
+ },
47
+ executeAsync: async <Row extends QueryResultRow = QueryResultRow>(
48
+ params?: SQLiteQueryParams,
49
+ ): Promise<QueryResult<Row>> => {
50
+ try {
51
+ return await queueOperationAsync(queueKey, async () =>
52
+ buildJSQueryResult(await nativeStatement.executeAsync(params)),
53
+ )
54
+ } catch (error) {
55
+ throw NitroSQLiteError.fromError(error)
56
+ }
57
+ },
58
+ finalize: () => {
59
+ try {
60
+ startOperationSync(queueKey, () => nativeStatement.finalize())
61
+ } catch (error) {
62
+ throw NitroSQLiteError.fromError(error)
63
+ }
64
+ },
65
+ }
66
+ } catch (error) {
67
+ throw NitroSQLiteError.fromError(error)
68
+ }
69
+ }