@capgo/capacitor-fast-sql 8.0.11 → 8.0.13

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.
@@ -14,5 +14,6 @@ Pod::Spec.new do |s|
14
14
  s.ios.deployment_target = '15.0'
15
15
  s.dependency 'Capacitor'
16
16
  s.dependency 'Telegraph', '~> 0.30'
17
+ s.dependency 'SQLCipher', '~> 4.10'
17
18
  s.swift_version = '5.1'
18
19
  end
package/README.md CHANGED
@@ -7,6 +7,7 @@
7
7
  </div>
8
8
 
9
9
  High-performance native SQLite plugin with HTTP server for efficient sync operations and IndexedDB replacement.
10
+ Official Capgo alternative to Ionic Appflow Secure Storage.
10
11
 
11
12
  ## Why Fast SQL?
12
13
 
@@ -75,6 +76,10 @@ Add to your `AndroidManifest.xml` if needed:
75
76
  </application>
76
77
  ```
77
78
 
79
+ ## Encryption (iOS/Android)
80
+
81
+ Set `encrypted: true` and provide an `encryptionKey` when connecting. This uses SQLCipher on mobile platforms (ensure SQLCipher is linked on iOS if you use SwiftPM).
82
+
78
83
  ## Usage
79
84
 
80
85
  ### Basic Example
@@ -139,6 +144,24 @@ const results = await db.executeBatch([
139
144
  ]);
140
145
  ```
141
146
 
147
+ ### Key-Value Storage (Mobile-focused)
148
+
149
+ ```typescript
150
+ import { KeyValueStore } from '@capgo/capacitor-fast-sql';
151
+
152
+ const kv = await KeyValueStore.open({
153
+ database: 'myapp',
154
+ encrypted: true,
155
+ encryptionKey: 'super-secret-key',
156
+ });
157
+
158
+ await kv.set('session', { token: 'abc123', expiresAt: 1710000000 });
159
+ const session = await kv.get('session');
160
+ await kv.remove('session');
161
+ ```
162
+
163
+ > Note: Web support is intended for minimal testing only. The primary focus is iOS/Android.
164
+
142
165
  ## API
143
166
 
144
167
  <docgen-index>
