@capgo/capacitor-fast-sql 7.0.1

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 (37) hide show
  1. package/CapgoCapacitorFastSql.podspec +18 -0
  2. package/Package.swift +30 -0
  3. package/README.md +340 -0
  4. package/android/build.gradle +60 -0
  5. package/android/src/main/AndroidManifest.xml +4 -0
  6. package/android/src/main/java/app/capgo/capacitor/fastsql/CapgoCapacitorFastSqlPlugin.java +220 -0
  7. package/android/src/main/java/app/capgo/capacitor/fastsql/SQLDatabase.java +231 -0
  8. package/android/src/main/java/app/capgo/capacitor/fastsql/SQLHTTPServer.java +229 -0
  9. package/dist/esm/definitions.d.ts +225 -0
  10. package/dist/esm/definitions.d.ts.map +1 -0
  11. package/dist/esm/definitions.js +10 -0
  12. package/dist/esm/helpers.d.ts +7 -0
  13. package/dist/esm/helpers.d.ts.map +1 -0
  14. package/dist/esm/helpers.js +6 -0
  15. package/dist/esm/index.d.ts +5 -0
  16. package/dist/esm/index.d.ts.map +1 -0
  17. package/dist/esm/index.js +5 -0
  18. package/dist/esm/native-sql.d.ts +42 -0
  19. package/dist/esm/native-sql.d.ts.map +1 -0
  20. package/dist/esm/native-sql.js +69 -0
  21. package/dist/esm/plugin.d.ts +3 -0
  22. package/dist/esm/plugin.d.ts.map +1 -0
  23. package/dist/esm/plugin.js +4 -0
  24. package/dist/esm/sql-connection.d.ts +94 -0
  25. package/dist/esm/sql-connection.d.ts.map +1 -0
  26. package/dist/esm/sql-connection.js +246 -0
  27. package/dist/esm/web.d.ts +67 -0
  28. package/dist/esm/web.d.ts.map +1 -0
  29. package/dist/esm/web.js +215 -0
  30. package/dist/plugin.cjs.js +557 -0
  31. package/dist/plugin.cjs.js.map +1 -0
  32. package/dist/plugin.js +560 -0
  33. package/dist/plugin.js.map +1 -0
  34. package/ios/Sources/CapgoCapacitorFastSqlPlugin/CapgoCapacitorFastSqlPlugin.swift +202 -0
  35. package/ios/Sources/CapgoCapacitorFastSqlPlugin/SQLDatabase.swift +215 -0
  36. package/ios/Sources/CapgoCapacitorFastSqlPlugin/SQLHTTPServer.swift +311 -0
  37. package/package.json +90 -0
