strata-storage 2.4.2 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/AI-INTEGRATION-GUIDE.md +208 -0
  2. package/README.md +427 -181
  3. package/android/AGENTS.md +34 -0
  4. package/android/CLAUDE.md +51 -0
  5. package/android/src/main/java/com/strata/storage/SQLiteStorage.java +35 -0
  6. package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +191 -27
  7. package/dist/README.md +427 -181
  8. package/dist/adapters/capacitor/FilesystemAdapter.d.ts.map +1 -1
  9. package/dist/adapters/capacitor/FilesystemAdapter.js +2 -1
  10. package/dist/adapters/capacitor/PreferencesAdapter.d.ts.map +1 -1
  11. package/dist/adapters/capacitor/PreferencesAdapter.js +2 -1
  12. package/dist/adapters/capacitor/SecureAdapter.d.ts.map +1 -1
  13. package/dist/adapters/capacitor/SecureAdapter.js +2 -1
  14. package/dist/adapters/capacitor/SqliteAdapter.d.ts.map +1 -1
  15. package/dist/adapters/capacitor/SqliteAdapter.js +2 -1
  16. package/dist/adapters/web/CacheAdapter.d.ts.map +1 -1
  17. package/dist/adapters/web/CacheAdapter.js +11 -3
  18. package/dist/adapters/web/CookieAdapter.d.ts +37 -1
  19. package/dist/adapters/web/CookieAdapter.d.ts.map +1 -1
  20. package/dist/adapters/web/CookieAdapter.js +89 -9
  21. package/dist/adapters/web/IndexedDBAdapter.d.ts.map +1 -1
  22. package/dist/adapters/web/IndexedDBAdapter.js +10 -2
  23. package/dist/adapters/web/LocalStorageAdapter.d.ts +31 -0
  24. package/dist/adapters/web/LocalStorageAdapter.d.ts.map +1 -1
  25. package/dist/adapters/web/LocalStorageAdapter.js +92 -19
  26. package/dist/adapters/web/MemoryAdapter.d.ts +24 -0
  27. package/dist/adapters/web/MemoryAdapter.d.ts.map +1 -1
  28. package/dist/adapters/web/MemoryAdapter.js +69 -18
  29. package/dist/adapters/web/SessionStorageAdapter.d.ts +24 -0
  30. package/dist/adapters/web/SessionStorageAdapter.d.ts.map +1 -1
  31. package/dist/adapters/web/SessionStorageAdapter.js +71 -9
  32. package/dist/adapters/web/URLAdapter.d.ts +59 -0
  33. package/dist/adapters/web/URLAdapter.d.ts.map +1 -0
  34. package/dist/adapters/web/URLAdapter.js +234 -0
  35. package/dist/adapters/web/index.d.ts +1 -0
  36. package/dist/adapters/web/index.d.ts.map +1 -1
  37. package/dist/adapters/web/index.js +1 -0
  38. package/dist/android/AGENTS.md +34 -0
  39. package/dist/android/CLAUDE.md +51 -0
  40. package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +35 -0
  41. package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +191 -27
  42. package/dist/capacitor.d.ts.map +1 -1
  43. package/dist/capacitor.js +2 -1
  44. package/dist/config/support.d.ts +10 -0
  45. package/dist/config/support.d.ts.map +1 -0
  46. package/dist/config/support.js +9 -0
  47. package/dist/core/BaseAdapter.d.ts +8 -0
  48. package/dist/core/BaseAdapter.d.ts.map +1 -1
  49. package/dist/core/BaseAdapter.js +34 -14
  50. package/dist/core/Strata.d.ts +56 -2
  51. package/dist/core/Strata.d.ts.map +1 -1
  52. package/dist/core/Strata.js +501 -53
  53. package/dist/features/encryption.d.ts.map +1 -1
  54. package/dist/features/encryption.js +3 -2
  55. package/dist/features/integrity.d.ts +16 -0
  56. package/dist/features/integrity.d.ts.map +1 -0
  57. package/dist/features/integrity.js +28 -0
  58. package/dist/features/observer.d.ts.map +1 -1
  59. package/dist/features/observer.js +2 -1
  60. package/dist/features/query.d.ts +7 -1
  61. package/dist/features/query.d.ts.map +1 -1
  62. package/dist/features/query.js +9 -2
  63. package/dist/features/sync.d.ts.map +1 -1
  64. package/dist/features/sync.js +4 -3
  65. package/dist/index.d.ts +35 -2
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +55 -30
  68. package/dist/integrations/angular/index.d.ts +158 -0
  69. package/dist/integrations/angular/index.d.ts.map +1 -0
  70. package/dist/integrations/angular/index.js +395 -0
  71. package/dist/integrations/index.d.ts +15 -0
  72. package/dist/integrations/index.d.ts.map +1 -0
  73. package/dist/integrations/index.js +18 -0
  74. package/dist/integrations/react/index.d.ts +75 -0
  75. package/dist/integrations/react/index.d.ts.map +1 -0
  76. package/dist/integrations/react/index.js +191 -0
  77. package/dist/integrations/vue/index.d.ts +103 -0
  78. package/dist/integrations/vue/index.d.ts.map +1 -0
  79. package/dist/integrations/vue/index.js +274 -0
  80. package/dist/ios/AGENTS.md +33 -0
  81. package/dist/ios/CLAUDE.md +49 -0
  82. package/dist/ios/Plugin/KeychainStorage.swift +139 -50
  83. package/dist/ios/Plugin/SQLiteStorage.swift +40 -0
  84. package/dist/ios/Plugin/StrataStoragePlugin.m +23 -0
  85. package/dist/ios/Plugin/StrataStoragePlugin.swift +201 -52
  86. package/dist/package.json +21 -5
  87. package/dist/plugin/index.d.ts.map +1 -1
  88. package/dist/plugin/index.js +2 -1
  89. package/dist/types/index.d.ts +58 -9
  90. package/dist/types/index.d.ts.map +1 -1
  91. package/dist/types/index.js +0 -13
  92. package/dist/utils/errors.d.ts +7 -0
  93. package/dist/utils/errors.d.ts.map +1 -1
  94. package/dist/utils/errors.js +15 -3
  95. package/dist/utils/index.d.ts +63 -5
  96. package/dist/utils/index.d.ts.map +1 -1
  97. package/dist/utils/index.js +109 -16
  98. package/dist/utils/logger.d.ts +31 -0
  99. package/dist/utils/logger.d.ts.map +1 -0
  100. package/dist/utils/logger.js +63 -0
  101. package/ios/AGENTS.md +33 -0
  102. package/ios/CLAUDE.md +49 -0
  103. package/ios/Plugin/KeychainStorage.swift +139 -50
  104. package/ios/Plugin/SQLiteStorage.swift +40 -0
  105. package/ios/Plugin/StrataStoragePlugin.m +23 -0
  106. package/ios/Plugin/StrataStoragePlugin.swift +201 -52
  107. package/package.json +35 -23
  108. package/scripts/build.js +16 -5
  109. package/scripts/configure.js +2 -6
  110. package/scripts/postinstall.js +2 -2
  111. 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": true,
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 = try sqliteStorage.get(key: key)
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.localizedDescription)
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.localizedDescription)
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
- try sqliteStorage.remove(key: key)
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.localizedDescription)
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
- let prefix = call.getString("prefix")
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
- try sqliteStorage.clear(prefix: prefix)
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.localizedDescription)
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 = try sqliteStorage.keys(pattern: pattern)
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.localizedDescription)
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.localizedDescription)
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.4.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",
@@ -10,11 +10,10 @@
10
10
  "ios/",