@@ -44,7 +44,6 @@ android {
44
44
 
45
45
  repositories {
46
46
  google()
47
- jcenter()
48
47
  mavenCentral()
49
48
  }
50
49
 
@@ -52,8 +51,10 @@ dependencies {
52
51
  implementation fileTree(dir: 'libs', include: ['*.jar'])
53
52
  implementation project(':capacitor-android')
54
53
  implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
54
+ implementation 'androidx.sqlite:sqlite:2.4.0'
55
55
  implementation 'com.google.code.gson:gson:2.13.2'
56
56
  implementation 'org.nanohttpd:nanohttpd:2.3.1'
57
+ implementation 'net.zetetic:sqlcipher-android:4.13.0'
57
58
  testImplementation "junit:junit:$junitVersion"
58
59
  androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
59
60
  androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
@@ -19,9 +19,9 @@ import java.util.Map;
19
19
  @CapacitorPlugin(name = "CapgoCapacitorFastSql")
20
20
  public class CapgoCapacitorFastSqlPlugin extends Plugin {
21
21
 
22
- private final String pluginVersion = "8.0.11";
22
+ private final String pluginVersion = "8.0.13";
23
23
 
24
- private Map<String, SQLDatabase> databases = new HashMap<>();
24
+ private Map<String, DatabaseConnection> databases = new HashMap<>();
25
25
  private SQLHTTPServer server;
26
26
 
27
27
  @PluginMethod
@@ -31,6 +31,12 @@ public class CapgoCapacitorFastSqlPlugin extends Plugin {
31
31
  call.reject("Database name is required");
32
32
  return;
33
33
  }
34
+ boolean encrypted = call.getBoolean("encrypted", false);
35
+ String encryptionKey = call.getString("encryptionKey");
36
+ if (encrypted && (encryptionKey == null || encryptionKey.isEmpty())) {
37
+ call.reject("Encryption key is required when encrypted is true");
38
+ return;
39
+ }
34
40
 
35
41
  // Check if already connected
36
42
  if (databases.containsKey(database)) {
@@ -49,7 +55,12 @@ public class CapgoCapacitorFastSqlPlugin extends Plugin {
49
55
  File dbFile = getDatabasePath(database);
50
56
 
51
57
  // Open database
52
- SQLDatabase db = new SQLDatabase(dbFile.getAbsolutePath());
58
+ DatabaseConnection db;
59
+ if (encrypted) {
60
+ db = new EncryptedSQLDatabase(dbFile.getAbsolutePath(), encryptionKey);
61
+ } else {
62
+ db = new SQLDatabase(dbFile.getAbsolutePath());
63
+ }
53
64
  databases.put(database, db);
54
65
 
55
66
  // Start HTTP server if not already running
@@ -76,7 +87,7 @@ public class CapgoCapacitorFastSqlPlugin extends Plugin {
76
87
  return;
77
88
  }
78
89
 
79
- SQLDatabase db = databases.get(database);
90
+ DatabaseConnection db = databases.get(database);
80
91
  if (db == null) {
81
92
  call.reject("Database '" + database + "' is not connected");
82
93
  return;
@@ -132,7 +143,7 @@ public class CapgoCapacitorFastSqlPlugin extends Plugin {
132
143
  return;
133
144
  }
134
145
 
135
- SQLDatabase db = databases.get(database);
146
+ DatabaseConnection db = databases.get(database);
136
147
  if (db == null) {
137
148
  call.reject("Database '" + database + "' is not connected");
138
149
  return;
@@ -156,7 +167,7 @@ public class CapgoCapacitorFastSqlPlugin extends Plugin {
156
167
  return;
157
168
  }
158
169
 
159
- SQLDatabase db = databases.get(database);
170
+ DatabaseConnection db = databases.get(database);
160
171
  if (db == null) {
161
172
  call.reject("Database '" + database + "' is not connected");
162
173
  return;
@@ -178,7 +189,7 @@ public class CapgoCapacitorFastSqlPlugin extends Plugin {
178
189
  return;
179
190
  }
180
191
 
181
- SQLDatabase db = databases.get(database);
192
+ DatabaseConnection db = databases.get(database);
182
193
  if (db == null) {
183
194
  call.reject("Database '" + database + "' is not connected");
184
195
  return;
@@ -200,7 +211,7 @@ public class CapgoCapacitorFastSqlPlugin extends Plugin {
200
211
  return;
201
212
  }
202
213
 
203
- SQLDatabase db = databases.get(database);
214
+ DatabaseConnection db = databases.get(database);
204
215
  if (db == null) {
205
216
  call.reject("Database '" + database + "' is not connected");
206
217
  return;
@@ -0,0 +1,16 @@
1
+ package app.capgo.capacitor.fastsql;
2
+
3
+ import com.getcapacitor.JSArray;
4
+ import com.getcapacitor.JSObject;
5
+
6
+ public interface DatabaseConnection {
7
+ JSObject execute(String statement, JSArray params) throws Exception;
8
+
9
+ void beginTransaction() throws Exception;
10
+
11
+ void commitTransaction() throws Exception;
12
+
13
+ void rollbackTransaction() throws Exception;
14
+
15
+ void close();
16
+ }
@@ -0,0 +1,222 @@
1
+ package app.capgo.capacitor.fastsql;
2
+
3
+ import android.database.Cursor;
4
+ import android.util.Base64;
5
+ import com.getcapacitor.JSArray;
6
+ import com.getcapacitor.JSObject;
7
+ import java.nio.charset.StandardCharsets;
8
+ import java.util.ArrayList;
9
+ import java.util.List;
10
+ import net.zetetic.database.sqlcipher.SQLiteDatabase;
11
+ import net.zetetic.database.sqlcipher.SQLiteStatement;
12
+ import org.json.JSONObject;
13
+
14
+ /**
15
+ * SQLite database wrapper for Android using SQLCipher.
16
+ */
17
+ public class EncryptedSQLDatabase implements DatabaseConnection {
18
+
19
+ private SQLiteDatabase db;
20
+ private boolean inTransaction = false;
21
+
22
+ public EncryptedSQLDatabase(String path, String encryptionKey) throws Exception {
23
+ if (encryptionKey == null || encryptionKey.isEmpty()) {
24
+ throw new Exception("Encryption key is required when encrypted is true");
25
+ }
26
+ byte[] keyBytes = encryptionKey.getBytes(StandardCharsets.UTF_8);
27
+ this.db = SQLiteDatabase.openOrCreateDatabase(path, keyBytes, null, null);
28
+ // Enable foreign keys
29
+ db.execSQL("PRAGMA foreign_keys = ON");
30
+ }
31
+
32
+ public void close() {
33
+ if (db != null && db.isOpen()) {
34
+ db.close();
35
+ }
36
+ }
37
+
38
+ public JSObject execute(String statement, JSArray params) throws Exception {
39
+ if (db == null || !db.isOpen()) {
40
+ throw new Exception("Database is not open");
41
+ }
42
+
43
+ String trimmedStatement = statement.trim().toUpperCase();
44
+ boolean isQuery =
45
+ trimmedStatement.startsWith("SELECT") || trimmedStatement.startsWith("PRAGMA") || trimmedStatement.startsWith("EXPLAIN");
46
+
47
+ if (isQuery) {
48
+ return executeQuery(statement, params);
49
+ } else {
50
+ return executeUpdate(statement, params);
51
+ }
52
+ }
53
+
54
+ private JSObject executeQuery(String statement, JSArray params) throws Exception {
55
+ Cursor cursor = null;
56
+ try {
57
+ String[] bindArgs = convertParamsToStringArray(params);
58
+ cursor = db.rawQuery(statement, bindArgs);
59
+
60
+ JSArray rows = new JSArray();
61
+ while (cursor.moveToNext()) {
62
+ JSObject row = new JSObject();
63
+ for (int i = 0; i < cursor.getColumnCount(); i++) {
64
+ String columnName = cursor.getColumnName(i);
65
+ Object value = getColumnValue(cursor, i);
66
+ row.put(columnName, value);
67
+ }
68
+ rows.put(row);
69
+ }
70
+
71
+ JSObject result = new JSObject();
72
+ result.put("rows", rows);
73
+ result.put("rowsAffected", 0);
74
+ return result;
75
+ } finally {
76
+ if (cursor != null) {
77
+ cursor.close();
78
+ }
79
+ }
80
+ }
81
+
82
+ private JSObject executeUpdate(String statement, JSArray params) throws Exception {
83
+ SQLiteStatement stmt = null;
84
+ try {
85
+ stmt = db.compileStatement(statement);
86
+ bindParams(stmt, params);
87
+
88
+ long result;
89
+ if (statement.trim().toUpperCase().startsWith("INSERT")) {
90
+ result = stmt.executeInsert();
91
+ } else {
92
+ stmt.execute();
93
+ result = -1;
94
+ }
95
+
96
+ int changes = (int) db.compileStatement("SELECT changes()").simpleQueryForLong();
97
+
98
+ JSObject ret = new JSObject();
99
+ ret.put("rows", new JSArray());
100
+ ret.put("rowsAffected", changes);
101
+ if (result > 0) {
102
+ ret.put("insertId", result);
103
+ }
104
+ return ret;
105
+ } finally {
106
+ if (stmt != null) {
107
+ stmt.close();
108
+ }
109
+ }
110
+ }
111
+
112
+ public void beginTransaction() throws Exception {
113
+ if (inTransaction) {
114
+ throw new Exception("Transaction already active");
115
+ }
116
+ db.beginTransaction();
117
+ inTransaction = true;
118
+ }
119
+
120
+ public void commitTransaction() throws Exception {
121
+ if (!inTransaction) {
122
+ throw new Exception("No transaction active");
123
+ }
124
+ db.setTransactionSuccessful();
125
+ db.endTransaction();
126
+ inTransaction = false;
127
+ }
128
+
129
+ public void rollbackTransaction() throws Exception {
130
+ if (!inTransaction) {
131
+ throw new Exception("No transaction active");
132
+ }
133
+ db.endTransaction();
134
+ inTransaction = false;
135
+ }
136
+
137
+ private String[] convertParamsToStringArray(JSArray params) throws Exception {
138
+ if (params == null || params.length() == 0) {
139
+ return new String[0];
140
+ }
141
+
142
+ List<String> args = new ArrayList<>();
143
+ for (int i = 0; i < params.length(); i++) {
144
+ Object value = params.get(i);
145
+
146
+ if (value == null || value == JSONObject.NULL) {
147
+ args.add(null);
148
+ } else if (value instanceof JSONObject) {
149
+ JSONObject obj = (JSONObject) value;
150
+ if (obj.has("_type") && "binary".equals(obj.getString("_type"))) {
151
+ args.add(obj.getString("_data"));
152
+ } else {
153
+ args.add(value.toString());
154
+ }
155
+ } else {
156
+ args.add(value.toString());
157
+ }
158
+ }
159
+ return args.toArray(new String[0]);
160
+ }
161
+
162
+ private void bindParams(SQLiteStatement stmt, JSArray params) throws Exception {
163
+ if (params == null || params.length() == 0) {
164
+ return;
165
+ }
166
+
167
+ for (int i = 0; i < params.length(); i++) {
168
+ Object value = params.get(i);
169
+ int index = i + 1;
170
+
171
+ if (value == null || value == JSONObject.NULL) {
172
+ stmt.bindNull(index);
173
+ } else if (value instanceof String) {
174
+ stmt.bindString(index, (String) value);
175
+ } else if (value instanceof Integer) {
176
+ stmt.bindLong(index, ((Integer) value).longValue());
177
+ } else if (value instanceof Long) {
178
+ stmt.bindLong(index, (Long) value);
179
+ } else if (value instanceof Double) {
180
+ stmt.bindDouble(index, (Double) value);
181
+ } else if (value instanceof Float) {
182
+ stmt.bindDouble(index, ((Float) value).doubleValue());
183
+ } else if (value instanceof Boolean) {
184
+ stmt.bindLong(index, ((Boolean) value) ? 1 : 0);
185
+ } else if (value instanceof JSONObject) {
186
+ JSONObject obj = (JSONObject) value;
187
+ if (obj.has("_type") && "binary".equals(obj.getString("_type"))) {
188
+ String base64 = obj.getString("_data");
189
+ byte[] bytes = Base64.decode(base64, Base64.DEFAULT);
190
+ stmt.bindBlob(index, bytes);
191
+ } else {
192
+ stmt.bindString(index, value.toString());
193
+ }
194
+ } else {
195
+ stmt.bindString(index, value.toString());
196
+ }
197
+ }
198
+ }
199
+
200
+ private Object getColumnValue(Cursor cursor, int index) {
201
+ int type = cursor.getType(index);
202
+ switch (type) {
203
+ case Cursor.FIELD_TYPE_NULL:
204
+ return JSONObject.NULL;
205
+ case Cursor.FIELD_TYPE_INTEGER:
206
+ return cursor.getLong(index);
207
+ case Cursor.FIELD_TYPE_FLOAT:
208
+ return cursor.getDouble(index);
209
+ case Cursor.FIELD_TYPE_STRING:
210
+ return cursor.getString(index);
211
+ case Cursor.FIELD_TYPE_BLOB:
212
+ byte[] blob = cursor.getBlob(index);
213
+ String base64 = Base64.encodeToString(blob, Base64.NO_WRAP);
214
+ JSObject blobObj = new JSObject();
215
+ blobObj.put("_type", "binary");
216
+ blobObj.put("_data", base64);
217
+ return blobObj;
218
+ default:
219
+ return JSONObject.NULL;
220
+ }
221
+ }
222
+ }
@@ -15,7 +15,7 @@ import org.json.JSONObject;
15
15
  /**
16
16
  * SQLite database wrapper for Android
17
17
  */
18
- public class SQLDatabase {
18
+ public class SQLDatabase implements DatabaseConnection {
19
19
 
20
20
  private SQLiteDatabase db;
21
21
  private boolean inTransaction = false;
@@ -23,10 +23,10 @@ import org.json.JSONObject;
23
23
  public class SQLHTTPServer extends NanoHTTPD {
24
24
 
25
25
  private final String token;
26
- private final Map<String, SQLDatabase> databases;
26
+ private final Map<String, DatabaseConnection> databases;
27
27
  private final Gson gson = new Gson();
28
28
 
29
- public SQLHTTPServer(Map<String, SQLDatabase> databases) throws IOException {
29
+ public SQLHTTPServer(Map<String, DatabaseConnection> databases) throws IOException {
30
30
  super(findAvailablePort());
31
31
  this.databases = databases;
32
32
  this.token = generateToken();
@@ -55,7 +55,7 @@ public class SQLHTTPServer extends NanoHTTPD {
55
55
  }
56
56
 
57
57
  // Check if database exists
58
- SQLDatabase db = databases.get(database);
58
+ DatabaseConnection db = databases.get(database);
59
59
  if (db == null) {
60
60
  return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/plain", "Database not found");
61
61
  }
@@ -82,7 +82,7 @@ public class SQLHTTPServer extends NanoHTTPD {
82
82
  }
83
83
  }
84
84
 
85
- private Response handleExecute(IHTTPSession session, SQLDatabase db) throws Exception {
85
+ private Response handleExecute(IHTTPSession session, DatabaseConnection db) throws Exception {
86
86
  // Read request body
87
87
  String body = readRequestBody(session);
88
88
  JsonObject request = JsonParser.parseString(body).getAsJsonObject();
@@ -125,7 +125,7 @@ public class SQLHTTPServer extends NanoHTTPD {
125
125
  return newFixedLengthResponse(Response.Status.OK, "application/json", resultJson);
126
126
  }
127
127
 
128
- private Response handleBatch(IHTTPSession session, SQLDatabase db) throws Exception {
128
+ private Response handleBatch(IHTTPSession session, DatabaseConnection db) throws Exception {
129
129
  // Read request body
130
130
  String body = readRequestBody(session);
131
131
  JsonObject request = JsonParser.parseString(body).getAsJsonObject();
@@ -171,17 +171,17 @@ public class SQLHTTPServer extends NanoHTTPD {
171
171
  return newFixedLengthResponse(Response.Status.OK, "application/json", results.toString());
172
172
  }
173
173
 
174
- private Response handleBeginTransaction(SQLDatabase db) throws Exception {
174
+ private Response handleBeginTransaction(DatabaseConnection db) throws Exception {
175
175
  db.beginTransaction();
176
176
  return newFixedLengthResponse(Response.Status.OK, "application/json", "{}");
177
177
  }
178
178
 
179
- private Response handleCommitTransaction(SQLDatabase db) throws Exception {
179
+ private Response handleCommitTransaction(DatabaseConnection db) throws Exception {
180
180
  db.commitTransaction();
181
181
  return newFixedLengthResponse(Response.Status.OK, "application/json", "{}");
182
182
  }
183
183
 
184
- private Response handleRollbackTransaction(SQLDatabase db) throws Exception {
184
+ private Response handleRollbackTransaction(DatabaseConnection db) throws Exception {
185
185
  db.rollbackTransaction();
186
186
  return newFixedLengthResponse(Response.Status.OK, "application/json", "{}");
187
187
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fast-sql.d.ts","sourceRoot":"","sources":["../../src/fast-sql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD;;;;;GAKG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAC,WAAW,CAAyC;IAEnE;;;;;OAKG;WACU,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC;IAkB3E;;;;OAIG;WACU,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAaxD;;;;;OAKG;IACH,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAI5D;;OAEG;WACU,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3C;;;;OAIG;IACH,MAAM,CAAC,gBAAgB,IAAI,MAAM,EAAE;CAGpC"}
1
+ {"version":3,"file":"fast-sql.d.ts","sourceRoot":"","sources":["../../src/fast-sql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD;;;;;GAKG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAC,WAAW,CAAyC;IAEnE;;;;;OAKG;WACU,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC;IAmB3E;;;;OAIG;WACU,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAaxD;;;;;OAKG;IACH,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAI5D;;OAEG;WACU,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3C;;;;OAIG;IACH,MAAM,CAAC,gBAAgB,IAAI,MAAM,EAAE;CAGpC"}
@@ -15,8 +15,9 @@ export class FastSQL {
15
15
  */
16
16
  static async connect(options) {
17
17
  // Check if already connected
18
- if (this.connections.has(options.database)) {
19
- return this.connections.get(options.database);
18
+ const existing = this.connections.get(options.database);
19
+ if (existing) {
20
+ return existing;
20
21
  }
21
22
  // Connect via native plugin
22
23
  const info = await CapgoCapacitorFastSql.connect(options);
@@ -2,4 +2,6 @@ export * from './definitions';
2
2
  export { CapgoCapacitorFastSql } from './plugin';
3
3
  export { FastSQL } from './fast-sql';
4
4
  export { SQLConnection } from './sql-connection';
5
+ export { KeyValueStore } from './key-value';
6
+ export type { KeyValueStoreOptions, KeyValueValue } from './key-value';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
package/dist/esm/index.js CHANGED
@@ -3,3 +3,4 @@ export { CapgoCapacitorFastSql } from './plugin';
3
3
  // Re-export helper classes for convenience
4
4
  export { FastSQL } from './fast-sql';
5
5
  export { SQLConnection } from './sql-connection';
6
+ export { KeyValueStore } from './key-value';
@@ -0,0 +1,61 @@
1
+ import type { SQLConnectionOptions } from './definitions';
2
+ import type { SQLConnection } from './sql-connection';
3
+ export type KeyValueValue = string | number | boolean | null | Uint8Array | Record<string, unknown> | unknown[];
4
+ export interface KeyValueStoreOptions extends SQLConnectionOptions {
5
+ store?: string;
6
+ }
7
+ /**
8
+ * Key-value storage backed by the FastSQL database connection.
9
+ *
10
+ * This is a lightweight wrapper for mobile-focused secure storage use cases.
11
+ */
12
+ export declare class KeyValueStore {
13
+ private connection;
14
+ private store;
15
+ private initialized;
16
+ private ownsConnection;
17
+ private closed;
18
+ private constructor();
19
+ /**
20
+ * Open (or create) a key-value store for the given database.
21
+ */
22
+ static open(options: KeyValueStoreOptions): Promise<KeyValueStore>;
23
+ /**
24
+ * Create a key-value store from an existing SQLConnection.
25
+ * Note: The caller retains ownership and is responsible for closing the connection.
26
+ */
27
+ static fromConnection(connection: SQLConnection, store?: string): Promise<KeyValueStore>;
28
+ /**
29
+ * Close the key-value store and release resources.
30
+ * Only disconnects the database if this store owns the connection (created via open()).
31
+ */
32
+ close(): Promise<void>;
33
+ /**
34
+ * Store a value by key.
35
+ */
36
+ set(key: string, value: KeyValueValue): Promise<void>;
37
+ /**
38
+ * Retrieve a value by key. Returns null if the key is missing.
39
+ */
40
+ get(key: string): Promise<KeyValueValue | null>;
41
+ /**
42
+ * Check if a key exists.
43
+ */
44
+ has(key: string): Promise<boolean>;
45
+ /**
46
+ * Remove a single key.
47
+ */
48
+ remove(key: string): Promise<void>;
49
+ /**
50
+ * Clear all keys for the current store.
51
+ */
52
+ clear(): Promise<void>;
53
+ /**
54
+ * List all keys for the current store.
55
+ */
56
+ keys(): Promise<string[]>;
57
+ private ensureSchema;
58
+ private encodeValue;
59
+ private decodeValue;
60
+ }
61
+ //# sourceMappingURL=key-value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-value.d.ts","sourceRoot":"","sources":["../../src/key-value.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAoB,MAAM,eAAe,CAAC;AAE5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,CAAC;AAEhH,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD;;;;GAIG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO;IAKP;;OAEG;WACU,IAAI,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC;IASxE;;;OAGG;WACU,cAAc,CAAC,UAAU,EAAE,aAAa,EAAE,KAAK,SAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAMjG;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3D;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAerD;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASxC;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAMjB,YAAY;IAW1B,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,WAAW;CAsCpB"}