strata-storage 2.4.2 → 2.5.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/AI-INTEGRATION-GUIDE.md +208 -0
- package/README.md +427 -181
- package/android/AGENTS.md +34 -0
- package/android/CLAUDE.md +51 -0
- package/android/src/main/java/com/strata/storage/SQLiteStorage.java +35 -0
- package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +191 -27
- package/dist/README.md +427 -181
- package/dist/adapters/capacitor/FilesystemAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/FilesystemAdapter.js +2 -1
- package/dist/adapters/capacitor/PreferencesAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/PreferencesAdapter.js +2 -1
- package/dist/adapters/capacitor/SecureAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/SecureAdapter.js +2 -1
- package/dist/adapters/capacitor/SqliteAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/SqliteAdapter.js +2 -1
- package/dist/adapters/web/CacheAdapter.d.ts.map +1 -1
- package/dist/adapters/web/CacheAdapter.js +11 -3
- package/dist/adapters/web/CookieAdapter.d.ts +37 -1
- package/dist/adapters/web/CookieAdapter.d.ts.map +1 -1
- package/dist/adapters/web/CookieAdapter.js +89 -9
- package/dist/adapters/web/IndexedDBAdapter.d.ts.map +1 -1
- package/dist/adapters/web/IndexedDBAdapter.js +10 -2
- package/dist/adapters/web/LocalStorageAdapter.d.ts +31 -0
- package/dist/adapters/web/LocalStorageAdapter.d.ts.map +1 -1
- package/dist/adapters/web/LocalStorageAdapter.js +92 -19
- package/dist/adapters/web/MemoryAdapter.d.ts +24 -0
- package/dist/adapters/web/MemoryAdapter.d.ts.map +1 -1
- package/dist/adapters/web/MemoryAdapter.js +69 -18
- package/dist/adapters/web/SessionStorageAdapter.d.ts +24 -0
- package/dist/adapters/web/SessionStorageAdapter.d.ts.map +1 -1
- package/dist/adapters/web/SessionStorageAdapter.js +71 -9
- package/dist/adapters/web/URLAdapter.d.ts +59 -0
- package/dist/adapters/web/URLAdapter.d.ts.map +1 -0
- package/dist/adapters/web/URLAdapter.js +234 -0
- package/dist/adapters/web/index.d.ts +1 -0
- package/dist/adapters/web/index.d.ts.map +1 -1
- package/dist/adapters/web/index.js +1 -0
- package/dist/android/AGENTS.md +34 -0
- package/dist/android/CLAUDE.md +51 -0
- package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +35 -0
- package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +191 -27
- package/dist/capacitor.d.ts.map +1 -1
- package/dist/capacitor.js +2 -1
- package/dist/config/support.d.ts +10 -0
- package/dist/config/support.d.ts.map +1 -0
- package/dist/config/support.js +9 -0
- package/dist/core/BaseAdapter.d.ts +8 -0
- package/dist/core/BaseAdapter.d.ts.map +1 -1
- package/dist/core/BaseAdapter.js +34 -14
- package/dist/core/Strata.d.ts +56 -2
- package/dist/core/Strata.d.ts.map +1 -1
- package/dist/core/Strata.js +501 -53
- package/dist/features/encryption.d.ts.map +1 -1
- package/dist/features/encryption.js +3 -2
- package/dist/features/integrity.d.ts +16 -0
- package/dist/features/integrity.d.ts.map +1 -0
- package/dist/features/integrity.js +28 -0
- package/dist/features/observer.d.ts.map +1 -1
- package/dist/features/observer.js +2 -1
- package/dist/features/query.d.ts +7 -1
- package/dist/features/query.d.ts.map +1 -1
- package/dist/features/query.js +9 -2
- package/dist/features/sync.d.ts.map +1 -1
- package/dist/features/sync.js +4 -3
- package/dist/index.d.ts +35 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +55 -30
- package/dist/integrations/angular/index.d.ts +158 -0
- package/dist/integrations/angular/index.d.ts.map +1 -0
- package/dist/integrations/angular/index.js +395 -0
- package/dist/integrations/index.d.ts +15 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +18 -0
- package/dist/integrations/react/index.d.ts +75 -0
- package/dist/integrations/react/index.d.ts.map +1 -0
- package/dist/integrations/react/index.js +191 -0
- package/dist/integrations/vue/index.d.ts +103 -0
- package/dist/integrations/vue/index.d.ts.map +1 -0
- package/dist/integrations/vue/index.js +274 -0
- package/dist/ios/AGENTS.md +33 -0
- package/dist/ios/CLAUDE.md +49 -0
- package/dist/ios/Plugin/KeychainStorage.swift +139 -50
- package/dist/ios/Plugin/SQLiteStorage.swift +40 -0
- package/dist/ios/Plugin/StrataStoragePlugin.m +23 -0
- package/dist/ios/Plugin/StrataStoragePlugin.swift +201 -52
- package/dist/package.json +21 -5
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +2 -1
- package/dist/types/index.d.ts +58 -9
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -13
- package/dist/utils/errors.d.ts +7 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +15 -3
- package/dist/utils/index.d.ts +63 -5
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +109 -16
- package/dist/utils/logger.d.ts +31 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +63 -0
- package/ios/AGENTS.md +33 -0
- package/ios/CLAUDE.md +49 -0
- package/ios/Plugin/KeychainStorage.swift +139 -50
- package/ios/Plugin/SQLiteStorage.swift +40 -0
- package/ios/Plugin/StrataStoragePlugin.m +23 -0
- package/ios/Plugin/StrataStoragePlugin.swift +201 -52
- package/package.json +35 -23
- package/scripts/build.js +16 -5
- package/scripts/configure.js +2 -6
- package/scripts/postinstall.js +2 -2
- package/Readme.md +0 -271
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# AGENTS.md — android/
|
|
2
|
+
|
|
3
|
+
Last Updated: 2026-04-03
|
|
4
|
+
|
|
5
|
+
> Agent instructions for Android native development.
|
|
6
|
+
|
|
7
|
+
## Files
|
|
8
|
+
|
|
9
|
+
| File | Purpose |
|
|
10
|
+
|------|---------|
|
|
11
|
+
| `StrataStoragePlugin.java` | Capacitor plugin entry (com.stratastorage) |
|
|
12
|
+
| `SharedPreferencesStorage.java` | General key-value storage (com.strata.storage) |
|
|
13
|
+
| `EncryptedStorage.java` | Secure storage (com.strata.storage) |
|
|
14
|
+
| `SQLiteStorage.java` | Database storage (com.strata.storage) |
|
|
15
|
+
|
|
16
|
+
## Agent Rules
|
|
17
|
+
|
|
18
|
+
### Security (IRON-SOLID)
|
|
19
|
+
- Sensitive data MUST use `EncryptedStorage`
|
|
20
|
+
- NEVER store secrets in `SharedPreferencesStorage`
|
|
21
|
+
|
|
22
|
+
### SQL Safety (IRON-SOLID)
|
|
23
|
+
- ALWAYS use parameterized queries
|
|
24
|
+
- NEVER concatenate user input into SQL strings
|
|
25
|
+
|
|
26
|
+
### Plugin Architecture
|
|
27
|
+
- Methods exposed through `StrataStoragePlugin.java`
|
|
28
|
+
- Each storage backend is a separate Java class
|
|
29
|
+
- Two package paths: `com.stratastorage` (plugin) and `com.strata.storage` (impl)
|
|
30
|
+
|
|
31
|
+
### Before Modifying
|
|
32
|
+
- Understand Capacitor plugin protocol for Android
|
|
33
|
+
- Test on Android emulator after changes
|
|
34
|
+
- Verify Gradle build succeeds
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# CLAUDE.md — android/
|
|
2
|
+
|
|
3
|
+
Last Updated: 2026-04-03
|
|
4
|
+
|
|
5
|
+
## Android Native Plugin
|
|
6
|
+
|
|
7
|
+
Java implementation of native storage backends for Capacitor.
|
|
8
|
+
|
|
9
|
+
### Files
|
|
10
|
+
|
|
11
|
+
| File | Path | Purpose |
|
|
12
|
+
|------|------|---------|
|
|
13
|
+
| `StrataStoragePlugin.java` | `src/main/java/com/stratastorage/` | Main Capacitor plugin entry |
|
|
14
|
+
| `SharedPreferencesStorage.java` | `src/main/java/com/strata/storage/` | SharedPreferences general storage |
|
|
15
|
+
| `EncryptedStorage.java` | `src/main/java/com/strata/storage/` | EncryptedSharedPreferences secure storage |
|
|
16
|
+
| `SQLiteStorage.java` | `src/main/java/com/strata/storage/` | SQLite database storage |
|
|
17
|
+
|
|
18
|
+
### Configuration
|
|
19
|
+
|
|
20
|
+
- Build: `build.gradle`
|
|
21
|
+
- Proguard: `proguard-rules.pro`
|
|
22
|
+
- Manifest: `src/main/AndroidManifest.xml`
|
|
23
|
+
|
|
24
|
+
**Note**: There are two Java package paths — `com.stratastorage` (plugin) and `com.strata.storage` (implementations).
|
|
25
|
+
|
|
26
|
+
## Rules
|
|
27
|
+
|
|
28
|
+
### Security (IRON-SOLID)
|
|
29
|
+
- Sensitive data MUST use `EncryptedStorage` (EncryptedSharedPreferences)
|
|
30
|
+
- NEVER store credentials, tokens, or secrets in `SharedPreferencesStorage`
|
|
31
|
+
- Follow Android Keystore best practices
|
|
32
|
+
|
|
33
|
+
### SQL Safety (IRON-SOLID)
|
|
34
|
+
- ALWAYS use parameterized queries in `SQLiteStorage`
|
|
35
|
+
- NEVER concatenate user input into SQL strings
|
|
36
|
+
- Use `SQLiteDatabase.query()` or prepared statements
|
|
37
|
+
|
|
38
|
+
### Plugin Architecture
|
|
39
|
+
- All native methods exposed through `StrataStoragePlugin.java`
|
|
40
|
+
- Plugin bridges Capacitor JS calls to Java implementations
|
|
41
|
+
- Each storage backend is a separate Java class
|
|
42
|
+
|
|
43
|
+
### Build
|
|
44
|
+
- Gradle-based build system
|
|
45
|
+
- Proguard rules configured for release builds
|
|
46
|
+
- Test on Android emulator after changes
|
|
47
|
+
|
|
48
|
+
### Before Modifying
|
|
49
|
+
- Understand the Capacitor plugin protocol for Android
|
|
50
|
+
- Test on Android emulator after changes
|
|
51
|
+
- Verify Gradle build succeeds
|
|
@@ -227,6 +227,41 @@ public class SQLiteStorage extends SQLiteOpenHelper {
|
|
|
227
227
|
db.close();
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Returns every row as a map of { key, value } where value is the decoded
|
|
233
|
+
* stored payload (UTF-8 string of the BLOB). The JS SqliteAdapter applies
|
|
234
|
+
* the real query condition by re-fetching/filtering each key, so this only
|
|
235
|
+
* needs to enumerate candidate rows.
|
|
236
|
+
*/
|
|
237
|
+
public List<Map<String, Object>> query() {
|
|
238
|
+
List<Map<String, Object>> rows = new ArrayList<>();
|
|
239
|
+
SQLiteDatabase db = this.getReadableDatabase();
|
|
240
|
+
Cursor cursor = null;
|
|
241
|
+
try {
|
|
242
|
+
cursor = db.query(TABLE_NAME, new String[]{KEY_ID, KEY_VALUE},
|
|
243
|
+
null, null, null, null, null);
|
|
244
|
+
if (cursor != null && cursor.moveToFirst()) {
|
|
245
|
+
do {
|
|
246
|
+
Map<String, Object> row = new HashMap<>();
|
|
247
|
+
row.put("key", cursor.getString(0));
|
|
248
|
+
byte[] valueBytes = cursor.getBlob(1);
|
|
249
|
+
if (valueBytes != null) {
|
|
250
|
+
row.put("value", new String(valueBytes, StandardCharsets.UTF_8));
|
|
251
|
+
} else {
|
|
252
|
+
row.put("value", null);
|
|
253
|
+
}
|
|
254
|
+
rows.add(row);
|
|
255
|
+
} while (cursor.moveToNext());
|
|
256
|
+
}
|
|
257
|
+
return rows;
|
|
258
|
+
} finally {
|
|
259
|
+
if (cursor != null) {
|
|
260
|
+
cursor.close();
|
|
261
|
+
}
|
|
262
|
+
db.close();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
230
265
|
|
|
231
266
|
public SizeInfo size() {
|
|
232
267
|
SQLiteDatabase db = this.getReadableDatabase();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.stratastorage;
|
|
2
2
|
|
|
3
3
|
import com.getcapacitor.JSObject;
|
|
4
|
+
import com.getcapacitor.JSArray;
|
|
4
5
|
import com.getcapacitor.Plugin;
|
|
5
6
|
import com.getcapacitor.PluginCall;
|
|
6
7
|
import com.getcapacitor.PluginMethod;
|
|
@@ -12,10 +13,15 @@ import android.util.Log;
|
|
|
12
13
|
import org.json.JSONArray;
|
|
13
14
|
import org.json.JSONException;
|
|
14
15
|
import java.util.List;
|
|
16
|
+
import java.util.Map;
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* Main Capacitor plugin for Strata Storage
|
|
18
|
-
* Coordinates between different storage types on Android
|
|
20
|
+
* Coordinates between different storage types on Android.
|
|
21
|
+
*
|
|
22
|
+
* Storage types with a real native backend: preferences, secure, sqlite.
|
|
23
|
+
* `filesystem` is NOT implemented natively and is rejected explicitly rather
|
|
24
|
+
* than silently falling through to SharedPreferences.
|
|
19
25
|
*/
|
|
20
26
|
@CapacitorPlugin(name = "StrataStorage")
|
|
21
27
|
public class StrataStoragePlugin extends Plugin {
|
|
@@ -27,30 +33,58 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
27
33
|
public void load() {
|
|
28
34
|
try {
|
|
29
35
|
sharedPrefsStorage = new SharedPreferencesStorage(getContext());
|
|
36
|
+
} catch (Exception e) {
|
|
37
|
+
Log.e("StrataStorage", "Failed to initialize preferences storage", e);
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
30
40
|
encryptedStorage = new EncryptedStorage(getContext());
|
|
41
|
+
} catch (Exception e) {
|
|
42
|
+
// Secure storage may be unavailable on some devices/keystores —
|
|
43
|
+
// keep the rest of the plugin functional.
|
|
44
|
+
Log.e("StrataStorage", "Failed to initialize encrypted storage", e);
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
31
47
|
sqliteStorage = new SQLiteStorage(getContext());
|
|
32
48
|
} catch (Exception e) {
|
|
33
|
-
|
|
34
|
-
Log.e("StrataStorage", "Failed to initialize storage", e);
|
|
49
|
+
Log.e("StrataStorage", "Failed to initialize SQLite storage", e);
|
|
35
50
|
}
|
|
36
51
|
}
|
|
37
52
|
|
|
53
|
+
private void rejectUnsupportedFilesystem(PluginCall call) {
|
|
54
|
+
call.reject(
|
|
55
|
+
"Filesystem storage is not implemented in the native Android plugin. " +
|
|
56
|
+
"Use the 'preferences', 'secure', or 'sqlite' storage types, or a " +
|
|
57
|
+
"web/Capacitor Filesystem-backed adapter."
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
38
61
|
/**
|
|
39
|
-
* Check if storage is available
|
|
62
|
+
* Check if a specific storage type is available.
|
|
63
|
+
* Matches the JS contract: resolves { available: boolean }.
|
|
40
64
|
*/
|
|
41
65
|
@PluginMethod
|
|
42
66
|
public void isAvailable(PluginCall call) {
|
|
67
|
+
String storage = call.getString("storage", "preferences");
|
|
68
|
+
boolean available;
|
|
69
|
+
switch (storage) {
|
|
70
|
+
case "secure":
|
|
71
|
+
available = encryptedStorage != null;
|
|
72
|
+
break;
|
|
73
|
+
case "sqlite":
|
|
74
|
+
available = sqliteStorage != null;
|
|
75
|
+
break;
|
|
76
|
+
case "filesystem":
|
|
77
|
+
// No native filesystem backend.
|
|
78
|
+
available = false;
|
|
79
|
+
break;
|
|
80
|
+
case "preferences":
|
|
81
|
+
default:
|
|
82
|
+
available = sharedPrefsStorage != null;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
|
|
43
86
|
JSObject result = new JSObject();
|
|
44
|
-
result.put("available",
|
|
45
|
-
result.put("platform", "android");
|
|
46
|
-
|
|
47
|
-
JSObject adapters = new JSObject();
|
|
48
|
-
adapters.put("preferences", true);
|
|
49
|
-
adapters.put("secure", true);
|
|
50
|
-
adapters.put("sqlite", true);
|
|
51
|
-
adapters.put("filesystem", true);
|
|
52
|
-
result.put("adapters", adapters);
|
|
53
|
-
|
|
87
|
+
result.put("available", available);
|
|
54
88
|
call.resolve(result);
|
|
55
89
|
}
|
|
56
90
|
|
|
@@ -66,7 +100,7 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
66
100
|
}
|
|
67
101
|
|
|
68
102
|
String storage = call.getString("storage", "preferences");
|
|
69
|
-
|
|
103
|
+
|
|
70
104
|
try {
|
|
71
105
|
Object value = null;
|
|
72
106
|
|
|
@@ -85,6 +119,9 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
85
119
|
}
|
|
86
120
|
value = sqliteStorage.get(key);
|
|
87
121
|
break;
|
|
122
|
+
case "filesystem":
|
|
123
|
+
rejectUnsupportedFilesystem(call);
|
|
124
|
+
return;
|
|
88
125
|
case "preferences":
|
|
89
126
|
default:
|
|
90
127
|
if (sharedPrefsStorage == null) {
|
|
@@ -116,33 +153,41 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
116
153
|
|
|
117
154
|
Object value = call.getData().opt("value");
|
|
118
155
|
String storage = call.getString("storage", "preferences");
|
|
119
|
-
|
|
156
|
+
|
|
120
157
|
try {
|
|
158
|
+
boolean ok;
|
|
121
159
|
switch (storage) {
|
|
122
160
|
case "secure":
|
|
123
161
|
if (encryptedStorage == null) {
|
|
124
162
|
call.reject("Encrypted storage not available");
|
|
125
163
|
return;
|
|
126
164
|
}
|
|
127
|
-
encryptedStorage.set(key, value);
|
|
165
|
+
ok = encryptedStorage.set(key, value);
|
|
128
166
|
break;
|
|
129
167
|
case "sqlite":
|
|
130
168
|
if (sqliteStorage == null) {
|
|
131
169
|
call.reject("SQLite storage not available");
|
|
132
170
|
return;
|
|
133
171
|
}
|
|
134
|
-
sqliteStorage.set(key, value);
|
|
172
|
+
ok = sqliteStorage.set(key, value);
|
|
135
173
|
break;
|
|
174
|
+
case "filesystem":
|
|
175
|
+
rejectUnsupportedFilesystem(call);
|
|
176
|
+
return;
|
|
136
177
|
case "preferences":
|
|
137
178
|
default:
|
|
138
179
|
if (sharedPrefsStorage == null) {
|
|
139
180
|
call.reject("Preferences storage not available");
|
|
140
181
|
return;
|
|
141
182
|
}
|
|
142
|
-
sharedPrefsStorage.set(key, value);
|
|
183
|
+
ok = sharedPrefsStorage.set(key, value);
|
|
143
184
|
break;
|
|
144
185
|
}
|
|
145
186
|
|
|
187
|
+
if (!ok) {
|
|
188
|
+
call.reject("Failed to persist value to " + storage + " storage");
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
146
191
|
call.resolve();
|
|
147
192
|
} catch (Exception e) {
|
|
148
193
|
call.reject("Failed to set value", e);
|
|
@@ -161,7 +206,7 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
161
206
|
}
|
|
162
207
|
|
|
163
208
|
String storage = call.getString("storage", "preferences");
|
|
164
|
-
|
|
209
|
+
|
|
165
210
|
try {
|
|
166
211
|
switch (storage) {
|
|
167
212
|
case "secure":
|
|
@@ -178,6 +223,9 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
178
223
|
}
|
|
179
224
|
sqliteStorage.remove(key);
|
|
180
225
|
break;
|
|
226
|
+
case "filesystem":
|
|
227
|
+
rejectUnsupportedFilesystem(call);
|
|
228
|
+
return;
|
|
181
229
|
case "preferences":
|
|
182
230
|
default:
|
|
183
231
|
if (sharedPrefsStorage == null) {
|
|
@@ -195,13 +243,17 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
195
243
|
}
|
|
196
244
|
|
|
197
245
|
/**
|
|
198
|
-
* Clear storage
|
|
246
|
+
* Clear storage.
|
|
247
|
+
* Accepts the JS `pattern` (used as a key prefix) and a legacy `prefix`.
|
|
199
248
|
*/
|
|
200
249
|
@PluginMethod
|
|
201
250
|
public void clear(PluginCall call) {
|
|
202
251
|
String storage = call.getString("storage", "preferences");
|
|
203
|
-
String prefix = call.getString("
|
|
204
|
-
|
|
252
|
+
String prefix = call.getString("pattern");
|
|
253
|
+
if (prefix == null) {
|
|
254
|
+
prefix = call.getString("prefix");
|
|
255
|
+
}
|
|
256
|
+
|
|
205
257
|
try {
|
|
206
258
|
switch (storage) {
|
|
207
259
|
case "secure":
|
|
@@ -218,6 +270,9 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
218
270
|
}
|
|
219
271
|
sqliteStorage.clear(prefix);
|
|
220
272
|
break;
|
|
273
|
+
case "filesystem":
|
|
274
|
+
rejectUnsupportedFilesystem(call);
|
|
275
|
+
return;
|
|
221
276
|
case "preferences":
|
|
222
277
|
default:
|
|
223
278
|
if (sharedPrefsStorage == null) {
|
|
@@ -241,7 +296,7 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
241
296
|
public void keys(PluginCall call) {
|
|
242
297
|
String storage = call.getString("storage", "preferences");
|
|
243
298
|
String pattern = call.getString("pattern");
|
|
244
|
-
|
|
299
|
+
|
|
245
300
|
try {
|
|
246
301
|
List<String> keys = null;
|
|
247
302
|
|
|
@@ -260,6 +315,9 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
260
315
|
}
|
|
261
316
|
keys = sqliteStorage.keys(pattern);
|
|
262
317
|
break;
|
|
318
|
+
case "filesystem":
|
|
319
|
+
rejectUnsupportedFilesystem(call);
|
|
320
|
+
return;
|
|
263
321
|
case "preferences":
|
|
264
322
|
default:
|
|
265
323
|
if (sharedPrefsStorage == null) {
|
|
@@ -284,7 +342,7 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
284
342
|
@PluginMethod
|
|
285
343
|
public void size(PluginCall call) {
|
|
286
344
|
String storage = call.getString("storage", "preferences");
|
|
287
|
-
|
|
345
|
+
|
|
288
346
|
try {
|
|
289
347
|
JSObject result = new JSObject();
|
|
290
348
|
|
|
@@ -307,6 +365,9 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
307
365
|
result.put("total", sqliteSizeInfo.total);
|
|
308
366
|
result.put("count", sqliteSizeInfo.count);
|
|
309
367
|
break;
|
|
368
|
+
case "filesystem":
|
|
369
|
+
rejectUnsupportedFilesystem(call);
|
|
370
|
+
return;
|
|
310
371
|
case "preferences":
|
|
311
372
|
default:
|
|
312
373
|
if (sharedPrefsStorage == null) {
|
|
@@ -324,5 +385,108 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
324
385
|
call.reject("Failed to get size", e);
|
|
325
386
|
}
|
|
326
387
|
}
|
|
327
|
-
|
|
328
|
-
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Query SQLite-backed storage.
|
|
391
|
+
* Matches the optional `query` method in the JS contract:
|
|
392
|
+
* resolves { results: [{ key, value }] }. The JS SqliteAdapter applies the
|
|
393
|
+
* real condition by re-fetching/filtering, so this enumerates candidate
|
|
394
|
+
* rows.
|
|
395
|
+
*/
|
|
396
|
+
@PluginMethod
|
|
397
|
+
public void query(PluginCall call) {
|
|
398
|
+
String storage = call.getString("storage", "sqlite");
|
|
399
|
+
if (!"sqlite".equals(storage)) {
|
|
400
|
+
call.reject("Query is only supported for the 'sqlite' storage type");
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (sqliteStorage == null) {
|
|
404
|
+
call.reject("SQLite storage not available");
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
try {
|
|
409
|
+
List<Map<String, Object>> rows = sqliteStorage.query();
|
|
410
|
+
JSArray results = new JSArray();
|
|
411
|
+
for (Map<String, Object> row : rows) {
|
|
412
|
+
JSObject obj = new JSObject();
|
|
413
|
+
obj.put("key", row.get("key"));
|
|
414
|
+
obj.put("value", row.get("value"));
|
|
415
|
+
results.put(obj);
|
|
416
|
+
}
|
|
417
|
+
JSObject result = new JSObject();
|
|
418
|
+
result.put("results", results);
|
|
419
|
+
call.resolve(result);
|
|
420
|
+
} catch (Exception e) {
|
|
421
|
+
call.reject("Failed to query SQLite", e);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Android-specific: read an encrypted preference.
|
|
427
|
+
* Resolves { value: unknown }. Honors an optional `fileName`.
|
|
428
|
+
*/
|
|
429
|
+
@PluginMethod
|
|
430
|
+
public void getEncryptedPreference(PluginCall call) {
|
|
431
|
+
String key = call.getString("key");
|
|
432
|
+
if (key == null) {
|
|
433
|
+
call.reject("Key is required");
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
String fileName = call.getString("fileName");
|
|
437
|
+
|
|
438
|
+
try {
|
|
439
|
+
EncryptedStorage store = resolveEncryptedStore(fileName);
|
|
440
|
+
if (store == null) {
|
|
441
|
+
call.reject("Encrypted storage not available");
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
JSObject result = new JSObject();
|
|
445
|
+
result.put("value", store.get(key));
|
|
446
|
+
call.resolve(result);
|
|
447
|
+
} catch (Exception e) {
|
|
448
|
+
call.reject("Failed to read encrypted preference", e);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Android-specific: write an encrypted preference. Honors an optional
|
|
454
|
+
* `fileName`.
|
|
455
|
+
*/
|
|
456
|
+
@PluginMethod
|
|
457
|
+
public void setEncryptedPreference(PluginCall call) {
|
|
458
|
+
String key = call.getString("key");
|
|
459
|
+
if (key == null) {
|
|
460
|
+
call.reject("Key is required");
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
Object value = call.getData().opt("value");
|
|
464
|
+
String fileName = call.getString("fileName");
|
|
465
|
+
|
|
466
|
+
try {
|
|
467
|
+
EncryptedStorage store = resolveEncryptedStore(fileName);
|
|
468
|
+
if (store == null) {
|
|
469
|
+
call.reject("Encrypted storage not available");
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
if (!store.set(key, value)) {
|
|
473
|
+
call.reject("Failed to persist encrypted preference");
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
call.resolve();
|
|
477
|
+
} catch (Exception e) {
|
|
478
|
+
call.reject("Failed to write encrypted preference", e);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Returns the default encrypted store, or builds a file-specific one when a
|
|
484
|
+
* custom file name is supplied.
|
|
485
|
+
*/
|
|
486
|
+
private EncryptedStorage resolveEncryptedStore(String fileName) throws Exception {
|
|
487
|
+
if (fileName == null || fileName.isEmpty()) {
|
|
488
|
+
return encryptedStorage;
|
|
489
|
+
}
|
|
490
|
+
return new EncryptedStorage(getContext(), fileName);
|
|
491
|
+
}
|
|
492
|
+
}
|