strata-storage 1.5.0 → 1.6.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 (38) hide show
  1. package/dist/README.md +116 -0
  2. package/dist/adapters/capacitor/FilesystemAdapter.js +4 -4
  3. package/dist/adapters/capacitor/PreferencesAdapter.js +4 -4
  4. package/dist/adapters/capacitor/SecureAdapter.js +4 -4
  5. package/dist/adapters/capacitor/SqliteAdapter.js +4 -4
  6. package/dist/adapters/capacitor/index.js +4 -4
  7. package/dist/adapters/web/CacheAdapter.js +3 -3
  8. package/dist/adapters/web/CookieAdapter.js +2 -2
  9. package/dist/adapters/web/IndexedDBAdapter.js +3 -3
  10. package/dist/adapters/web/LocalStorageAdapter.js +3 -3
  11. package/dist/adapters/web/MemoryAdapter.js +2 -2
  12. package/dist/adapters/web/SessionStorageAdapter.js +1 -1
  13. package/dist/adapters/web/index.js +6 -6
  14. package/dist/android/src/main/java/com/strata/storage/EncryptedStorage.java +65 -0
  15. package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +147 -0
  16. package/dist/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +74 -0
  17. package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +256 -0
  18. package/dist/core/AdapterRegistry.js +1 -1
  19. package/dist/core/BaseAdapter.js +3 -3
  20. package/dist/core/StorageStrategy.js +1 -0
  21. package/dist/core/Strata.js +17 -17
  22. package/dist/features/compression.js +1 -1
  23. package/dist/features/encryption.d.ts.map +1 -1
  24. package/dist/features/encryption.js +6 -5
  25. package/dist/features/sync.js +1 -1
  26. package/dist/features/ttl.js +1 -1
  27. package/dist/index.js +24 -24
  28. package/dist/ios/Plugin/KeychainStorage.swift +87 -0
  29. package/dist/ios/Plugin/SQLiteStorage.swift +167 -0
  30. package/dist/ios/Plugin/StrataStoragePlugin.swift +204 -0
  31. package/dist/ios/Plugin/UserDefaultsStorage.swift +44 -0
  32. package/dist/package.json +14 -4
  33. package/dist/plugin/index.js +2 -2
  34. package/package.json +8 -26
  35. package/scripts/build.js +119 -14
  36. package/scripts/cli.js +6 -2
  37. package/scripts/configure.js +7 -3
  38. package/scripts/postinstall.js +6 -2