@@ -0,0 +1,18 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'CapgoCapacitorFastSql'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '14.0'
15
+ s.dependency 'Capacitor'
16
+ s.dependency 'Telegraph', '~> 0.30'
17
+ s.swift_version = '5.1'
18
+ end
package/Package.swift ADDED
@@ -0,0 +1,30 @@
1
+ // swift-tools-version: 5.9
2
+ import PackageDescription
3
+
4
+ let package = Package(
5
+ name: "CapgoCapacitorFastSql",
6
+ platforms: [.iOS(.v14)],
7
+ products: [
8
+ .library(
9
+ name: "CapgoCapacitorFastSql",
10
+ targets: ["CapgoCapacitorFastSqlPlugin"])
11
+ ],
12
+ dependencies: [
13
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0"),
14
+ .package(url: "https://github.com/Building42/Telegraph.git", from: "0.30.0")
15
+ ],
16
+ targets: [
17
+ .target(
18
+ name: "CapgoCapacitorFastSqlPlugin",
19
+ dependencies: [
20
+ .product(name: "Capacitor", package: "capacitor-swift-pm"),
21
+ .product(name: "Cordova", package: "capacitor-swift-pm"),
22
+ .product(name: "Telegraph", package: "Telegraph")
23
+ ],
24
+ path: "ios/Sources/CapgoCapacitorFastSqlPlugin"),
25
+ .testTarget(
26
+ name: "CapgoCapacitorFastSqlPluginTests",
27
+ dependencies: ["CapgoCapacitorFastSqlPlugin"],
28
+ path: "ios/Tests/CapgoCapacitorFastSqlPluginTests")
29
+ ]
30
+ )
package/README.md ADDED
@@ -0,0 +1,340 @@
1
+ # @capgo/capacitor-fast-sql
2
+ <a href="https://capgo.app/"><img src='https://raw.githubusercontent.com/Cap-go/capgo/main/assets/capgo_banner.png' alt='Capgo - Instant updates for capacitor'/></a>
3
+
4
+ <div align="center">
5
+ <h2><a href="https://capgo.app/?ref=plugin"> ➡️ Get Instant updates for your App with Capgo</a></h2>
6
+ <h2><a href="https://capgo.app/consulting/?ref=plugin"> Missing a feature? We'll build the plugin for you 💪</a></h2>
7
+ </div>
8
+
9
+ High-performance native SQLite plugin with HTTP server for efficient sync operations and IndexedDB replacement.
10
+
11
+ ## Documentation
12
+
13
+ The most complete doc is available here: https://capgo.app/docs/plugins/fast-sql/
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install @capgo/capacitor-fast-sql
19
+ npx cap sync
20
+ ```
21
+
22
+ ## Overview
23
+
24
+ This plugin provides direct native SQLite database access with a custom communication protocol inspired by [capacitor-blob-writer](https://github.com/diachedelic/capacitor-blob-writer). Instead of using Capacitor's standard bridge (which serializes data inefficiently), it establishes a local HTTP server for optimal performance with large datasets and sync operations.
25
+
26
+ ### Key Features
27
+
28
+ - **Custom HTTP Protocol**: Bypasses Capacitor's bridge for up to 25x faster performance with large data
29
+ - **Direct Native SQLite**: Full SQL support with transactions, batch operations, and binary data
30
+ - **Sync-Friendly**: Designed for local sync systems (CRDTs, operational transforms, etc.)
31
+ - **IndexedDB Replacement**: Provides reliable alternative to broken/limited IndexedDB implementations
32
+ - **Cross-Platform**: iOS, Android, and Web (using sql.js + IndexedDB for persistence)
33
+
34
+ ## iOS Configuration
35
+
36
+ Add to your `Info.plist` if you encounter any issues:
37
+
38
+ ```xml
39
+ <key>NSAppTransportSecurity</key>
40
+ <dict>
41
+ <key>NSAllowsLocalNetworking</key>
42
+ <true/>
43
+ </dict>
44
+ ```
45
+
46
+ ## Android Configuration
47
+
48
+ Add to your `AndroidManifest.xml` if needed:
49
+
50
+ ```xml
51
+ <application
52
+ android:usesCleartextTraffic="true">
53
+ ...
54
+ </application>
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ ### Basic Example
60
+
61
+ ```typescript
62
+ import { NativeSQL } from '@capgo/capacitor-fast-sql';
63
+
64
+ // Connect to database
65
+ const db = await NativeSQL.connect({ database: 'myapp' });
66
+
67
+ // Create table
68
+ await db.execute(`
69
+ CREATE TABLE IF NOT EXISTS users (
70
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
71
+ name TEXT NOT NULL,
72
+ email TEXT UNIQUE
73
+ )
74
+ `);
75
+
76
+ // Insert data
77
+ const result = await db.run(
78
+ 'INSERT INTO users (name, email) VALUES (?, ?)',
79
+ ['John Doe', 'john@example.com']
80
+ );
81
+ console.log('Inserted row ID:', result.insertId);
82
+
83
+ // Query data
84
+ const users = await db.query('SELECT * FROM users WHERE name LIKE ?', ['John%']);
85
+ console.log('Users:', users);
86
+
87
+ // Close connection
88
+ await NativeSQL.disconnect('myapp');
89
+ ```
90
+
91
+ ### Transaction Example
92
+
93
+ ```typescript
94
+ const db = await NativeSQL.connect({ database: 'myapp' });
95
+
96
+ try {
97
+ await db.transaction(async (tx) => {
98
+ await tx.run('INSERT INTO accounts (name, balance) VALUES (?, ?)', ['Alice', 1000]);
99
+ await tx.run('INSERT INTO accounts (name, balance) VALUES (?, ?)', ['Bob', 500]);
100
+ await tx.run('UPDATE accounts SET balance = balance - 100 WHERE name = ?', ['Alice']);
101
+ await tx.run('UPDATE accounts SET balance = balance + 100 WHERE name = ?', ['Bob']);
102
+ });
103
+ console.log('Transaction successful!');
104
+ } catch (error) {
105
+ console.error('Transaction failed:', error);
106
+ }
107
+ ```
108
+
109
+ ### Batch Operations
110
+
111
+ ```typescript
112
+ const db = await NativeSQL.connect({ database: 'myapp' });
113
+
114
+ const results = await db.executeBatch([
115
+ { statement: 'INSERT INTO logs (message) VALUES (?)', params: ['Log 1'] },
116
+ { statement: 'INSERT INTO logs (message) VALUES (?)', params: ['Log 2'] },
117
+ { statement: 'INSERT INTO logs (message) VALUES (?)', params: ['Log 3'] },
118
+ ]);
119
+ ```
120
+
121
+ ## API
122
+
123
+ <docgen-index>
124
+
125
+ * [`connect(...)`](#connect)
126
+ * [`disconnect(...)`](#disconnect)
127
+ * [`getServerInfo(...)`](#getserverinfo)
128
+ * [`execute(...)`](#execute)
129
+ * [`beginTransaction(...)`](#begintransaction)
130
+ * [`commitTransaction(...)`](#committransaction)
131
+ * [`rollbackTransaction(...)`](#rollbacktransaction)
132
+ * [`getPluginVersion()`](#getpluginversion)
133
+ * [Interfaces](#interfaces)
134
+ * [Enums](#enums)
135
+
136
+ </docgen-index>
137
+
138
+ <docgen-api>
139
+ <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
140
+
141
+ Native SQL Plugin for high-performance SQLite database access.
142
+
143
+ This plugin uses a custom HTTP-based protocol for efficient data transfer,
144
+ bypassing Capacitor's standard bridge for better performance with sync operations.
145
+
146
+ ### connect(...)
147
+
148
+ ```typescript
149
+ connect(options: SQLConnectionOptions) => Promise<{ port: number; token: string; database: string; }>
150
+ ```
151
+
152
+ Initialize the database connection and start the HTTP server.
153
+
154
+ | Param | Type | Description |
155
+ | ------------- | --------------------------------------------------------------------- | ------------------- |
156
+ | **`options`** | <code><a href="#sqlconnectionoptions">SQLConnectionOptions</a></code> | - Connection options |
157
+
158
+ **Returns:** <code>Promise&lt;{ port: number; token: string; database: string; }&gt;</code>
159
+
160
+ **Since:** 0.0.1
161
+
162
+ --------------------
163
+
164
+
165
+ ### disconnect(...)
166
+
167
+ ```typescript
168
+ disconnect(options: { database: string; }) => Promise<void>
169
+ ```
170
+
171
+ Close database connection and stop the HTTP server.
172
+
173
+ | Param | Type | Description |
174
+ | ------------- | ---------------------------------- | --------------------- |
175
+ | **`options`** | <code>{ database: string; }</code> | - Database name to close |
176
+
177
+ **Since:** 0.0.1
178
+
179
+ --------------------
180
+
181
+
182
+ ### getServerInfo(...)
183
+
184
+ ```typescript
185
+ getServerInfo(options: { database: string; }) => Promise<{ port: number; token: string; }>
186
+ ```
187
+
188
+ Get the HTTP server port and token for direct communication.
189
+
190
+ | Param | Type | Description |
191
+ | ------------- | ---------------------------------- | --------------- |
192
+ | **`options`** | <code>{ database: string; }</code> | - Database name |
193
+
194
+ **Returns:** <code>Promise&lt;{ port: number; token: string; }&gt;</code>
195
+
196
+ **Since:** 0.0.1
197
+
198
+ --------------------
199
+
200
+
201
+ ### execute(...)
202
+
203
+ ```typescript
204
+ execute(options: { database: string; statement: string; params?: SQLValue[]; }) => Promise<SQLResult>
205
+ ```
206
+
207
+ Execute a SQL query via Capacitor bridge (for simple queries).
208
+ For better performance with large datasets, use the HTTP protocol directly via SQLConnection class.
209
+
210
+ | Param | Type | Description |
211
+ | ------------- | -------------------------------------------------------------------------------------------- | ------------------ |
212
+ | **`options`** | <code>{ database: string; statement: string; params?: <a href="#sqlvalue">SQLValue</a>[]; }</code> | - Query parameters |
213
+
214
+ **Returns:** <code>Promise&lt;<a href="#sqlresult">SQLResult</a>&gt;</code>
215
+
216
+ **Since:** 0.0.1
217
+
218
+ --------------------
219
+
220
+
221
+ ### beginTransaction(...)
222
+
223
+ ```typescript
224
+ beginTransaction(options: { database: string; isolationLevel?: IsolationLevel; }) => Promise<void>
225
+ ```
226
+
227
+ Begin a database transaction.
228
+
229
+ | Param | Type | Description |
230
+ | ------------- | ------------------------------------------------------------------------------------------------------ | ----------------------- |
231
+ | **`options`** | <code>{ database: string; isolationLevel?: <a href="#isolationlevel">IsolationLevel</a>; }</code> | - Transaction options |
232
+
233
+ **Since:** 0.0.1
234
+
235
+ --------------------
236
+
237
+
238
+ ### commitTransaction(...)
239
+
240
+ ```typescript
241
+ commitTransaction(options: { database: string; }) => Promise<void>
242
+ ```
243
+
244
+ Commit the current transaction.
245
+
246
+ | Param | Type | Description |
247
+ | ------------- | ---------------------------------- | --------------- |
248
+ | **`options`** | <code>{ database: string; }</code> | - Database name |
249
+
250
+ **Since:** 0.0.1
251
+
252
+ --------------------
253
+
254
+
255
+ ### rollbackTransaction(...)
256
+
257
+ ```typescript
258
+ rollbackTransaction(options: { database: string; }) => Promise<void>
259
+ ```
260
+
261
+ Rollback the current transaction.
262
+
263
+ | Param | Type | Description |
264
+ | ------------- | ---------------------------------- | --------------- |
265
+ | **`options`** | <code>{ database: string; }</code> | - Database name |
266
+
267
+ **Since:** 0.0.1
268
+
269
+ --------------------
270
+
271
+
272
+ ### getPluginVersion()
273
+
274
+ ```typescript
275
+ getPluginVersion() => Promise<{ version: string; }>
276
+ ```
277
+
278
+ Get the native Capacitor plugin version.
279
+
280
+ **Returns:** <code>Promise&lt;{ version: string; }&gt;</code>
281
+
282
+ **Since:** 0.0.1
283
+
284
+ --------------------
285
+
286
+
287
+ ### Interfaces
288
+
289
+
290
+ #### SQLConnectionOptions
291
+
292
+ Database connection options
293
+
294
+ | Prop | Type | Description |
295
+ | ------------------- | -------------------- | --------------------------------------------------- |
296
+ | **`database`** | <code>string</code> | Database name (file will be created in app data directory) |
297
+ | **`encrypted`** | <code>boolean</code> | Enable encryption (iOS/Android only) |
298
+ | **`encryptionKey`** | <code>string</code> | Encryption key (required if encrypted is true) |
299
+ | **`readOnly`** | <code>boolean</code> | Read-only mode |
300
+
301
+
302
+ #### SQLResult
303
+
304
+ Result of a SQL query execution
305
+
306
+ | Prop | Type | Description |
307
+ | ------------------- | --------------------------------------------- | ---------------------------------------------------------------- |
308
+ | **`rows`** | <code><a href="#sqlrow">SQLRow</a>[]</code> | Rows returned by the query (for SELECT statements) |
309
+ | **`rowsAffected`** | <code>number</code> | Number of rows affected by the query (for INSERT/UPDATE/DELETE) |
310
+ | **`insertId`** | <code>number</code> | ID of the last inserted row (for INSERT statements with auto-increment) |
311
+
312
+
313
+ #### SQLRow
314
+
315
+ SQL row result - values indexed by column name
316
+
317
+
318
+ ### Enums
319
+
320
+
321
+ #### IsolationLevel
322
+
323
+ Transaction isolation levels
324
+
325
+ | Members | Value |
326
+ | ---------------------- | ------------------------------ |
327
+ | **`ReadUncommitted`** | <code>'READ UNCOMMITTED'</code> |
328
+ | **`ReadCommitted`** | <code>'READ COMMITTED'</code> |
329
+ | **`RepeatableRead`** | <code>'REPEATABLE READ'</code> |
330
+ | **`Serializable`** | <code>'SERIALIZABLE'</code> |
331
+
332
+
333
+ ### Type Aliases
334
+
335
+
336
+ #### SQLValue
337
+
338
+ <code>string | number | boolean | null | Uint8Array</code>
339
+
340
+ </docgen-api>
@@ -0,0 +1,60 @@
1
+ ext {
2
+ junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
3
+ androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
4
+ androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
5
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
6
+ }
7
+
8
+ buildscript {
9
+ repositories {
10
+ mavenCentral()
11
+ google()
12
+ }
13
+ dependencies {
14
+ classpath 'com.android.tools.build:gradle:8.7.2'
15
+ }
16
+ }
17
+
18
+ apply plugin: 'com.android.library'
19
+
20
+ android {
21
+ namespace 'app.capgo.capacitor.fastsql'
22
+ compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
23
+ defaultConfig {
24
+ minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
25
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
26
+ versionCode 1
27
+ versionName "1.0"
28
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
29
+ }
30
+ buildTypes {
31
+ release {
32
+ minifyEnabled false
33
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
34
+ }
35
+ }
36
+ lintOptions {
37
+ abortOnError false
38
+ }
39
+ compileOptions {
40
+ sourceCompatibility JavaVersion.VERSION_21
41
+ targetCompatibility JavaVersion.VERSION_21
42
+ }
43
+ }
44
+
45
+ repositories {
46
+ google()
47
+ jcenter()
48
+ mavenCentral()
49
+ }
50
+
51
+ dependencies {
52
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
53
+ implementation project(':capacitor-android')
54
+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
55
+ implementation 'com.google.code.gson:gson:2.10.1'
56
+ implementation 'org.nanohttpd:nanohttpd:2.3.1'
57
+ testImplementation "junit:junit:$junitVersion"
58
+ androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
59
+ androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
60
+ }
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <uses-permission android:name="android.permission.INTERNET" />
4
+ </manifest>
@@ -0,0 +1,220 @@
1
+ package app.capgo.capacitor.fastsql;
2
+
3
+ import com.getcapacitor.JSArray;
4
+ import com.getcapacitor.JSObject;
5
+ import com.getcapacitor.Plugin;
6
+ import com.getcapacitor.PluginCall;
7
+ import com.getcapacitor.PluginMethod;
8
+ import com.getcapacitor.annotation.CapacitorPlugin;
9
+
10
+ import java.io.File;
11
+ import java.util.HashMap;
12
+ import java.util.Map;
13
+
14
+ /**
15
+ * Native SQL Plugin for Android
16
+ *
17
+ * This plugin uses a custom HTTP server for efficient data transfer,
18
+ * bypassing Capacitor's standard bridge for better performance.
19
+ */
20
+ @CapacitorPlugin(name = "CapgoCapacitorFastSql")
21
+ public class CapgoCapacitorFastSqlPlugin extends Plugin {
22
+
23
+ private Map<String, SQLDatabase> databases = new HashMap<>();
24
+ private SQLHTTPServer server;
25
+
26
+ @PluginMethod
27
+ public void connect(PluginCall call) {
28
+ String database = call.getString("database");
29
+ if (database == null) {
30
+ call.reject("Database name is required");
31
+ return;
32
+ }
33
+
34
+ // Check if already connected
35
+ if (databases.containsKey(database)) {
36
+ if (server != null) {
37
+ JSObject ret = new JSObject();
38
+ ret.put("port", server.getPort());
39
+ ret.put("token", server.getToken());
40
+ ret.put("database", database);
41
+ call.resolve(ret);
42
+ return;
43
+ }
44
+ }
45
+
46
+ try {
47
+ // Get database path
48
+ File dbFile = getDatabasePath(database);
49
+
50
+ // Open database
51
+ SQLDatabase db = new SQLDatabase(dbFile.getAbsolutePath());
52
+ databases.put(database, db);
53
+
54
+ // Start HTTP server if not already running
55
+ if (server == null) {
56
+ server = new SQLHTTPServer(databases);
57
+ server.start();
58
+ }
59
+
60
+ JSObject ret = new JSObject();
61
+ ret.put("port", server.getPort());
62
+ ret.put("token", server.getToken());
63
+ ret.put("database", database);
64
+ call.resolve(ret);
65
+ } catch (Exception e) {
66
+ call.reject("Failed to connect to database: " + e.getMessage(), e);
67
+ }
68
+ }
69
+
70
+ @PluginMethod
71
+ public void disconnect(PluginCall call) {
72
+ String database = call.getString("database");
73
+ if (database == null) {
74
+ call.reject("Database name is required");
75
+ return;
76
+ }
77
+
78
+ SQLDatabase db = databases.get(database);
79
+ if (db == null) {
80
+ call.reject("Database '" + database + "' is not connected");
81
+ return;
82
+ }
83
+
84
+ db.close();
85
+ databases.remove(database);
86
+
87
+ // Stop server if no more databases
88
+ if (databases.isEmpty() && server != null) {
89
+ server.stop();
90
+ server = null;
91
+ }
92
+
93
+ call.resolve();
94
+ }
95
+
96
+ @PluginMethod
97
+ public void getServerInfo(PluginCall call) {
98
+ String database = call.getString("database");
99
+ if (database == null) {
100
+ call.reject("Database name is required");
101
+ return;
102
+ }
103
+
104
+ if (!databases.containsKey(database)) {
105
+ call.reject("Database '" + database + "' is not connected");
106
+ return;
107
+ }
108
+
109
+ if (server == null) {
110
+ call.reject("Server is not running");
111
+ return;
112
+ }
113
+
114
+ JSObject ret = new JSObject();
115
+ ret.put("port", server.getPort());
116
+ ret.put("token", server.getToken());
117
+ call.resolve(ret);
118
+ }
119
+
120
+ @PluginMethod
121
+ public void execute(PluginCall call) {
122
+ String database = call.getString("database");
123
+ if (database == null) {
124
+ call.reject("Database name is required");
125
+ return;
126
+ }
127
+
128
+ String statement = call.getString("statement");
129
+ if (statement == null) {
130
+ call.reject("Statement is required");
131
+ return;
132
+ }
133
+
134
+ SQLDatabase db = databases.get(database);
135
+ if (db == null) {
136
+ call.reject("Database '" + database + "' is not connected");
137
+ return;
138
+ }
139
+
140
+ JSArray params = call.getArray("params", new JSArray());
141
+
142
+ try {
143
+ JSObject result = db.execute(statement, params);
144
+ call.resolve(result);
145
+ } catch (Exception e) {
146
+ call.reject("Failed to execute statement: " + e.getMessage(), e);
147
+ }
148
+ }
149
+
150
+ @PluginMethod
151
+ public void beginTransaction(PluginCall call) {
152
+ String database = call.getString("database");
153
+ if (database == null) {
154
+ call.reject("Database name is required");
155
+ return;
156
+ }
157
+
158
+ SQLDatabase db = databases.get(database);
159
+ if (db == null) {
160
+ call.reject("Database '" + database + "' is not connected");
161
+ return;
162
+ }
163
+
164
+ try {
165
+ db.beginTransaction();
166
+ call.resolve();
167
+ } catch (Exception e) {
168
+ call.reject("Failed to begin transaction: " + e.getMessage(), e);
169
+ }
170
+ }
171
+
172
+ @PluginMethod
173
+ public void commitTransaction(PluginCall call) {
174
+ String database = call.getString("database");
175
+ if (database == null) {
176
+ call.reject("Database name is required");
177
+ return;
178
+ }
179
+
180
+ SQLDatabase db = databases.get(database);
181
+ if (db == null) {
182
+ call.reject("Database '" + database + "' is not connected");
183
+ return;
184
+ }
185
+
186
+ try {
187
+ db.commitTransaction();
188
+ call.resolve();
189
+ } catch (Exception e) {
190
+ call.reject("Failed to commit transaction: " + e.getMessage(), e);
191
+ }
192
+ }
193
+
194
+ @PluginMethod
195
+ public void rollbackTransaction(PluginCall call) {
196
+ String database = call.getString("database");
197
+ if (database == null) {
198
+ call.reject("Database name is required");
199
+ return;
200
+ }
201
+
202
+ SQLDatabase db = databases.get(database);
203
+ if (db == null) {
204
+ call.reject("Database '" + database + "' is not connected");
205
+ return;
206
+ }
207
+
208
+ try {
209
+ db.rollbackTransaction();
210
+ call.resolve();
211
+ } catch (Exception e) {
212
+ call.reject("Failed to rollback transaction: " + e.getMessage(), e);
213
+ }
214
+ }
215
+
216
+ private File getDatabasePath(String database) {
217
+ File dataDir = getContext().getFilesDir();
218
+ return new File(dataDir, database + ".db");
219
+ }
220
+ }