strata-storage 1.4.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.
- package/StrataStorage.podspec +17 -0
- package/dist/README.md +116 -0
- package/dist/adapters/capacitor/FilesystemAdapter.js +4 -4
- package/dist/adapters/capacitor/PreferencesAdapter.js +4 -4
- package/dist/adapters/capacitor/SecureAdapter.js +4 -4
- package/dist/adapters/capacitor/SqliteAdapter.js +4 -4
- package/dist/adapters/capacitor/index.js +4 -4
- package/dist/adapters/web/CacheAdapter.js +3 -3
- package/dist/adapters/web/CookieAdapter.js +2 -2
- package/dist/adapters/web/IndexedDBAdapter.js +3 -3
- package/dist/adapters/web/LocalStorageAdapter.js +3 -3
- package/dist/adapters/web/MemoryAdapter.js +2 -2
- package/dist/adapters/web/SessionStorageAdapter.js +1 -1
- package/dist/adapters/web/index.js +6 -6
- package/dist/android/src/main/java/com/strata/storage/EncryptedStorage.java +65 -0
- package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +147 -0
- package/dist/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +74 -0
- package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +256 -0
- package/dist/core/AdapterRegistry.js +1 -1
- package/dist/core/BaseAdapter.js +3 -3
- package/dist/core/StorageStrategy.js +1 -0
- package/dist/core/Strata.js +17 -17
- package/dist/features/compression.js +1 -1
- package/dist/features/encryption.d.ts.map +1 -1
- package/dist/features/encryption.js +6 -5
- package/dist/features/sync.js +1 -1
- package/dist/features/ttl.js +1 -1
- package/dist/index.js +24 -24
- package/dist/ios/Plugin/KeychainStorage.swift +87 -0
- package/dist/ios/Plugin/SQLiteStorage.swift +167 -0
- package/dist/ios/Plugin/StrataStoragePlugin.swift +204 -0
- package/dist/ios/Plugin/UserDefaultsStorage.swift +44 -0
- package/dist/package.json +14 -4
- package/dist/plugin/index.js +2 -2
- package/package.json +10 -27
- package/scripts/build.js +119 -14
- package/scripts/cli.js +6 -2
- package/scripts/configure.js +7 -3
- 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
|
+
}
|
package/dist/core/BaseAdapter.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Base adapter implementation with common functionality
|
|
3
3
|
*/
|
|
4
|
-
import { NotSupportedError } from
|
|
5
|
-
import { EventEmitter, matchGlob, getObjectSize } from
|
|
6
|
-
import { QueryEngine } from
|
|
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
|
*/
|
package/dist/core/Strata.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Strata Storage - Main entry point
|
|
3
3
|
* Zero-dependency universal storage solution
|
|
4
4
|
*/
|
|
5
|
-
import { AdapterRegistry } from
|
|
6
|
-
import { isBrowser, isNode, isCapacitor } from
|
|
7
|
-
import { StorageError, EncryptionError } from
|
|
8
|
-
import { EncryptionManager } from
|
|
9
|
-
import { CompressionManager } from
|
|
10
|
-
import { SyncManager } from
|
|
11
|
-
import { TTLManager } from
|
|
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(
|
|
493
|
-
const { LocalStorageAdapter } = await import(
|
|
494
|
-
const { SessionStorageAdapter } = await import(
|
|
495
|
-
const { IndexedDBAdapter } = await import(
|
|
496
|
-
const { CookieAdapter } = await import(
|
|
497
|
-
const { CacheAdapter } = await import(
|
|
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(
|
|
507
|
-
const { SqliteAdapter } = await import(
|
|
508
|
-
const { SecureAdapter } = await import(
|
|
509
|
-
const { FilesystemAdapter } = await import(
|
|
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
|
|
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;
|
|
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
|
|
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
|
|
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:
|
|
109
|
+
salt: saltBuffer,
|
|
109
110
|
iterations: iterations,
|
|
110
111
|
hash: 'SHA-256',
|
|
111
112
|
}, keyMaterial, {
|
package/dist/features/sync.js
CHANGED
package/dist/features/ttl.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -4,37 +4,37 @@
|
|
|
4
4
|
* @packageDocumentation
|
|
5
5
|
*/
|
|
6
6
|
// Main export
|
|
7
|
-
export { Strata } from
|
|
8
|
-
import { Strata } from
|
|
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
|
|
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
|
|
12
|
+
export { serialize, deserialize, deepClone, deepMerge, formatBytes, parseSize, EventEmitter, } from "./utils/index.js";
|
|
13
13
|
// Base classes for custom adapters
|
|
14
|
-
export { BaseAdapter } from
|
|
15
|
-
export { AdapterRegistry } from
|
|
14
|
+
export { BaseAdapter } from "./core/BaseAdapter.js";
|
|
15
|
+
export { AdapterRegistry } from "./core/AdapterRegistry.js";
|
|
16
16
|
// Features
|
|
17
|
-
export { EncryptionManager } from
|
|
18
|
-
export { CompressionManager } from
|
|
19
|
-
export { SyncManager, createSyncManager } from
|
|
20
|
-
export { QueryEngine, createQueryEngine } from
|
|
21
|
-
export { TTLManager, createTTLManager } from
|
|
22
|
-
export { MigrationManager } from
|
|
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
|
|
25
|
-
export { StrataStorage } from
|
|
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
|
|
28
|
-
export { LocalStorageAdapter } from
|
|
29
|
-
export { SessionStorageAdapter } from
|
|
30
|
-
export { IndexedDBAdapter } from
|
|
31
|
-
export { CookieAdapter } from
|
|
32
|
-
export { CacheAdapter } from
|
|
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
|
|
35
|
-
export { SqliteAdapter } from
|
|
36
|
-
export { SecureAdapter } from
|
|
37
|
-
export { FilesystemAdapter } from
|
|
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
|
+
}
|