strata-storage 2.0.3 → 2.1.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 (31) hide show
  1. package/Readme.md +109 -27
  2. package/android/src/main/java/com/strata/storage/EncryptedStorage.java +44 -3
  3. package/android/src/main/java/com/strata/storage/SQLiteStorage.java +35 -5
  4. package/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +43 -3
  5. package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +12 -3
  6. package/dist/android/src/main/java/com/strata/storage/EncryptedStorage.java +44 -3
  7. package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +35 -5
  8. package/dist/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +43 -3
  9. package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +12 -3
  10. package/dist/capacitor.d.ts.map +1 -1
  11. package/dist/capacitor.js +4 -3
  12. package/dist/core/Strata.d.ts +133 -2
  13. package/dist/core/Strata.d.ts.map +1 -1
  14. package/dist/core/Strata.js +133 -2
  15. package/dist/firebase.d.ts.map +1 -1
  16. package/dist/firebase.js +21 -1
  17. package/dist/ios/Plugin/KeychainStorage.swift +31 -9
  18. package/dist/ios/Plugin/SQLiteStorage.swift +29 -6
  19. package/dist/ios/Plugin/UserDefaultsStorage.swift +25 -7
  20. package/dist/package.json +5 -5
  21. package/dist/plugin/web.d.ts +10 -6
  22. package/dist/plugin/web.d.ts.map +1 -1
  23. package/dist/plugin/web.js +42 -13
  24. package/dist/utils/index.d.ts +0 -3
  25. package/dist/utils/index.d.ts.map +1 -1
  26. package/dist/utils/index.js +0 -3
  27. package/ios/Plugin/KeychainStorage.swift +31 -9
  28. package/ios/Plugin/SQLiteStorage.swift +29 -6
  29. package/ios/Plugin/UserDefaultsStorage.swift +25 -7
  30. package/package.json +15 -15
  31. package/dist/README.md +0 -179
package/Readme.md CHANGED
@@ -2,14 +2,64 @@
2
2
 
3
3
  ## 📚 Documentation
4
4
 
5
- - **[Getting Started](./docs/getting-started/installation.md)** - Installation and setup
5
+ ### Getting Started
6
+ - **[Installation](./docs/getting-started/installation.md)** - Installation and setup
6
7
  - **[Quick Start Guide](./docs/getting-started/quick-start.md)** - Get running in minutes
7
- - **[API Reference](./docs/api/README.md)** - Complete API documentation
8
8
  - **[Configuration](./docs/getting-started/configuration.md)** - Configuration options
