strata-storage 2.4.3 → 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 +115 -261
- package/README.md +426 -182
- 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 +426 -182
- 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/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 +31 -20
- package/scripts/build.js +16 -5
- package/scripts/configure.js +2 -6
- package/scripts/postinstall.js +2 -2
- package/Readme.md +0 -271
|
@@ -3,30 +3,41 @@ import Capacitor
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Main Capacitor plugin for Strata Storage
|
|
6
|
-
* Coordinates between different storage types on iOS
|
|
6
|
+
* Coordinates between different storage types on iOS.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: Method registration with the Capacitor bridge lives in
|
|
9
|
+
* StrataStoragePlugin.m (CAP_PLUGIN / CAP_PLUGIN_METHOD). Keep the two in
|
|
10
|
+
* sync when adding or renaming methods.
|
|
7
11
|
*/
|
|
8
12
|
@objc(StrataStoragePlugin)
|
|
9
13
|
public class StrataStoragePlugin: CAPPlugin {
|
|
10
14
|
private let userDefaultsStorage = UserDefaultsStorage()
|
|
11
15
|
private let keychainStorage = KeychainStorage()
|
|
12
16
|
private let sqliteStorage = SQLiteStorage()
|
|
13
|
-
|
|
17
|
+
|
|
18
|
+
/// Storage types that have a real native backend on iOS.
|
|
19
|
+
/// `filesystem` is intentionally absent — see isAvailable / resolveUnsupported.
|
|
20
|
+
private let supportedStorageTypes: Set<String> = ["preferences", "secure", "sqlite"]
|
|
21
|
+
|
|
14
22
|
/**
|
|
15
|
-
* Check if storage is available
|
|
23
|
+
* Check if a specific storage type is available.
|
|
24
|
+
* Matches the JS contract: resolves `{ available: boolean }`.
|
|
16
25
|
*/
|
|
17
26
|
@objc func isAvailable(_ call: CAPPluginCall) {
|
|
27
|
+
let storage = call.getString("storage") ?? "preferences"
|
|
18
28
|
call.resolve([
|
|
19
|
-
"available":
|
|
20
|
-
"platform": "ios",
|
|
21
|
-
"adapters": [
|
|
22
|
-
"preferences": true,
|
|
23
|
-
"secure": true,
|
|
24
|
-
"sqlite": true,
|
|
25
|
-
"filesystem": true
|
|
26
|
-
]
|
|
29
|
+
"available": supportedStorageTypes.contains(storage)
|
|
27
30
|
])
|
|
28
31
|
}
|
|
29
|
-
|
|
32
|
+
|
|
33
|
+
private func rejectUnsupportedFilesystem(_ call: CAPPluginCall) {
|
|
34
|
+
call.reject(
|
|
35
|
+
"Filesystem storage is not implemented in the native iOS plugin. " +
|
|
36
|
+
"Use the 'preferences', 'secure', or 'sqlite' storage types, or a " +
|
|
37
|
+
"web/Capacitor Filesystem-backed adapter."
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
30
41
|
/**
|
|
31
42
|
* Get value from storage
|
|
32
43
|
*/
|
|
@@ -35,31 +46,34 @@ public class StrataStoragePlugin: CAPPlugin {
|
|
|
35
46
|
call.reject("Key is required")
|
|
36
47
|
return
|
|
37
48
|
}
|
|
38
|
-
|
|
49
|
+
|
|
39
50
|
let storage = call.getString("storage") ?? "preferences"
|
|
40
|
-
|
|
51
|
+
|
|
41
52
|
do {
|
|
42
53
|
let value: Any?
|
|
43
|
-
|
|
54
|
+
|
|
44
55
|
switch storage {
|
|
45
56
|
case "secure":
|
|
46
57
|
value = try keychainStorage.get(key: key)
|
|
47
58
|
case "sqlite":
|
|
48
|
-
value =
|
|
59
|
+
value = sqliteStorage.get(key: key)
|
|
60
|
+
case "filesystem":
|
|
61
|
+
rejectUnsupportedFilesystem(call)
|
|
62
|
+
return
|
|
49
63
|
case "preferences":
|
|
50
64
|
fallthrough
|
|
51
65
|
default:
|
|
52
66
|
value = userDefaultsStorage.get(key: key)
|
|
53
67
|
}
|
|
54
|
-
|
|
68
|
+
|
|
55
69
|
call.resolve([
|
|
56
70
|
"value": value ?? NSNull()
|
|
57
71
|
])
|
|
58
72
|
} catch {
|
|
59
|
-
call.reject("Failed to get value", error
|
|
73
|
+
call.reject("Failed to get value", nil, error)
|
|
60
74
|
}
|
|
61
75
|
}
|
|
62
|
-
|
|
76
|
+
|
|
63
77
|
/**
|
|
64
78
|
* Set value in storage
|
|
65
79
|
*/
|
|
@@ -68,28 +82,35 @@ public class StrataStoragePlugin: CAPPlugin {
|
|
|
68
82
|
call.reject("Key is required")
|
|
69
83
|
return
|
|
70
84
|
}
|
|
71
|
-
|
|
85
|
+
|
|
72
86
|
let value = call.getValue("value") ?? NSNull()
|
|
73
87
|
let storage = call.getString("storage") ?? "preferences"
|
|
74
|
-
|
|
88
|
+
|
|
75
89
|
do {
|
|
76
90
|
switch storage {
|
|
77
91
|
case "secure":
|
|
78
|
-
try keychainStorage.set(key: key, value: value)
|
|
92
|
+
_ = try keychainStorage.set(key: key, value: value)
|
|
79
93
|
case "sqlite":
|
|
80
|
-
try sqliteStorage.set(key: key, value: value)
|
|
94
|
+
let ok = try sqliteStorage.set(key: key, value: value)
|
|
95
|
+
if !ok {
|
|
96
|
+
call.reject("Failed to write value to SQLite")
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
case "filesystem":
|
|
100
|
+
rejectUnsupportedFilesystem(call)
|
|
101
|
+
return
|
|
81
102
|
case "preferences":
|
|
82
103
|
fallthrough
|
|
83
104
|
default:
|
|
84
105
|
userDefaultsStorage.set(key: key, value: value)
|
|
85
106
|
}
|
|
86
|
-
|
|
107
|
+
|
|
87
108
|
call.resolve()
|
|
88
109
|
} catch {
|
|
89
|
-
call.reject("Failed to set value", error
|
|
110
|
+
call.reject("Failed to set value", nil, error)
|
|
90
111
|
}
|
|
91
112
|
}
|
|
92
|
-
|
|
113
|
+
|
|
93
114
|
/**
|
|
94
115
|
* Remove value from storage
|
|
95
116
|
*/
|
|
@@ -98,107 +119,235 @@ public class StrataStoragePlugin: CAPPlugin {
|
|
|
98
119
|
call.reject("Key is required")
|
|
99
120
|
return
|
|
100
121
|
}
|
|
101
|
-
|
|
122
|
+
|
|
102
123
|
let storage = call.getString("storage") ?? "preferences"
|
|
103
|
-
|
|
124
|
+
|
|
104
125
|
do {
|
|
105
126
|
switch storage {
|
|
106
127
|
case "secure":
|
|
107
|
-
try keychainStorage.remove(key: key)
|
|
128
|
+
_ = try keychainStorage.remove(key: key)
|
|
108
129
|
case "sqlite":
|
|
109
|
-
|
|
130
|
+
_ = sqliteStorage.remove(key: key)
|
|
131
|
+
case "filesystem":
|
|
132
|
+
rejectUnsupportedFilesystem(call)
|
|
133
|
+
return
|
|
110
134
|
case "preferences":
|
|
111
135
|
fallthrough
|
|
112
136
|
default:
|
|
113
137
|
userDefaultsStorage.remove(key: key)
|
|
114
138
|
}
|
|
115
|
-
|
|
139
|
+
|
|
116
140
|
call.resolve()
|
|
117
141
|
} catch {
|
|
118
|
-
call.reject("Failed to remove value", error
|
|
142
|
+
call.reject("Failed to remove value", nil, error)
|
|
119
143
|
}
|
|
120
144
|
}
|
|
121
|
-
|
|
145
|
+
|
|
122
146
|
/**
|
|
123
|
-
* Clear storage
|
|
147
|
+
* Clear storage.
|
|
148
|
+
* The JS contract sends an optional `pattern`. The native backends accept
|
|
149
|
+
* a prefix; we use `pattern` as that prefix (prefix/contains matching).
|
|
124
150
|
*/
|
|
125
151
|
@objc func clear(_ call: CAPPluginCall) {
|
|
126
152
|
let storage = call.getString("storage") ?? "preferences"
|
|
127
|
-
|
|
128
|
-
|
|
153
|
+
// Accept both `pattern` (JS contract) and legacy `prefix`.
|
|
154
|
+
let prefix = call.getString("pattern") ?? call.getString("prefix")
|
|
155
|
+
|
|
129
156
|
do {
|
|
130
157
|
switch storage {
|
|
131
158
|
case "secure":
|
|
132
|
-
try keychainStorage.clear(prefix: prefix)
|
|
159
|
+
_ = try keychainStorage.clear(prefix: prefix)
|
|
133
160
|
case "sqlite":
|
|
134
|
-
|
|
161
|
+
_ = sqliteStorage.clear(prefix: prefix)
|
|
162
|
+
case "filesystem":
|
|
163
|
+
rejectUnsupportedFilesystem(call)
|
|
164
|
+
return
|
|
135
165
|
case "preferences":
|
|
136
166
|
fallthrough
|
|
137
167
|
default:
|
|
138
168
|
userDefaultsStorage.clear(prefix: prefix)
|
|
139
169
|
}
|
|
140
|
-
|
|
170
|
+
|
|
141
171
|
call.resolve()
|
|
142
172
|
} catch {
|
|
143
|
-
call.reject("Failed to clear storage", error
|
|
173
|
+
call.reject("Failed to clear storage", nil, error)
|
|
144
174
|
}
|
|
145
175
|
}
|
|
146
|
-
|
|
176
|
+
|
|
147
177
|
/**
|
|
148
178
|
* Get all keys from storage
|
|
149
179
|
*/
|
|
150
180
|
@objc func keys(_ call: CAPPluginCall) {
|
|
151
181
|
let storage = call.getString("storage") ?? "preferences"
|
|
152
182
|
let pattern = call.getString("pattern")
|
|
153
|
-
|
|
183
|
+
|
|
154
184
|
do {
|
|
155
185
|
let keys: [String]
|
|
156
|
-
|
|
186
|
+
|
|
157
187
|
switch storage {
|
|
158
188
|
case "secure":
|
|
159
189
|
keys = try keychainStorage.keys(pattern: pattern)
|
|
160
190
|
case "sqlite":
|
|
161
|
-
keys =
|
|
191
|
+
keys = sqliteStorage.keys(pattern: pattern)
|
|
192
|
+
case "filesystem":
|
|
193
|
+
rejectUnsupportedFilesystem(call)
|
|
194
|
+
return
|
|
162
195
|
case "preferences":
|
|
163
196
|
fallthrough
|
|
164
197
|
default:
|
|
165
198
|
keys = userDefaultsStorage.keys(pattern: pattern)
|
|
166
199
|
}
|
|
167
|
-
|
|
200
|
+
|
|
168
201
|
call.resolve([
|
|
169
202
|
"keys": keys
|
|
170
203
|
])
|
|
171
204
|
} catch {
|
|
172
|
-
call.reject("Failed to get keys", error
|
|
205
|
+
call.reject("Failed to get keys", nil, error)
|
|
173
206
|
}
|
|
174
207
|
}
|
|
175
|
-
|
|
208
|
+
|
|
176
209
|
/**
|
|
177
210
|
* Get storage size information
|
|
178
211
|
*/
|
|
179
212
|
@objc func size(_ call: CAPPluginCall) {
|
|
180
213
|
let storage = call.getString("storage") ?? "preferences"
|
|
181
|
-
|
|
214
|
+
|
|
182
215
|
do {
|
|
183
216
|
let sizeInfo: (total: Int, count: Int)
|
|
184
|
-
|
|
217
|
+
|
|
185
218
|
switch storage {
|
|
186
219
|
case "secure":
|
|
187
220
|
sizeInfo = try keychainStorage.size()
|
|
188
221
|
case "sqlite":
|
|
189
222
|
sizeInfo = try sqliteStorage.size()
|
|
223
|
+
case "filesystem":
|
|
224
|
+
rejectUnsupportedFilesystem(call)
|
|
225
|
+
return
|
|
190
226
|
case "preferences":
|
|
191
227
|
fallthrough
|
|
192
228
|
default:
|
|
193
229
|
sizeInfo = userDefaultsStorage.size()
|
|
194
230
|
}
|
|
195
|
-
|
|
231
|
+
|
|
196
232
|
call.resolve([
|
|
197
233
|
"total": sizeInfo.total,
|
|
198
234
|
"count": sizeInfo.count
|
|
199
235
|
])
|
|
200
236
|
} catch {
|
|
201
|
-
call.reject("Failed to get size", error
|
|
237
|
+
call.reject("Failed to get size", nil, error)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Query SQLite-backed storage.
|
|
243
|
+
* Matches the optional `query` method in the JS contract:
|
|
244
|
+
* resolves `{ results: [{ key, value }] }`.
|
|
245
|
+
*/
|
|
246
|
+
@objc func query(_ call: CAPPluginCall) {
|
|
247
|
+
let storage = call.getString("storage") ?? "sqlite"
|
|
248
|
+
|
|
249
|
+
guard storage == "sqlite" else {
|
|
250
|
+
call.reject("Query is only supported for the 'sqlite' storage type")
|
|
251
|
+
return
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let condition = call.getObject("condition") ?? [:]
|
|
255
|
+
let results = sqliteStorage.query(condition: condition)
|
|
256
|
+
call.resolve([
|
|
257
|
+
"results": results
|
|
258
|
+
])
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* iOS-specific: read a UserDefaults value.
|
|
263
|
+
* Resolves `{ value: unknown }`.
|
|
264
|
+
*/
|
|
265
|
+
@objc func getUserDefaults(_ call: CAPPluginCall) {
|
|
266
|
+
guard let key = call.getString("key") else {
|
|
267
|
+
call.reject("Key is required")
|
|
268
|
+
return
|
|
269
|
+
}
|
|
270
|
+
let suiteName = call.getString("suiteName")
|
|
271
|
+
let store = suiteName != nil ? UserDefaultsStorage(suiteName: suiteName) : userDefaultsStorage
|
|
272
|
+
call.resolve([
|
|
273
|
+
"value": store.get(key: key) ?? NSNull()
|
|
274
|
+
])
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* iOS-specific: write a UserDefaults value.
|
|
279
|
+
*/
|
|
280
|
+
@objc func setUserDefaults(_ call: CAPPluginCall) {
|
|
281
|
+
guard let key = call.getString("key") else {
|
|
282
|
+
call.reject("Key is required")
|
|
283
|
+
return
|
|
284
|
+
}
|
|
285
|
+
let value = call.getValue("value") ?? NSNull()
|
|
286
|
+
let suiteName = call.getString("suiteName")
|
|
287
|
+
let store = suiteName != nil ? UserDefaultsStorage(suiteName: suiteName) : userDefaultsStorage
|
|
288
|
+
_ = store.set(key: key, value: value)
|
|
289
|
+
call.resolve()
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* iOS-specific: read a Keychain value. Resolves `{ value: string | null }`.
|
|
294
|
+
*/
|
|
295
|
+
@objc func getKeychain(_ call: CAPPluginCall) {
|
|
296
|
+
guard let key = call.getString("key") else {
|
|
297
|
+
call.reject("Key is required")
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
let service = call.getString("service")
|
|
301
|
+
let accessGroup = call.getString("accessGroup")
|
|
302
|
+
let store = (service != nil || accessGroup != nil)
|
|
303
|
+
? KeychainStorage(service: service, accessGroup: accessGroup)
|
|
304
|
+
: keychainStorage
|
|
305
|
+
|
|
306
|
+
do {
|
|
307
|
+
let value = try store.get(key: key)
|
|
308
|
+
// The JS contract types this as `string | null`. Serialize
|
|
309
|
+
// non-string values to a JSON string so the bridge stays typed.
|
|
310
|
+
if let value = value {
|
|
311
|
+
if let str = value as? String {
|
|
312
|
+
call.resolve(["value": str])
|
|
313
|
+
} else if let data = try? JSONSerialization.data(withJSONObject: value, options: []),
|
|
314
|
+
let str = String(data: data, encoding: .utf8) {
|
|
315
|
+
call.resolve(["value": str])
|
|
316
|
+
} else {
|
|
317
|
+
call.resolve(["value": NSNull()])
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
call.resolve(["value": NSNull()])
|
|
321
|
+
}
|
|
322
|
+
} catch {
|
|
323
|
+
call.reject("Failed to read keychain item", nil, error)
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* iOS-specific: write a Keychain value, honoring the `accessible` option.
|
|
329
|
+
*/
|
|
330
|
+
@objc func setKeychain(_ call: CAPPluginCall) {
|
|
331
|
+
guard let key = call.getString("key") else {
|
|
332
|
+
call.reject("Key is required")
|
|
333
|
+
return
|
|
334
|
+
}
|
|
335
|
+
guard let value = call.getString("value") else {
|
|
336
|
+
call.reject("Value is required and must be a string")
|
|
337
|
+
return
|
|
338
|
+
}
|
|
339
|
+
let service = call.getString("service")
|
|
340
|
+
let accessGroup = call.getString("accessGroup")
|
|
341
|
+
let accessible = call.getString("accessible")
|
|
342
|
+
let store = (service != nil || accessGroup != nil)
|
|
343
|
+
? KeychainStorage(service: service, accessGroup: accessGroup)
|
|
344
|
+
: keychainStorage
|
|
345
|
+
|
|
346
|
+
do {
|
|
347
|
+
_ = try store.set(key: key, value: value, accessible: accessible)
|
|
348
|
+
call.resolve()
|
|
349
|
+
} catch {
|
|
350
|
+
call.reject("Failed to write keychain item", nil, error)
|
|
202
351
|
}
|
|
203
352
|
}
|
|
204
|
-
}
|
|
353
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strata-storage",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Zero-dependency universal storage plugin providing a unified API for all storage operations across web, Android, and iOS platforms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,9 +13,7 @@
|
|
|
13
13
|
"StrataStorage.podspec",
|
|
14
14
|
"AI-INTEGRATION-GUIDE.md"
|
|
15
15
|
],
|
|
16
|
-
"bin":
|
|
17
|
-
"strata-storage": "./scripts/cli.js"
|
|
18
|
-
},
|
|
16
|
+
"bin": "./scripts/cli.js",
|
|
19
17
|
"exports": {
|
|
20
18
|
".": {
|
|
21
19
|
"types": "./dist/index.d.ts",
|
|
@@ -82,11 +80,18 @@
|
|
|
82
80
|
"homepage": "https://github.com/aoneahsan/strata-storage#readme",
|
|
83
81
|
"peerDependencies": {
|
|
84
82
|
"@angular/core": ">=21.0.6",
|
|
83
|
+
"@angular/forms": ">=21.0.6",
|
|
85
84
|
"@capacitor/core": ">=8.0.0",
|
|
86
85
|
"react": ">=19.2.3",
|
|
87
86
|
"vue": ">=3.5.26"
|
|
88
87
|
},
|
|
89
88
|
"peerDependenciesMeta": {
|
|
89
|
+
"@angular/core": {
|
|
90
|
+
"optional": true
|
|
91
|
+
},
|
|
92
|
+
"@angular/forms": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
90
95
|
"@capacitor/core": {
|
|
91
96
|
"optional": true
|
|
92
97
|
},
|
|
@@ -95,28 +100,33 @@
|
|
|
95
100
|
},
|
|
96
101
|
"vue": {
|
|
97
102
|
"optional": true
|
|
98
|
-
},
|
|
99
|
-
"@angular/core": {
|
|
100
|
-
"optional": true
|
|
101
103
|
}
|
|
102
104
|
},
|
|
103
105
|
"devDependencies": {
|
|
104
|
-
"@
|
|
105
|
-
"@
|
|
106
|
-
"@
|
|
107
|
-
"@
|
|
108
|
-
"@
|
|
109
|
-
"
|
|
106
|
+
"@angular/common": "^21.2.14",
|
|
107
|
+
"@angular/core": "^21.2.14",
|
|
108
|
+
"@angular/forms": "^21.2.14",
|
|
109
|
+
"@capacitor/core": "^8.3.4",
|
|
110
|
+
"@types/node": "^25.9.1",
|
|
111
|
+
"@types/react": "^19.2.15",
|
|
112
|
+
"@typescript-eslint/eslint-plugin": "^8.60.0",
|
|
113
|
+
"@typescript-eslint/parser": "^8.60.0",
|
|
114
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
115
|
+
"eslint": "^10.4.0",
|
|
110
116
|
"eslint-config-prettier": "^10.1.8",
|
|
111
117
|
"eslint-plugin-prettier": "^5.5.5",
|
|
112
|
-
"jsdom": "^
|
|
113
|
-
"prettier": "^3.8.
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"
|
|
118
|
+
"jsdom": "^29.1.1",
|
|
119
|
+
"prettier": "^3.8.3",
|
|
120
|
+
"react": "^19.2.6",
|
|
121
|
+
"rxjs": "^7.8.2",
|
|
122
|
+
"typescript": "^6.0.3",
|
|
123
|
+
"typescript-eslint": "^8.60.0",
|
|
124
|
+
"vitest": "^4.1.7",
|
|
125
|
+
"vue": "^3.5.34",
|
|
126
|
+
"zone.js": "~0.16.0"
|
|
117
127
|
},
|
|
118
128
|
"engines": {
|
|
119
|
-
"node": ">=
|
|
129
|
+
"node": ">=24.13.0"
|
|
120
130
|
},
|
|
121
131
|
"capacitor": {
|
|
122
132
|
"ios": {
|
|
@@ -126,5 +136,6 @@
|
|
|
126
136
|
"src": "android",
|
|
127
137
|
"androidModule": "strata-storage"
|
|
128
138
|
}
|
|
129
|
-
}
|
|
139
|
+
},
|
|
140
|
+
"packageManager": "yarn@4.14.1"
|
|
130
141
|
}
|
package/scripts/build.js
CHANGED
|
@@ -26,7 +26,7 @@ fs.mkdirSync(distDir, { recursive: true });
|
|
|
26
26
|
// Compile TypeScript to ESM
|
|
27
27
|
console.log('📦 Building ES Modules...');
|
|
28
28
|
try {
|
|
29
|
-
execSync('
|
|
29
|
+
execSync('yarn exec tsc', { stdio: 'inherit', cwd: rootDir });
|
|
30
30
|
} catch (error) {
|
|
31
31
|
console.error('❌ Build failed');
|
|
32
32
|
process.exit(1);
|
|
@@ -141,6 +141,18 @@ const distPackageJson = {
|
|
|
141
141
|
'./firebase': {
|
|
142
142
|
types: './firebase.d.ts',
|
|
143
143
|
default: './firebase.js'
|
|
144
|
+
},
|
|
145
|
+
'./react': {
|
|
146
|
+
types: './integrations/react/index.d.ts',
|
|
147
|
+
default: './integrations/react/index.js'
|
|
148
|
+
},
|
|
149
|
+
'./vue': {
|
|
150
|
+
types: './integrations/vue/index.d.ts',
|
|
151
|
+
default: './integrations/vue/index.js'
|
|
152
|
+
},
|
|
153
|
+
'./angular': {
|
|
154
|
+
types: './integrations/angular/index.d.ts',
|
|
155
|
+
default: './integrations/angular/index.js'
|
|
144
156
|
}
|
|
145
157
|
},
|
|
146
158
|
author: packageJson.author,
|
|
@@ -151,9 +163,8 @@ const distPackageJson = {
|
|
|
151
163
|
peerDependenciesMeta: packageJson.peerDependenciesMeta,
|
|
152
164
|
capacitor: packageJson.capacitor,
|
|
153
165
|
sideEffects: false,
|
|
154
|
-
engines
|
|
155
|
-
|
|
156
|
-
}
|
|
166
|
+
// Mirror the root engines so the published manifest never drifts from it.
|
|
167
|
+
engines: packageJson.engines || { node: '>=18.0.0' }
|
|
157
168
|
};
|
|
158
169
|
|
|
159
170
|
fs.writeFileSync(
|
|
@@ -162,4 +173,4 @@ fs.writeFileSync(
|
|
|
162
173
|
);
|
|
163
174
|
|
|
164
175
|
console.log('✅ Build completed successfully!');
|
|
165
|
-
console.log(`📂 Output: ${distDir}`);
|
|
176
|
+
console.log(`📂 Output: ${distDir}`);
|
package/scripts/configure.js
CHANGED
|
@@ -399,11 +399,7 @@ async function installDependencies(config) {
|
|
|
399
399
|
}
|
|
400
400
|
|
|
401
401
|
// Install command
|
|
402
|
-
const command =
|
|
403
|
-
? `yarn add ${deps.join(' ')}`
|
|
404
|
-
: config.packageManager === 'pnpm'
|
|
405
|
-
? `pnpm add ${deps.join(' ')}`
|
|
406
|
-
: `npm install ${deps.join(' ')}`;
|
|
402
|
+
const command = `yarn add ${deps.join(' ')}`;
|
|
407
403
|
|
|
408
404
|
try {
|
|
409
405
|
log.info(`Running: ${command}`);
|
|
@@ -445,4 +441,4 @@ configure().catch((error) => {
|
|
|
445
441
|
log.error('Configuration failed:');
|
|
446
442
|
console.error(error);
|
|
447
443
|
process.exit(1);
|
|
448
|
-
});
|
|
444
|
+
});
|
package/scripts/postinstall.js
CHANGED
|
@@ -30,7 +30,7 @@ if (isCapacitorProject) {
|
|
|
30
30
|
console.log('📱 Capacitor Support Available (Optional):');
|
|
31
31
|
console.log(' import { registerCapacitorAdapters } from "strata-storage/capacitor";');
|
|
32
32
|
console.log(' await registerCapacitorAdapters(storage);');
|
|
33
|
-
console.log(' Run "
|
|
33
|
+
console.log(' Run "yarn cap sync" to sync native code\n');
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
console.log('✨ Features:');
|
|
@@ -41,4 +41,4 @@ console.log(' • Built-in encryption & compression');
|
|
|
41
41
|
console.log(' • Cross-tab synchronization\n');
|
|
42
42
|
|
|
43
43
|
console.log('📖 Documentation: https://github.com/aoneahsan/strata-storage');
|
|
44
|
-
console.log('⭐ Star us on GitHub: https://github.com/aoneahsan/strata-storage\n');
|
|
44
|
+
console.log('⭐ Star us on GitHub: https://github.com/aoneahsan/strata-storage\n');
|