11
11
  "android/",
12
12
  "scripts/",
13
- "StrataStorage.podspec"
13
+ "StrataStorage.podspec",
14
+ "AI-INTEGRATION-GUIDE.md"
14
15
  ],
15
- "bin": {
16
- "strata-storage": "./scripts/cli.js"
17
- },
16
+ "bin": "./scripts/cli.js",
18
17
  "exports": {
19
18
  ".": {
20
19
  "types": "./dist/index.d.ts",
@@ -48,7 +47,7 @@
48
47
  "typecheck": "tsc --noEmit",
49
48
  "test": "vitest",
50
49
  "test:coverage": "vitest --coverage",
51
- "prepublishOnly": "pnpm build && pnpm lint && pnpm typecheck",
50
+ "prepublishOnly": "yarn build && yarn lint && yarn typecheck",
52
51
  "postinstall": "node scripts/postinstall.js || true"
53
52
  },
54
53
  "keywords": [
@@ -81,11 +80,18 @@
81
80
  "homepage": "https://github.com/aoneahsan/strata-storage#readme",
82
81
  "peerDependencies": {
83
82
  "@angular/core": ">=21.0.6",
83
+ "@angular/forms": ">=21.0.6",
84
84
  "@capacitor/core": ">=8.0.0",
85
85
  "react": ">=19.2.3",
86
86
  "vue": ">=3.5.26"
87
87
  },
88
88
  "peerDependenciesMeta": {
89
+ "@angular/core": {
90
+ "optional": true
91
+ },
92
+ "@angular/forms": {
93
+ "optional": true
94
+ },
89
95
  "@capacitor/core": {
90
96
  "optional": true
91
97
  },
@@ -94,28 +100,33 @@
94
100
  },
95
101
  "vue": {
96
102
  "optional": true
97
- },
98
- "@angular/core": {
99
- "optional": true
100
103
  }
101
104
  },
102
105
  "devDependencies": {
103
- "@types/node": "^25.0.3",
104
- "@types/react": "^19.2.7",
105
- "@typescript-eslint/eslint-plugin": "^8.50.1",
106
- "@typescript-eslint/parser": "^8.50.1",
107
- "@vitest/coverage-v8": "^4.0.16",
108
- "eslint": "^9.39.2",
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",
109
116
  "eslint-config-prettier": "^10.1.8",
110
- "eslint-plugin-prettier": "^5.5.4",
111
- "jsdom": "^27.4.0",
112
- "prettier": "^3.7.4",
113
- "typescript": "^5.9.3",
114
- "typescript-eslint": "^8.50.1",
115
- "vitest": "^4.0.16"
117
+ "eslint-plugin-prettier": "^5.5.5",
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"
116
127
  },
117
128
  "engines": {
118
- "node": ">=18.0.0"
129
+ "node": ">=24.13.0"
119
130
  },
120
131
  "capacitor": {
121
132
  "ios": {
@@ -125,5 +136,6 @@
125
136
  "src": "android",
126
137
  "androidModule": "strata-storage"
127
138
  }
128
- }
139
+ },
140
+ "packageManager": "yarn@4.14.1"
129
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('npx tsc', { stdio: 'inherit', cwd: rootDir });
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
- node: '>=18.0.0'
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}`);
@@ -399,11 +399,7 @@ async function installDependencies(config) {
399
399
  }
400
400
 
401
401
  // Install command
402
- const command = config.packageManager === 'yarn'
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
+ });
@@ -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 "npx cap sync" to sync native code\n');
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');