9
- - **[Platform Guides](./docs/guides/platforms/web.md)** - Platform-specific guides
10
- - **[Examples](./docs/examples/README.md)** - Code examples and recipes
9
+
10
+ ### Core Documentation
11
+ - **[API Reference](./docs/api/README.md)** - Complete API documentation
12
+ - **[Core API](./docs/api/core/strata.md)** - Main Strata class
13
+ - **[Type Definitions](./docs/api/core/types.md)** - TypeScript types
14
+ - **[Error Handling](./docs/api/core/errors.md)** - Error types and handling
15
+
16
+ ### Storage Adapters
17
+ - **[Web Adapters](./docs/api/adapters/README.md#web-adapters)** - Browser storage
18
+ - [localStorage](./docs/api/adapters/web/localstorage.md)
19
+ - [sessionStorage](./docs/api/adapters/web/sessionstorage.md)
20
+ - [IndexedDB](./docs/api/adapters/web/indexeddb.md)
21
+ - [Cookies](./docs/api/adapters/web/cookies.md)
22
+ - [Cache API](./docs/api/adapters/web/cache.md)
23
+ - [Memory](./docs/api/adapters/web/memory.md)
24
+ - **[Capacitor Adapters](./docs/api/adapters/README.md#capacitor-adapters)** - Native storage
25
+ - [Preferences](./docs/api/adapters/capacitor/preferences.md)
26
+ - [Secure Storage](./docs/api/adapters/capacitor/secure.md)
27
+ - [SQLite](./docs/api/adapters/capacitor/sqlite.md)
28
+ - [Filesystem](./docs/api/adapters/capacitor/filesystem.md)
29
+
30
+ ### Advanced Features
31
+ - **[Encryption](./docs/guides/features/encryption.md)** - Data encryption guide
32
+ - **[Compression](./docs/guides/features/compression.md)** - Data compression
33
+ - **[TTL Management](./docs/api/features/ttl.md)** - Auto-expiration
34
+ - **[Cross-Tab Sync](./docs/guides/features/sync.md)** - Real-time synchronization
35
+ - **[Query Engine](./docs/guides/features/queries.md)** - MongoDB-like queries
36
+ - **[Migrations](./docs/guides/features/migrations.md)** - Data migration system
37
+
38
+ ### Platform Guides
39
+ - **[Web Platform](./docs/guides/platforms/web.md)** - Browser-specific features
40
+ - **[iOS Platform](./docs/guides/platforms/ios.md)** - iOS implementation
41
+ - **[Android Platform](./docs/guides/platforms/android.md)** - Android implementation
42
+ - **[Capacitor](./docs/guides/platforms/capacitor.md)** - Capacitor integration
43
+
44
+ ### Common Patterns
45
+ - **[Caching Strategies](./docs/guides/patterns/caching.md)** - Caching best practices
46
+ - **[Session Management](./docs/guides/patterns/sessions.md)** - User session handling
47
+
48
+ ### Examples
49
+ - **[Basic Usage](./docs/examples/basic-usage.md)** - Simple examples
50
+ - **[React Integration](./docs/examples/frameworks/react.md)** - React hooks and providers
51
+ - **[Vue Integration](./docs/examples/frameworks/vue.md)** - Vue composables
52
+ - **[Angular Integration](./docs/examples/frameworks/angular.md)** - Angular services
53
+ - **[Authentication](./docs/examples/user-auth.md)** - User authentication
54
+ - **[Shopping Cart](./docs/examples/shopping-cart.md)** - E-commerce example
55
+ - **[Form Persistence](./docs/examples/form-persistence.md)** - Form data saving
56
+ - **[Offline Support](./docs/examples/offline-support.md)** - Offline-first apps
57
+ - **[All Examples](./docs/examples/README.md)** - Complete examples list
58
+
59
+ ### Resources
11
60
  - **[GitHub](https://github.com/aoneahsan/strata-storage)** - Source code
12
61
  - **[NPM](https://www.npmjs.com/package/strata-storage)** - Package registry
62
+ - **[Example App](./examples/react-capacitor-app)** - Full demo application
13
63
 
14
64
  ---
15
65
 
@@ -108,13 +158,13 @@ await storage.set('data', value, { storage: 'firestore' });
108
158
  - ✅ **Filesystem** - File-based storage
109
159
 
110
160
  ### Advanced Features
111
- - ✅ **Encryption** - AES-GCM encryption with Web Crypto API
112
- - ✅ **Compression** - LZ-string compression algorithm
113
- - ✅ **Cross-Tab Sync** - Real-time synchronization across tabs
114
- - ✅ **Query Engine** - MongoDB-like queries for filtering data
115
- - ✅ **TTL Support** - Automatic expiration with sliding TTL
116
- - ✅ **Migration System** - Version-based data migrations
117
- - 🚧 **Framework Integrations** - React, Vue, Angular (coming soon)
161
+ - ✅ **[Encryption](./docs/guides/features/encryption.md)** - AES-GCM encryption with Web Crypto API
162
+ - ✅ **[Compression](./docs/guides/features/compression.md)** - LZ-string compression algorithm
163
+ - ✅ **[Cross-Tab Sync](./docs/guides/features/sync.md)** - Real-time synchronization across tabs
164
+ - ✅ **[Query Engine](./docs/guides/features/queries.md)** - MongoDB-like queries for filtering data
165
+ - ✅ **[TTL Support](./docs/api/features/ttl.md)** - Automatic expiration with sliding TTL
166
+ - ✅ **[Migration System](./docs/guides/features/migrations.md)** - Version-based data migrations
167
+ - **Framework Integrations** - [React](./docs/examples/frameworks/react.md), [Vue](./docs/examples/frameworks/vue.md), [Angular](./docs/examples/frameworks/angular.md)
118
168
 
119
169
  ## 📖 Basic Usage
120
170
 
@@ -135,40 +185,72 @@ await storage.set('key', value, {
135
185
  ttl: 3600000, // Expire in 1 hour
136
186
  encrypt: true, // Encrypt this value
137
187
  compress: true, // Compress if beneficial
138
- tags: ['user-data'] // Tag for grouping
188
+ tags: ['user-data'], // Tag for grouping
189
+ metadata: { // Attach metadata
190
+ version: 1,
191
+ source: 'api'
192
+ }
139
193
  });
140
194
 
141
- // Query data
195
+ // Query data with MongoDB-like syntax
142
196
  const results = await storage.query({
143
197
  tags: { $in: ['user-data'] },
144
- 'value.age': { $gte: 18 }
198
+ 'value.age': { $gte: 18 },
199
+ 'metadata.version': 1
145
200
  });
146
201
 
147
202
  // Subscribe to changes
148
203
  storage.subscribe((change) => {
149
204
  console.log(`${change.key} changed from ${change.oldValue} to ${change.newValue}`);
150
205
  });
206
+
207
+ // Check storage size
208
+ const size = await storage.size();
209
+ console.log(`Using ${size.total} bytes for ${size.count} items`);
151
210
  ```
152
211
 
153
- ## 🎯 Provider-less Architecture
212
+ ## 🎯 Why Strata Storage?
213
+
214
+ ### Provider-less Architecture
215
+ Like Zustand, Strata Storage works without providers, contexts, or wrappers. Just import and use - no setup required.
216
+
217
+ ### Zero Dependencies
218
+ Truly zero runtime dependencies. Everything is implemented from scratch for maximum control and minimal bundle size.
219
+
220
+ ### Universal Compatibility
221
+ - **One API** - Same code works on Web, iOS, and Android
222
+ - **Any Framework** - Works with React, Vue, Angular, or vanilla JavaScript
223
+ - **TypeScript First** - Full type safety and excellent IntelliSense
224
+ - **Tree-Shakeable** - Only bundle what you use
154
225
 
155
- Strata Storage follows a provider-less architecture similar to Zustand. The core library works everywhere with zero dependencies, and platform-specific features (like Capacitor) are completely optional.
226
+ ### Intelligent Storage Selection
227
+ Automatically selects the best available storage based on:
228
+ - Platform capabilities
229
+ - Data size and type
230
+ - Performance requirements
231
+ - Persistence needs
156
232
 
157
- - **Minimal by default** - Only includes web storage adapters
158
- - **Opt-in native features** - Explicitly add Capacitor support when needed
159
- - **Better tree-shaking** - Unused adapters are eliminated by bundlers
160
- - **Smaller bundle size** - Web-only projects don't include native code
233
+ ### Enterprise Ready
234
+ - **Encryption** - Built-in AES-GCM encryption
235
+ - **Compression** - Automatic data compression
236
+ - **TTL/Expiration** - Auto-cleanup of expired data
237
+ - **Sync** - Real-time cross-tab/device synchronization
238
+ - **Migrations** - Version-based data migrations
239
+ - **Querying** - MongoDB-like query engine
161
240
 
162
241
  ## 🏗 Project Status
163
242
 
164
- Currently in active development. Phase 1-5 completed:
165
- - ✅ Project setup and core architecture
166
- - ✅ Memory and web storage adapters
167
- - ✅ Capacitor plugin structure (now optional)
243
+ **Production Ready** - All major features implemented:
244
+ - ✅ Zero-dependency architecture
245
+ - ✅ Provider-less design (like Zustand)
246
+ - ✅ All web storage adapters (localStorage, IndexedDB, etc.)
247
+ - ✅ Complete Capacitor integration (iOS/Android)
248
+ - ✅ Native implementations (iOS Swift, Android Java)
168
249
  - ✅ Advanced features (encryption, compression, sync, query, TTL)
169
- - ✅ Provider-less architecture
170
- - 🚧 Native implementations (iOS/Android)
171
- - 🚧 Testing and documentation
250
+ - ✅ Framework integrations (React, Vue, Angular)
251
+ - Comprehensive documentation
252
+ - Full TypeScript support
253
+ - ✅ Example application with all features
172
254
 
173
255
  ## 📄 License
174
256
 
@@ -6,14 +6,20 @@ import android.os.Build;
6
6
  import androidx.security.crypto.EncryptedSharedPreferences;
7
7
  import androidx.security.crypto.MasterKey;
8
8
  import java.util.Set;
9
+ import java.util.HashSet;
9
10
  import java.util.Map;
10
11
 
11
12
  public class EncryptedStorage {
12
13
  private SharedPreferences encryptedPrefs;
13
14
  private SharedPreferences.Editor editor;
15
+ private static final String DEFAULT_NAME = "StrataSecureStorage";
16
+
17
+ public EncryptedStorage(Context context) throws Exception {
18
+ this(context, DEFAULT_NAME);
19
+ }
14
20
 
15
21
  public EncryptedStorage(Context context, String name) throws Exception {
16
- String fileName = name != null ? name : "StrataSecureStorage";
22
+ String fileName = name != null ? name : DEFAULT_NAME;
17
23
 
18
24
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
19
25
  MasterKey masterKey = new MasterKey.Builder(context)
@@ -51,12 +57,47 @@ public class EncryptedStorage {
51
57
  }
52
58
 
53
59
  public boolean clear() {
54
- editor.clear();
60
+ return clear(null);
61
+ }
62
+
63
+ public boolean clear(String prefix) {
64
+ if (prefix != null) {
65
+ // Clear only keys with the given prefix
66
+ Set<String> keysToRemove = new HashSet<>();
67
+ for (String key : encryptedPrefs.getAll().keySet()) {
68
+ if (key.startsWith(prefix) || key.contains(prefix)) {
69
+ keysToRemove.add(key);
70
+ }
71
+ }
72
+ for (String key : keysToRemove) {
73
+ editor.remove(key);
74
+ }
75
+ } else {
76
+ // Clear all keys
77
+ editor.clear();
78
+ }
55
79
  return editor.commit();
56
80
  }
57
81
 
58
82
  public Set<String> keys() {
59
- return encryptedPrefs.getAll().keySet();
83
+ return keys(null);
84
+ }
85
+
86
+ public Set<String> keys(String pattern) {
87
+ Set<String> allKeys = encryptedPrefs.getAll().keySet();
88
+
89
+ if (pattern == null) {
90
+ return allKeys;
91
+ }
92
+
93
+ // Filter keys by pattern
94
+ Set<String> filteredKeys = new HashSet<>();
95
+ for (String key : allKeys) {
96
+ if (key.startsWith(pattern) || key.contains(pattern)) {
97
+ filteredKeys.add(key);
98
+ }
99
+ }
100
+ return filteredKeys;
60
101
  }
61
102
 
62
103
  public boolean has(String key) {
@@ -13,6 +13,7 @@ import java.util.Map;
13
13
  public class SQLiteStorage extends SQLiteOpenHelper {
14
14
  private static final int DATABASE_VERSION = 1;
15
15
  private static final String TABLE_NAME = "strata_storage";
16
+ private static final String DEFAULT_DB_NAME = "strata.db";
16
17
 
17
18
  private static final String KEY_ID = "key";
18
19
  private static final String KEY_VALUE = "value";
@@ -22,8 +23,12 @@ public class SQLiteStorage extends SQLiteOpenHelper {
22
23
  private static final String KEY_TAGS = "tags";
23
24
  private static final String KEY_METADATA = "metadata";
24
25
 
26
+ public SQLiteStorage(Context context) {
27
+ this(context, DEFAULT_DB_NAME);
28
+ }
29
+
25
30
  public SQLiteStorage(Context context, String dbName) {
26
- super(context, dbName != null ? dbName : "strata.db", null, DATABASE_VERSION);
31
+ super(context, dbName != null ? dbName : DEFAULT_DB_NAME, null, DATABASE_VERSION);
27
32
  }
28
33
 
29
34
  @Override
@@ -112,18 +117,43 @@ public class SQLiteStorage extends SQLiteOpenHelper {
112
117
  }
113
118
 
114
119
  public boolean clear() {
120
+ return clear(null);
121
+ }
122
+
123
+ public boolean clear(String prefix) {
115
124
  SQLiteDatabase db = this.getWritableDatabase();
116
- db.delete(TABLE_NAME, null, null);
125
+ int result;
126
+
127
+ if (prefix != null) {
128
+ // Clear only keys with the given prefix
129
+ result = db.delete(TABLE_NAME, KEY_ID + " LIKE ?", new String[]{prefix + "%"});
130
+ } else {
131
+ // Clear all keys
132
+ result = db.delete(TABLE_NAME, null, null);
133
+ }
134
+
117
135
  db.close();
118
- return true;
136
+ return result >= 0;
119
137
  }
120
138
 
121
139
  public List<String> keys() {
140
+ return keys(null);
141
+ }
142
+
143
+ public List<String> keys(String pattern) {
122
144
  List<String> keys = new ArrayList<>();
123
- String selectQuery = "SELECT " + KEY_ID + " FROM " + TABLE_NAME;
145
+ String selectQuery;
146
+ String[] selectionArgs = null;
147
+
148
+ if (pattern != null) {
149
+ selectQuery = "SELECT " + KEY_ID + " FROM " + TABLE_NAME + " WHERE " + KEY_ID + " LIKE ?";
150
+ selectionArgs = new String[]{"% " + pattern + "%"};
151
+ } else {
152
+ selectQuery = "SELECT " + KEY_ID + " FROM " + TABLE_NAME;
153
+ }
124
154
 
125
155
  SQLiteDatabase db = this.getReadableDatabase();
126
- Cursor cursor = db.rawQuery(selectQuery, null);
156
+ Cursor cursor = db.rawQuery(selectQuery, selectionArgs);
127
157
 
128
158
  if (cursor.moveToFirst()) {
129
159
  do {
@@ -11,9 +11,14 @@ import org.json.JSONArray;
11
11
  public class SharedPreferencesStorage {
12
12
  private final SharedPreferences prefs;
13
13
  private final SharedPreferences.Editor editor;
14
+ private static final String DEFAULT_NAME = "StrataStorage";
15
+
16
+ public SharedPreferencesStorage(Context context) {
17
+ this(context, DEFAULT_NAME);
18
+ }
14
19
 
15
20
  public SharedPreferencesStorage(Context context, String name) {
16
- this.prefs = context.getSharedPreferences(name != null ? name : "StrataStorage", Context.MODE_PRIVATE);
21
+ this.prefs = context.getSharedPreferences(name != null ? name : DEFAULT_NAME, Context.MODE_PRIVATE);
17
22
  this.editor = prefs.edit();
18
23
  }
19
24
 
@@ -56,12 +61,47 @@ public class SharedPreferencesStorage {
56
61
  }
57
62
 
58
63
  public boolean clear() {
59
- editor.clear();
64
+ return clear(null);
65
+ }
66
+
67
+ public boolean clear(String prefix) {
68
+ if (prefix != null) {
69
+ // Clear only keys with the given prefix
70
+ Set<String> keysToRemove = new HashSet<>();
71
+ for (String key : prefs.getAll().keySet()) {
72
+ if (key.startsWith(prefix) || key.contains(prefix)) {
73
+ keysToRemove.add(key);
74
+ }
75
+ }
76
+ for (String key : keysToRemove) {
77
+ editor.remove(key);
78
+ }
79
+ } else {
80
+ // Clear all keys
81
+ editor.clear();
82
+ }
60
83
  return editor.commit();
61
84
  }
62
85
 
63
86
  public Set<String> keys() {
64
- return prefs.getAll().keySet();
87
+ return keys(null);
88
+ }
89
+
90
+ public Set<String> keys(String pattern) {
91
+ Set<String> allKeys = prefs.getAll().keySet();
92
+
93
+ if (pattern == null) {
94
+ return allKeys;
95
+ }
96
+
97
+ // Filter keys by pattern
98
+ Set<String> filteredKeys = new HashSet<>();
99
+ for (String key : allKeys) {
100
+ if (key.startsWith(pattern) || key.contains(pattern)) {
101
+ filteredKeys.add(key);
102
+ }
103
+ }
104
+ return filteredKeys;
65
105
  }
66
106
 
67
107
  public boolean has(String key) {
@@ -5,9 +5,13 @@ import com.getcapacitor.Plugin;
5
5
  import com.getcapacitor.PluginCall;
6
6
  import com.getcapacitor.PluginMethod;
7
7
  import com.getcapacitor.annotation.CapacitorPlugin;
8
+ import com.strata.storage.SharedPreferencesStorage;
9
+ import com.strata.storage.EncryptedStorage;
10
+ import com.strata.storage.SQLiteStorage;
8
11
  import org.json.JSONArray;
9
12
  import org.json.JSONException;
10
13
  import java.util.List;
14
+ import java.util.Set;
11
15
 
12
16
  /**
13
17
  * Main Capacitor plugin for Strata Storage
@@ -21,9 +25,14 @@ public class StrataStoragePlugin extends Plugin {
21
25
 
22
26
  @Override
23
27
  public void load() {
24
- sharedPrefsStorage = new SharedPreferencesStorage(getContext());
25
- encryptedStorage = new EncryptedStorage(getContext());
26
- sqliteStorage = new SQLiteStorage(getContext());
28
+ try {
29
+ sharedPrefsStorage = new SharedPreferencesStorage(getContext());
30
+ encryptedStorage = new EncryptedStorage(getContext());
31
+ sqliteStorage = new SQLiteStorage(getContext());
32
+ } catch (Exception e) {
33
+ // Log error but don't crash - some storage types may not be available
34
+ e.printStackTrace();
35
+ }
27
36
  }
28
37
 
29
38
  /**
@@ -6,14 +6,20 @@ import android.os.Build;
6
6
  import androidx.security.crypto.EncryptedSharedPreferences;
7
7
  import androidx.security.crypto.MasterKey;
8
8
  import java.util.Set;
9
+ import java.util.HashSet;
9
10
  import java.util.Map;
10
11
 
11
12
  public class EncryptedStorage {
12
13
  private SharedPreferences encryptedPrefs;
13
14
  private SharedPreferences.Editor editor;
15
+ private static final String DEFAULT_NAME = "StrataSecureStorage";
16
+
17
+ public EncryptedStorage(Context context) throws Exception {
18
+ this(context, DEFAULT_NAME);
19
+ }
14
20
 
15
21
  public EncryptedStorage(Context context, String name) throws Exception {
16
- String fileName = name != null ? name : "StrataSecureStorage";
22
+ String fileName = name != null ? name : DEFAULT_NAME;
17
23
 
18
24
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
19
25
  MasterKey masterKey = new MasterKey.Builder(context)
@@ -51,12 +57,47 @@ public class EncryptedStorage {
51
57
  }
52
58
 
53
59
  public boolean clear() {
54
- editor.clear();
60
+ return clear(null);
61
+ }
62
+
63
+ public boolean clear(String prefix) {
64
+ if (prefix != null) {
65
+ // Clear only keys with the given prefix
66
+ Set<String> keysToRemove = new HashSet<>();
67
+ for (String key : encryptedPrefs.getAll().keySet()) {
68
+ if (key.startsWith(prefix) || key.contains(prefix)) {
69
+ keysToRemove.add(key);
70
+ }
71
+ }
72
+ for (String key : keysToRemove) {
73
+ editor.remove(key);
74
+ }
75
+ } else {
76
+ // Clear all keys
77
+ editor.clear();
78
+ }
55
79
  return editor.commit();
56
80
  }
57
81
 
58
82
  public Set<String> keys() {
59
- return encryptedPrefs.getAll().keySet();
83
+ return keys(null);
84
+ }
85
+
86
+ public Set<String> keys(String pattern) {
87
+ Set<String> allKeys = encryptedPrefs.getAll().keySet();
88
+
89
+ if (pattern == null) {
90
+ return allKeys;
91
+ }
92
+
93
+ // Filter keys by pattern
94
+ Set<String> filteredKeys = new HashSet<>();
95
+ for (String key : allKeys) {
96
+ if (key.startsWith(pattern) || key.contains(pattern)) {
97
+ filteredKeys.add(key);
98
+ }
99
+ }
100
+ return filteredKeys;
60
101
  }
61
102
 
62
103
  public boolean has(String key) {
@@ -13,6 +13,7 @@ import java.util.Map;
13
13
  public class SQLiteStorage extends SQLiteOpenHelper {
14
14
  private static final int DATABASE_VERSION = 1;
15
15
  private static final String TABLE_NAME = "strata_storage";
16
+ private static final String DEFAULT_DB_NAME = "strata.db";
16
17
 
17
18
  private static final String KEY_ID = "key";
18
19
  private static final String KEY_VALUE = "value";
@@ -22,8 +23,12 @@ public class SQLiteStorage extends SQLiteOpenHelper {
22
23
  private static final String KEY_TAGS = "tags";
23
24
  private static final String KEY_METADATA = "metadata";
24
25
 
26
+ public SQLiteStorage(Context context) {
27
+ this(context, DEFAULT_DB_NAME);
28
+ }
29
+
25
30
  public SQLiteStorage(Context context, String dbName) {
26
- super(context, dbName != null ? dbName : "strata.db", null, DATABASE_VERSION);
31
+ super(context, dbName != null ? dbName : DEFAULT_DB_NAME, null, DATABASE_VERSION);
27
32
  }
28
33
 
29
34
  @Override
@@ -112,18 +117,43 @@ public class SQLiteStorage extends SQLiteOpenHelper {
112
117
  }
113
118
 
114
119
  public boolean clear() {
120
+ return clear(null);
121
+ }
122
+
123
+ public boolean clear(String prefix) {
115
124
  SQLiteDatabase db = this.getWritableDatabase();
116
- db.delete(TABLE_NAME, null, null);
125
+ int result;
126
+
127
+ if (prefix != null) {
128
+ // Clear only keys with the given prefix
129
+ result = db.delete(TABLE_NAME, KEY_ID + " LIKE ?", new String[]{prefix + "%"});
130
+ } else {
131
+ // Clear all keys
132
+ result = db.delete(TABLE_NAME, null, null);
133
+ }
134
+
117
135
  db.close();
118
- return true;
136
+ return result >= 0;
119
137
  }
120
138
 
121
139
  public List<String> keys() {
140
+ return keys(null);
141
+ }
142
+
143
+ public List<String> keys(String pattern) {
122
144
  List<String> keys = new ArrayList<>();
123
- String selectQuery = "SELECT " + KEY_ID + " FROM " + TABLE_NAME;
145
+ String selectQuery;
146
+ String[] selectionArgs = null;
147
+
148
+ if (pattern != null) {
149
+ selectQuery = "SELECT " + KEY_ID + " FROM " + TABLE_NAME + " WHERE " + KEY_ID + " LIKE ?";
150
+ selectionArgs = new String[]{"% " + pattern + "%"};
151
+ } else {
152
+ selectQuery = "SELECT " + KEY_ID + " FROM " + TABLE_NAME;
153
+ }
124
154
 
125
155
  SQLiteDatabase db = this.getReadableDatabase();
126
- Cursor cursor = db.rawQuery(selectQuery, null);
156
+ Cursor cursor = db.rawQuery(selectQuery, selectionArgs);
127
157
 
128
158
  if (cursor.moveToFirst()) {
129
159
  do {
@@ -11,9 +11,14 @@ import org.json.JSONArray;
11
11
  public class SharedPreferencesStorage {
12
12
  private final SharedPreferences prefs;
13
13
  private final SharedPreferences.Editor editor;
14
+ private static final String DEFAULT_NAME = "StrataStorage";
15
+
16
+ public SharedPreferencesStorage(Context context) {
17
+ this(context, DEFAULT_NAME);
18
+ }
14
19
 
15
20
  public SharedPreferencesStorage(Context context, String name) {
16
- this.prefs = context.getSharedPreferences(name != null ? name : "StrataStorage", Context.MODE_PRIVATE);
21
+ this.prefs = context.getSharedPreferences(name != null ? name : DEFAULT_NAME, Context.MODE_PRIVATE);
17
22
  this.editor = prefs.edit();
18
23
  }
19
24
 
@@ -56,12 +61,47 @@ public class SharedPreferencesStorage {
56
61
  }
57
62
 
58
63
  public boolean clear() {
59
- editor.clear();
64
+ return clear(null);
65
+ }
66
+
67
+ public boolean clear(String prefix) {
68
+ if (prefix != null) {
69
+ // Clear only keys with the given prefix
70
+ Set<String> keysToRemove = new HashSet<>();
71
+ for (String key : prefs.getAll().keySet()) {
72
+ if (key.startsWith(prefix) || key.contains(prefix)) {
73
+ keysToRemove.add(key);
74
+ }
75
+ }
76
+ for (String key : keysToRemove) {
77
+ editor.remove(key);
78
+ }
79
+ } else {
80
+ // Clear all keys
81
+ editor.clear();
82
+ }
60
83
  return editor.commit();
61
84
  }
62
85
 
63
86
  public Set<String> keys() {
64
- return prefs.getAll().keySet();
87
+ return keys(null);
88
+ }
89
+
90
+ public Set<String> keys(String pattern) {
91
+ Set<String> allKeys = prefs.getAll().keySet();
92
+
93
+ if (pattern == null) {
94
+ return allKeys;
95
+ }
96
+
97
+ // Filter keys by pattern
98
+ Set<String> filteredKeys = new HashSet<>();
99
+ for (String key : allKeys) {
100
+ if (key.startsWith(pattern) || key.contains(pattern)) {
101
+ filteredKeys.add(key);
102
+ }
103
+ }
104
+ return filteredKeys;
65
105
  }
66
106
 
67
107
  public boolean has(String key) {
@@ -5,9 +5,13 @@ import com.getcapacitor.Plugin;
5
5
  import com.getcapacitor.PluginCall;
6
6
  import com.getcapacitor.PluginMethod;
7
7
  import com.getcapacitor.annotation.CapacitorPlugin;
8
+ import com.strata.storage.SharedPreferencesStorage;
9
+ import com.strata.storage.EncryptedStorage;
10
+ import com.strata.storage.SQLiteStorage;
8
11
  import org.json.JSONArray;
9
12
  import org.json.JSONException;
10
13
  import java.util.List;
14
+ import java.util.Set;
11
15
 
12
16
  /**
13
17
  * Main Capacitor plugin for Strata Storage
@@ -21,9 +25,14 @@ public class StrataStoragePlugin extends Plugin {
21
25
 
22
26
  @Override
23
27
  public void load() {
24
- sharedPrefsStorage = new SharedPreferencesStorage(getContext());
25
- encryptedStorage = new EncryptedStorage(getContext());
26
- sqliteStorage = new SQLiteStorage(getContext());
28
+ try {
29
+ sharedPrefsStorage = new SharedPreferencesStorage(getContext());
30
+ encryptedStorage = new EncryptedStorage(getContext());
31
+ sqliteStorage = new SQLiteStorage(getContext());
32
+ } catch (Exception e) {
33
+ // Log error but don't crash - some storage types may not be available
34
+ e.printStackTrace();
35
+ }
27
36
  }
28
37
 
29
38
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"capacitor.d.ts","sourceRoot":"","sources":["../src/capacitor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAO5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAG3E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;GAGG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB9E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAMhD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAEnD"}
1
+ {"version":3,"file":"capacitor.d.ts","sourceRoot":"","sources":["../src/capacitor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAO5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAG3E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;GAGG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB9E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAShD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAEnD"}