@@ -0,0 +1,256 @@
1
+ package com.stratastorage;
2
+
3
+ import com.getcapacitor.JSObject;
4
+ import com.getcapacitor.Plugin;
5
+ import com.getcapacitor.PluginCall;
6
+ import com.getcapacitor.PluginMethod;
7
+ import com.getcapacitor.annotation.CapacitorPlugin;
8
+ import org.json.JSONArray;
9
+ import org.json.JSONException;
10
+ import java.util.List;
11
+
12
+ /**
13
+ * Main Capacitor plugin for Strata Storage
14
+ * Coordinates between different storage types on Android
15
+ */
16
+ @CapacitorPlugin(name = "StrataStorage")
17
+ public class StrataStoragePlugin extends Plugin {
18
+ private SharedPreferencesStorage sharedPrefsStorage;
19
+ private EncryptedStorage encryptedStorage;
20
+ private SQLiteStorage sqliteStorage;
21
+
22
+ @Override
23
+ public void load() {
24
+ sharedPrefsStorage = new SharedPreferencesStorage(getContext());
25
+ encryptedStorage = new EncryptedStorage(getContext());
26
+ sqliteStorage = new SQLiteStorage(getContext());
27
+ }
28
+
29
+ /**
30
+ * Check if storage is available
31
+ */
32
+ @PluginMethod
33
+ public void isAvailable(PluginCall call) {
34
+ JSObject result = new JSObject();
35
+ result.put("available", true);
36
+ result.put("platform", "android");
37
+
38
+ JSObject adapters = new JSObject();
39
+ adapters.put("preferences", true);
40
+ adapters.put("secure", true);
41
+ adapters.put("sqlite", true);
42
+ adapters.put("filesystem", true);
43
+ result.put("adapters", adapters);
44
+
45
+ call.resolve(result);
46
+ }
47
+
48
+ /**
49
+ * Get value from storage
50
+ */
51
+ @PluginMethod
52
+ public void get(PluginCall call) {
53
+ String key = call.getString("key");
54
+ if (key == null) {
55
+ call.reject("Key is required");
56
+ return;
57
+ }
58
+
59
+ String storage = call.getString("storage", "preferences");
60
+
61
+ try {
62
+ Object value = null;
63
+
64
+ switch (storage) {
65
+ case "secure":
66
+ value = encryptedStorage.get(key);
67
+ break;
68
+ case "sqlite":
69
+ value = sqliteStorage.get(key);
70
+ break;
71
+ case "preferences":
72
+ default:
73
+ value = sharedPrefsStorage.get(key);
74
+ break;
75
+ }
76
+
77
+ JSObject result = new JSObject();
78
+ result.put("value", value);
79
+ call.resolve(result);
80
+ } catch (Exception e) {
81
+ call.reject("Failed to get value", e);
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Set value in storage
87
+ */
88
+ @PluginMethod
89
+ public void set(PluginCall call) {
90
+ String key = call.getString("key");
91
+ if (key == null) {
92
+ call.reject("Key is required");
93
+ return;
94
+ }
95
+
96
+ Object value = call.getData().opt("value");
97
+ String storage = call.getString("storage", "preferences");
98
+
99
+ try {
100
+ switch (storage) {
101
+ case "secure":
102
+ encryptedStorage.set(key, value);
103
+ break;
104
+ case "sqlite":
105
+ sqliteStorage.set(key, value);
106
+ break;
107
+ case "preferences":
108
+ default:
109
+ sharedPrefsStorage.set(key, value);
110
+ break;
111
+ }
112
+
113
+ call.resolve();
114
+ } catch (Exception e) {
115
+ call.reject("Failed to set value", e);
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Remove value from storage
121
+ */
122
+ @PluginMethod
123
+ public void remove(PluginCall call) {
124
+ String key = call.getString("key");
125
+ if (key == null) {
126
+ call.reject("Key is required");
127
+ return;
128
+ }
129
+
130
+ String storage = call.getString("storage", "preferences");
131
+
132
+ try {
133
+ switch (storage) {
134
+ case "secure":
135
+ encryptedStorage.remove(key);
136
+ break;
137
+ case "sqlite":
138
+ sqliteStorage.remove(key);
139
+ break;
140
+ case "preferences":
141
+ default:
142
+ sharedPrefsStorage.remove(key);
143
+ break;
144
+ }
145
+
146
+ call.resolve();
147
+ } catch (Exception e) {
148
+ call.reject("Failed to remove value", e);
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Clear storage
154
+ */
155
+ @PluginMethod
156
+ public void clear(PluginCall call) {
157
+ String storage = call.getString("storage", "preferences");
158
+ String prefix = call.getString("prefix");
159
+
160
+ try {
161
+ switch (storage) {
162
+ case "secure":
163
+ encryptedStorage.clear(prefix);
164
+ break;
165
+ case "sqlite":
166
+ sqliteStorage.clear(prefix);
167
+ break;
168
+ case "preferences":
169
+ default:
170
+ sharedPrefsStorage.clear(prefix);
171
+ break;
172
+ }
173
+
174
+ call.resolve();
175
+ } catch (Exception e) {
176
+ call.reject("Failed to clear storage", e);
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Get all keys from storage
182
+ */
183
+ @PluginMethod
184
+ public void keys(PluginCall call) {
185
+ String storage = call.getString("storage", "preferences");
186
+ String pattern = call.getString("pattern");
187
+
188
+ try {
189
+ List<String> keys = null;
190
+
191
+ switch (storage) {
192
+ case "secure":
193
+ keys = encryptedStorage.keys(pattern);
194
+ break;
195
+ case "sqlite":
196
+ keys = sqliteStorage.keys(pattern);
197
+ break;
198
+ case "preferences":
199
+ default:
200
+ keys = sharedPrefsStorage.keys(pattern);
201
+ break;
202
+ }
203
+
204
+ JSObject result = new JSObject();
205
+ result.put("keys", new JSONArray(keys));
206
+ call.resolve(result);
207
+ } catch (Exception e) {
208
+ call.reject("Failed to get keys", e);
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Get storage size information
214
+ */
215
+ @PluginMethod
216
+ public void size(PluginCall call) {
217
+ String storage = call.getString("storage", "preferences");
218
+
219
+ try {
220
+ SizeInfo sizeInfo = null;
221
+
222
+ switch (storage) {
223
+ case "secure":
224
+ sizeInfo = encryptedStorage.size();
225
+ break;
226
+ case "sqlite":
227
+ sizeInfo = sqliteStorage.size();
228
+ break;
229
+ case "preferences":
230
+ default:
231
+ sizeInfo = sharedPrefsStorage.size();
232
+ break;
233
+ }
234
+
235
+ JSObject result = new JSObject();
236
+ result.put("total", sizeInfo.total);
237
+ result.put("count", sizeInfo.count);
238
+ call.resolve(result);
239
+ } catch (Exception e) {
240
+ call.reject("Failed to get size", e);
241
+ }
242
+ }
243
+
244
+ /**
245
+ * Size information class
246
+ */
247
+ static class SizeInfo {
248
+ public final long total;
249
+ public final int count;
250
+
251
+ public SizeInfo(long total, int count) {
252
+ this.total = total;
253
+ this.count = count;
254
+ }
255
+ }
256
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Registry for managing storage adapters
3
3
  */
4
- import { AdapterNotAvailableError } from '@/utils/errors';
4
+ import { AdapterNotAvailableError } from "../utils/errors.js";
5
5
  /**
6
6
  * Adapter registry for managing storage adapters
7
7
  */
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Base adapter implementation with common functionality
3
3
  */
4
- import { NotSupportedError } from '@/utils/errors';
5
- import { EventEmitter, matchGlob, getObjectSize } from '@/utils';
6
- import { QueryEngine } from '@/features/query';
4
+ import { NotSupportedError } from "../utils/errors.js";
5
+ import { EventEmitter, matchGlob, getObjectSize } from "../utils/index.js";
6
+ import { QueryEngine } from "../features/query.js";
7
7
  /**
8
8
  * Abstract base adapter that implements common functionality
9
9
  */
@@ -2,6 +2,7 @@
2
2
  * Storage strategy implementation for automatic adapter selection
3
3
  */
4
4
  import { StorageStrategy } from '@/types';
5
+ import { AdapterRegistry } from "./AdapterRegistry.js";
5
6
  /**
6
7
  * Strategy manager for selecting appropriate storage adapters
7
8
  */
@@ -2,13 +2,13 @@
2
2
  * Strata Storage - Main entry point
3
3
  * Zero-dependency universal storage solution
4
4
  */
5
- import { AdapterRegistry } from './AdapterRegistry';
6
- import { isBrowser, isNode, isCapacitor } from '@/utils';
7
- import { StorageError, EncryptionError } from '@/utils/errors';
8
- import { EncryptionManager } from '@/features/encryption';
9
- import { CompressionManager } from '@/features/compression';
10
- import { SyncManager } from '@/features/sync';
11
- import { TTLManager } from '@/features/ttl';
5
+ import { AdapterRegistry } from "./AdapterRegistry.js";
6
+ import { isBrowser, isNode, isCapacitor } from "../utils/index.js";
7
+ import { StorageError, EncryptionError } from "../utils/errors.js";
8
+ import { EncryptionManager } from "../features/encryption.js";
9
+ import { CompressionManager } from "../features/compression.js";
10
+ import { SyncManager } from "../features/sync.js";
11
+ import { TTLManager } from "../features/ttl.js";
12
12
  /**
13
13
  * Main Strata class - unified storage interface
14
14
  */
@@ -489,12 +489,12 @@ export class Strata {
489
489
  // Register adapters based on platform
490
490
  if (this.platform === 'web') {
491
491
  // Dynamically import and register web adapters
492
- const { MemoryAdapter } = await import('@/adapters/web/MemoryAdapter');
493
- const { LocalStorageAdapter } = await import('@/adapters/web/LocalStorageAdapter');
494
- const { SessionStorageAdapter } = await import('@/adapters/web/SessionStorageAdapter');
495
- const { IndexedDBAdapter } = await import('@/adapters/web/IndexedDBAdapter');
496
- const { CookieAdapter } = await import('@/adapters/web/CookieAdapter');
497
- const { CacheAdapter } = await import('@/adapters/web/CacheAdapter');
492
+ const { MemoryAdapter } = await import("../adapters/web/MemoryAdapter.js");
493
+ const { LocalStorageAdapter } = await import("../adapters/web/LocalStorageAdapter.js");
494
+ const { SessionStorageAdapter } = await import("../adapters/web/SessionStorageAdapter.js");
495
+ const { IndexedDBAdapter } = await import("../adapters/web/IndexedDBAdapter.js");
496
+ const { CookieAdapter } = await import("../adapters/web/CookieAdapter.js");
497
+ const { CacheAdapter } = await import("../adapters/web/CacheAdapter.js");
498
498
  this.registry.register(new MemoryAdapter());
499
499
  this.registry.register(new LocalStorageAdapter());
500
500
  this.registry.register(new SessionStorageAdapter());
@@ -503,10 +503,10 @@ export class Strata {
503
503
  this.registry.register(new CacheAdapter());
504
504
  // If running in Capacitor, also register native adapters
505
505
  if (isCapacitor()) {
506
- const { PreferencesAdapter } = await import('@/adapters/capacitor/PreferencesAdapter');
507
- const { SqliteAdapter } = await import('@/adapters/capacitor/SqliteAdapter');
508
- const { SecureAdapter } = await import('@/adapters/capacitor/SecureAdapter');
509
- const { FilesystemAdapter } = await import('@/adapters/capacitor/FilesystemAdapter');
506
+ const { PreferencesAdapter } = await import("../adapters/capacitor/PreferencesAdapter.js");
507
+ const { SqliteAdapter } = await import("../adapters/capacitor/SqliteAdapter.js");
508
+ const { SecureAdapter } = await import("../adapters/capacitor/SecureAdapter.js");
509
+ const { FilesystemAdapter } = await import("../adapters/capacitor/FilesystemAdapter.js");
510
510
  this.registry.register(new PreferencesAdapter());
511
511
  this.registry.register(new SqliteAdapter());
512
512
  this.registry.register(new SecureAdapter());
@@ -2,7 +2,7 @@
2
2
  * Compression Feature - Pure JavaScript LZ-string implementation
3
3
  * Zero-dependency compression/decompression for storage values
4
4
  */
5
- import { CompressionError } from '@/utils/errors';
5
+ import { CompressionError } from "../utils/errors.js";
6
6
  /**
7
7
  * Compression manager using pure JavaScript LZ-string algorithm
8
8
  */
@@ -1 +1 @@
1
- {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/features/encryption.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAClC,SAAS,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,QAAQ,CAAqC;gBAEzC,MAAM,GAAE,gBAAqB;IASzC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACG,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAyCtE;;OAEG;IACG,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAiCtF;;OAEG;YACW,SAAS;IA0CvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,gBAAgB,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM;IAc7C;;OAEG;IACG,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAU1C"}
1
+ {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/features/encryption.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAClC,SAAS,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,QAAQ,CAAqC;gBAEzC,MAAM,GAAE,gBAAqB;IASzC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACG,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA6CtE;;OAEG;IACG,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAiCtF;;OAEG;YACW,SAAS;IA8CvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,gBAAgB,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM;IAc7C;;OAEG;IACG,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAU1C"}
@@ -2,7 +2,7 @@
2
2
  * Encryption Feature - Web Crypto API implementation
3
3
  * Zero-dependency encryption/decryption for storage values
4
4
  */
5
- import { EncryptionError } from '@/utils/errors';
5
+ import { EncryptionError } from "../utils/errors.js";
6
6
  /**
7
7
  * Encryption manager using Web Crypto API
8
8
  */
@@ -48,8 +48,8 @@ export class EncryptionManager {
48
48
  // Convert to base64 for storage
49
49
  return {
50
50
  data: this.bufferToBase64(encryptedBuffer),
51
- salt: this.bufferToBase64(salt),
52
- iv: this.bufferToBase64(iv),
51
+ salt: this.bufferToBase64(salt.buffer.slice(salt.byteOffset, salt.byteOffset + salt.byteLength)),
52
+ iv: this.bufferToBase64(iv.buffer.slice(iv.byteOffset, iv.byteOffset + iv.byteLength)),
53
53
  algorithm: this.config.algorithm,
54
54
  iterations: this.config.iterations,
55
55
  };
@@ -91,7 +91,8 @@ export class EncryptionManager {
91
91
  */
92
92
  async deriveKey(password, salt, iterations = this.config.iterations) {
93
93
  // Check cache
94
- const cacheKey = `${password}-${this.bufferToBase64(salt)}-${iterations}`;
94
+ const saltBuffer = salt.buffer.slice(salt.byteOffset, salt.byteOffset + salt.byteLength);
95
+ const cacheKey = `${password}-${this.bufferToBase64(saltBuffer)}-${iterations}`;
95
96
  if (this.keyCache.has(cacheKey)) {
96
97
  return this.keyCache.get(cacheKey);
97
98
  }
@@ -105,7 +106,7 @@ export class EncryptionManager {
105
106
  // Derive key using PBKDF2
106
107
  const key = await crypto.subtle.deriveKey({
107
108
  name: 'PBKDF2',
108
- salt: salt,
109
+ salt: saltBuffer,
109
110
  iterations: iterations,
110
111
  hash: 'SHA-256',
111
112
  }, keyMaterial, {
@@ -2,7 +2,7 @@
2
2
  * Cross-tab Synchronization Feature
3
3
  * Zero-dependency implementation using BroadcastChannel and storage events
4
4
  */
5
- import { EventEmitter } from '@/utils';
5
+ import { EventEmitter } from "../utils/index.js";
6
6
  /**
7
7
  * Cross-tab synchronization manager
8
8
  */
@@ -2,7 +2,7 @@
2
2
  * TTL (Time To Live) Manager
3
3
  * Handles automatic expiration of storage items
4
4
  */
5
- import { EventEmitter } from '@/utils';
5
+ import { EventEmitter } from "../utils/index.js";
6
6
  /**
7
7
  * TTL Manager for handling item expiration
8
8
  */
package/dist/index.js CHANGED
@@ -4,37 +4,37 @@
4
4
  * @packageDocumentation
5
5
  */
6
6
  // Main export
7
- export { Strata } from './core/Strata';
8
- import { Strata } from './core/Strata';
7
+ export { Strata } from "./core/Strata.js";
8
+ import { Strata } from "./core/Strata.js";
9
9
  // Errors
10
- export { StrataError, StorageError, NotFoundError, QuotaExceededError, AdapterNotAvailableError, NotSupportedError, EncryptionError, CompressionError, SerializationError, ValidationError, TransactionError, MigrationError, SyncError, isStrataError, isQuotaError, } from './utils/errors';
10
+ export { StrataError, StorageError, NotFoundError, QuotaExceededError, AdapterNotAvailableError, NotSupportedError, EncryptionError, CompressionError, SerializationError, ValidationError, TransactionError, MigrationError, SyncError, isStrataError, isQuotaError, } from "./utils/errors.js";
11
11
  // Utilities (selected exports for advanced users)
12
- export { serialize, deserialize, deepClone, deepMerge, formatBytes, parseSize, EventEmitter, } from './utils';
12
+ export { serialize, deserialize, deepClone, deepMerge, formatBytes, parseSize, EventEmitter, } from "./utils/index.js";
13
13
  // Base classes for custom adapters
14
- export { BaseAdapter } from './core/BaseAdapter';
15
- export { AdapterRegistry } from './core/AdapterRegistry';
14
+ export { BaseAdapter } from "./core/BaseAdapter.js";
15
+ export { AdapterRegistry } from "./core/AdapterRegistry.js";
16
16
  // Features
17
- export { EncryptionManager } from './features/encryption';
18
- export { CompressionManager } from './features/compression';
19
- export { SyncManager, createSyncManager } from './features/sync';
20
- export { QueryEngine, createQueryEngine } from './features/query';
21
- export { TTLManager, createTTLManager } from './features/ttl';
22
- export { MigrationManager } from './features/migration';
17
+ export { EncryptionManager } from "./features/encryption.js";
18
+ export { CompressionManager } from "./features/compression.js";
19
+ export { SyncManager, createSyncManager } from "./features/sync.js";
20
+ export { QueryEngine, createQueryEngine } from "./features/query.js";
21
+ export { TTLManager, createTTLManager } from "./features/ttl.js";
22
+ export { MigrationManager } from "./features/migration.js";
23
23
  // Plugin definitions and main plugin
24
- export * from './plugin/definitions';
25
- export { StrataStorage } from './plugin';
24
+ export * from "./plugin/definitions.js";
25
+ export { StrataStorage } from "./plugin/index.js";
26
26
  // Web Storage Adapters (for advanced users who want direct adapter access)
27
- export { MemoryAdapter } from './adapters/web/MemoryAdapter';
28
- export { LocalStorageAdapter } from './adapters/web/LocalStorageAdapter';
29
- export { SessionStorageAdapter } from './adapters/web/SessionStorageAdapter';
30
- export { IndexedDBAdapter } from './adapters/web/IndexedDBAdapter';
31
- export { CookieAdapter } from './adapters/web/CookieAdapter';
32
- export { CacheAdapter } from './adapters/web/CacheAdapter';
27
+ export { MemoryAdapter } from "./adapters/web/MemoryAdapter.js";
28
+ export { LocalStorageAdapter } from "./adapters/web/LocalStorageAdapter.js";
29
+ export { SessionStorageAdapter } from "./adapters/web/SessionStorageAdapter.js";
30
+ export { IndexedDBAdapter } from "./adapters/web/IndexedDBAdapter.js";
31
+ export { CookieAdapter } from "./adapters/web/CookieAdapter.js";
32
+ export { CacheAdapter } from "./adapters/web/CacheAdapter.js";
33
33
  // Capacitor Storage Adapters
34
- export { PreferencesAdapter } from './adapters/capacitor/PreferencesAdapter';
35
- export { SqliteAdapter } from './adapters/capacitor/SqliteAdapter';
36
- export { SecureAdapter } from './adapters/capacitor/SecureAdapter';
37
- export { FilesystemAdapter } from './adapters/capacitor/FilesystemAdapter';
34
+ export { PreferencesAdapter } from "./adapters/capacitor/PreferencesAdapter.js";
35
+ export { SqliteAdapter } from "./adapters/capacitor/SqliteAdapter.js";
36
+ export { SecureAdapter } from "./adapters/capacitor/SecureAdapter.js";
37
+ export { FilesystemAdapter } from "./adapters/capacitor/FilesystemAdapter.js";
38
38
  /**
39
39
  * Create a new Strata instance with optional configuration
40
40
  *
@@ -0,0 +1,87 @@
1
+ import Foundation
2
+ import Security
3
+
4
+ @objc public class KeychainStorage: NSObject {
5
+ private let service: String
6
+ private let accessGroup: String?
7
+
8
+ @objc public init(service: String? = nil, accessGroup: String? = nil) {
9
+ self.service = service ?? Bundle.main.bundleIdentifier ?? "StrataStorage"
10
+ self.accessGroup = accessGroup
11
+ super.init()
12
+ }
13
+
14
+ @objc public func set(key: String, value: Data) -> Bool {
15
+ let query = createQuery(key: key)
16
+ SecItemDelete(query as CFDictionary)
17
+
18
+ var newItem = query
19
+ newItem[kSecValueData as String] = value
20
+
21
+ let status = SecItemAdd(newItem as CFDictionary, nil)
22
+ return status == errSecSuccess
23
+ }
24
+
25
+ @objc public func get(key: String) -> Data? {
26
+ var query = createQuery(key: key)
27
+ query[kSecReturnData as String] = true
28
+ query[kSecMatchLimit as String] = kSecMatchLimitOne
29
+
30
+ var result: AnyObject?
31
+ let status = SecItemCopyMatching(query as CFDictionary, &result)
32
+
33
+ guard status == errSecSuccess else { return nil }
34
+ return result as? Data
35
+ }
36
+
37
+ @objc public func remove(key: String) -> Bool {
38
+ let query = createQuery(key: key)
39
+ let status = SecItemDelete(query as CFDictionary)
40
+ return status == errSecSuccess
41
+ }
42
+
43
+ @objc public func clear() -> Bool {
44
+ let query: [String: Any] = [
45
+ kSecClass as String: kSecClassGenericPassword,
46
+ kSecAttrService as String: service
47
+ ]
48
+ let status = SecItemDelete(query as CFDictionary)
49
+ return status == errSecSuccess || status == errSecItemNotFound
50
+ }
51
+
52
+ @objc public func keys() -> [String] {
53
+ var query: [String: Any] = [
54
+ kSecClass as String: kSecClassGenericPassword,
55
+ kSecAttrService as String: service,
56
+ kSecReturnAttributes as String: true,
57
+ kSecMatchLimit as String: kSecMatchLimitAll
58
+ ]
59
+
60
+ if let accessGroup = accessGroup {
61
+ query[kSecAttrAccessGroup as String] = accessGroup
62
+ }
63
+
64
+ var result: AnyObject?
65
+ let status = SecItemCopyMatching(query as CFDictionary, &result)
66
+
67
+ guard status == errSecSuccess,
68
+ let items = result as? [[String: Any]] else { return [] }
69
+
70
+ return items.compactMap { $0[kSecAttrAccount as String] as? String }
71
+ }
72
+
73
+ private func createQuery(key: String) -> [String: Any] {
74
+ var query: [String: Any] = [
75
+ kSecClass as String: kSecClassGenericPassword,
76
+ kSecAttrService as String: service,
77
+ kSecAttrAccount as String: key,
78
+ kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
79
+ ]
80
+
81
+ if let accessGroup = accessGroup {
82
+ query[kSecAttrAccessGroup as String] = accessGroup
83
+ }
84
+
85
+ return query
86
+ }
87
+ }