strata-storage 2.3.0 → 2.4.1

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 (29) hide show
  1. package/android/src/main/java/com/strata/storage/EncryptedStorage.java +84 -21
  2. package/android/src/main/java/com/strata/storage/SQLiteStorage.java +140 -58
  3. package/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +66 -5
  4. package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +83 -10
  5. package/dist/adapters/web/MemoryAdapter.d.ts.map +1 -1
  6. package/dist/adapters/web/MemoryAdapter.js +7 -1
  7. package/dist/adapters/web/SessionStorageAdapter.d.ts.map +1 -1
  8. package/dist/adapters/web/SessionStorageAdapter.js +3 -2
  9. package/dist/android/src/main/java/com/strata/storage/EncryptedStorage.java +84 -21
  10. package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +140 -58
  11. package/dist/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +66 -5
  12. package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +83 -10
  13. package/dist/core/Strata.d.ts.map +1 -1
  14. package/dist/core/Strata.js +4 -6
  15. package/dist/firebase.d.ts.map +1 -1
  16. package/dist/firebase.js +75 -13
  17. package/dist/ios/Plugin/SQLiteStorage.swift +100 -30
  18. package/dist/ios/Plugin/UserDefaultsStorage.swift +13 -2
  19. package/dist/package.json +5 -5
  20. package/dist/plugin/index.d.ts.map +1 -1
  21. package/dist/plugin/index.js +31 -6
  22. package/dist/plugin/web.d.ts +5 -1
  23. package/dist/plugin/web.d.ts.map +1 -1
  24. package/dist/plugin/web.js +55 -32
  25. package/dist/utils/index.d.ts.map +1 -1
  26. package/dist/utils/index.js +7 -2
  27. package/ios/Plugin/SQLiteStorage.swift +100 -30
  28. package/ios/Plugin/UserDefaultsStorage.swift +13 -2
  29. package/package.json +17 -19
package/dist/firebase.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { StorageError } from "./utils/errors.js";
1
2
  /**
2
3
  * Enable Firebase sync for Strata Storage
3
4
  * This dynamically imports Firebase SDK only when needed
@@ -19,8 +20,9 @@ export async function enableFirebaseSync(storage, config) {
19
20
  });
20
21
  }
21
22
  if (config.firestore) {
23
+ const { getFirestore, doc, setDoc, getDoc, deleteDoc, collection, getDocs, onSnapshot } =
22
24
  // @ts-expect-error - Firebase is an optional peer dependency
23
- const { getFirestore, doc, setDoc, getDoc, deleteDoc } = await import('firebase/firestore');
25
+ await import('firebase/firestore');
24
26
  const db = getFirestore();
25
27
  const collectionName = config.collectionName || 'strata-storage';
26
28
  // Create custom adapter for Firestore
@@ -56,12 +58,31 @@ export async function enableFirebaseSync(storage, config) {
56
58
  return docSnap.exists();
57
59
  },
58
60
  async clear() {
59
- // Firestore doesn't have a direct clear method
60
- console.warn('Clear operation not supported for Firestore adapter');
61
+ try {
62
+ const collectionRef = collection(db, collectionName);
63
+ const snapshot = await getDocs(collectionRef);
64
+ const deletePromises = snapshot.docs.map((docSnapshot) => deleteDoc(doc(db, collectionName, docSnapshot.id)));
65
+ await Promise.all(deletePromises);
66
+ }
67
+ catch (error) {
68
+ throw new StorageError('Failed to clear Firestore collection', {
69
+ collectionName,
70
+ originalError: error,
71
+ });
72
+ }
61
73
  },
62
74
  async keys() {
63
- // Would need to implement with queries
64
- return [];
75
+ try {
76
+ const collectionRef = collection(db, collectionName);
77
+ const snapshot = await getDocs(collectionRef);
78
+ return snapshot.docs.map((docSnapshot) => docSnapshot.id);
79
+ }
80
+ catch (error) {
81
+ throw new StorageError('Failed to retrieve keys from Firestore', {
82
+ collectionName,
83
+ originalError: error,
84
+ });
85
+ }
65
86
  },
66
87
  async size() {
67
88
  return { total: 0, count: 0 };
@@ -72,9 +93,24 @@ export async function enableFirebaseSync(storage, config) {
72
93
  async isAvailable() {
73
94
  return true;
74
95
  },
75
- subscribe() {
76
- // Not implemented for Firebase adapter
77
- return () => { };
96
+ subscribe(callback) {
97
+ const collectionRef = collection(db, collectionName);
98
+ const unsubscribe = onSnapshot(collectionRef, (snapshot) => {
99
+ snapshot
100
+ .docChanges()
101
+ .forEach((change) => {
102
+ const docData = change.doc.data();
103
+ callback({
104
+ key: change.doc.id,
105
+ oldValue: change.type === 'removed' ? docData.value : undefined,
106
+ newValue: change.type !== 'removed' ? docData.value : undefined,
107
+ source: 'remote',
108
+ storage: 'firestore',
109
+ timestamp: Date.now(),
110
+ });
111
+ });
112
+ });
113
+ return unsubscribe;
78
114
  },
79
115
  async close() {
80
116
  // No cleanup needed
@@ -86,7 +122,7 @@ export async function enableFirebaseSync(storage, config) {
86
122
  }
87
123
  if (config.realtimeDatabase) {
88
124
  // @ts-expect-error - Firebase is an optional peer dependency
89
- const { getDatabase, ref, set, get, remove } = await import('firebase/database');
125
+ const { getDatabase, ref, set, get, remove, onValue } = await import('firebase/database');
90
126
  const db = getDatabase();
91
127
  // Create custom adapter for Realtime Database
92
128
  const realtimeAdapter = {
@@ -134,9 +170,32 @@ export async function enableFirebaseSync(storage, config) {
134
170
  async isAvailable() {
135
171
  return true;
136
172
  },
137
- subscribe() {
138
- // Not implemented for Firebase adapter
139
- return () => { };
173
+ subscribe(callback) {
174
+ const dbRef = ref(db, 'strata-storage');
175
+ let previousData = {};
176
+ const unsubscribe = onValue(dbRef, (snapshot) => {
177
+ const snapshotTyped = snapshot;
178
+ const currentData = snapshotTyped.exists()
179
+ ? snapshotTyped.val()
180
+ : {};
181
+ const allKeys = new Set([...Object.keys(previousData), ...Object.keys(currentData)]);
182
+ allKeys.forEach((key) => {
183
+ const oldValue = previousData[key];
184
+ const newValue = currentData[key];
185
+ if (oldValue !== newValue) {
186
+ callback({
187
+ key,
188
+ oldValue,
189
+ newValue,
190
+ source: 'remote',
191
+ storage: 'realtime',
192
+ timestamp: Date.now(),
193
+ });
194
+ }
195
+ });
196
+ previousData = { ...currentData };
197
+ });
198
+ return unsubscribe;
140
199
  },
141
200
  async close() {
142
201
  // No cleanup needed
@@ -149,7 +208,10 @@ export async function enableFirebaseSync(storage, config) {
149
208
  // Firebase sync enabled successfully
150
209
  }
151
210
  catch (error) {
152
- throw new Error(`Failed to enable Firebase sync: ${error instanceof Error ? error.message : 'Unknown error'}`);
211
+ throw new StorageError('Failed to enable Firebase sync', {
212
+ originalError: error,
213
+ config,
214
+ });
153
215
  }
154
216
  }
155
217
  /**
@@ -1,29 +1,47 @@
1
1
  import Foundation
2
2
  import SQLite3
3
+ import os.log
3
4
 
4
5
  @objc public class SQLiteStorage: NSObject {
5
6
  private var db: OpaquePointer?
6
7
  private let dbName: String
7
8
  private let tableName = "strata_storage"
9
+ private let logger = OSLog(subsystem: "com.strata.storage", category: "SQLiteStorage")
8
10
 
9
11
  @objc public init(dbName: String = "strata.db") {
10
12
  self.dbName = dbName
11
13
  super.init()
12
- openDatabase()
13
- createTable()
14
+ do {
15
+ try openDatabase()
16
+ try createTable()
17
+ } catch {
18
+ os_log("Failed to initialize SQLite storage: %{public}@", log: logger, type: .error, error.localizedDescription)
19
+ }
14
20
  }
15
21
 
16
22
  deinit {
17
23
  closeDatabase()
18
24
  }
19
25
 
20
- private func openDatabase() {
21
- let fileURL = try! FileManager.default
26
+ private func openDatabase() throws {
27
+ guard let fileURL = try? FileManager.default
22
28
  .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
23
- .appendingPathComponent(dbName)
24
-
25
- if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
26
- print("Unable to open database")
29
+ .appendingPathComponent(dbName) else {
30
+ throw NSError(
31
+ domain: "StrataStorage.SQLiteStorage",
32
+ code: 1001,
33
+ userInfo: [NSLocalizedDescriptionKey: "Unable to access document directory"]
34
+ )
35
+ }
36
+
37
+ guard sqlite3_open(fileURL.path, &db) == SQLITE_OK else {
38
+ let errorMessage = String(cString: sqlite3_errmsg(db))
39
+ sqlite3_close(db)
40
+ throw NSError(
41
+ domain: "StrataStorage.SQLiteStorage",
42
+ code: 1002,
43
+ userInfo: [NSLocalizedDescriptionKey: "Unable to open database: \(errorMessage)"]
44
+ )
27
45
  }
28
46
  }
29
47
 
@@ -31,7 +49,7 @@ import SQLite3
31
49
  sqlite3_close(db)
32
50
  }
33
51
 
34
- private func createTable() {
52
+ private func createTable() throws {
35
53
  let createTableString = """
36
54
  CREATE TABLE IF NOT EXISTS \(tableName) (
37
55
  key TEXT PRIMARY KEY NOT NULL,
@@ -43,19 +61,43 @@ import SQLite3
43
61
  metadata TEXT
44
62
  );
45
63
  """
46
-
64
+
47
65
  var createTableStatement: OpaquePointer?
48
- if sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK {
49
- if sqlite3_step(createTableStatement) == SQLITE_DONE {
50
- print("Storage table created.")
51
- }
66
+
67
+ guard sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK else {
68
+ let errorMessage = String(cString: sqlite3_errmsg(db))
69
+ throw NSError(
70
+ domain: "StrataStorage.SQLiteStorage",
71
+ code: 1003,
72
+ userInfo: [NSLocalizedDescriptionKey: "Failed to prepare CREATE TABLE: \(errorMessage)"]
73
+ )
74
+ }
75
+
76
+ defer {
77
+ sqlite3_finalize(createTableStatement)
78
+ }
79
+
80
+ guard sqlite3_step(createTableStatement) == SQLITE_DONE else {
81
+ let errorMessage = String(cString: sqlite3_errmsg(db))
82
+ throw NSError(
83
+ domain: "StrataStorage.SQLiteStorage",
84
+ code: 1004,
85
+ userInfo: [NSLocalizedDescriptionKey: "Failed to create table: \(errorMessage)"]
86
+ )
52
87
  }
53
- sqlite3_finalize(createTableStatement)
54
88
  }
55
89
 
56
90
  @objc public func set(key: String, value: Any, expires: Int64? = nil, tags: [String]? = nil, metadata: [String: Any]? = nil) throws -> Bool {
91
+ guard let db = db else {
92
+ throw NSError(
93
+ domain: "StrataStorage.SQLiteStorage",
94
+ code: 1000,
95
+ userInfo: [NSLocalizedDescriptionKey: "Database not initialized"]
96
+ )
97
+ }
98
+
57
99
  let data: Data
58
-
100
+
59
101
  if let dataValue = value as? Data {
60
102
  data = dataValue
61
103
  } else if let stringValue = value as? String {
@@ -96,9 +138,14 @@ import SQLite3
96
138
  }
97
139
 
98
140
  @objc public func get(key: String) -> [String: Any]? {
141
+ guard db != nil else {
142
+ os_log("Database not initialized", log: logger, type: .error)
143
+ return nil
144
+ }
145
+
99
146
  let querySQL = "SELECT * FROM \(tableName) WHERE key = ? LIMIT 1"
100
147
  var statement: OpaquePointer?
101
-
148
+
102
149
  guard sqlite3_prepare_v2(db, querySQL, -1, &statement, nil) == SQLITE_OK,
103
150
  sqlite3_bind_text(statement, 1, key, -1, nil) == SQLITE_OK else {
104
151
  sqlite3_finalize(statement)
@@ -142,82 +189,105 @@ import SQLite3
142
189
  }
143
190
 
144
191
  @objc public func remove(key: String) -> Bool {
192
+ guard db != nil else {
193
+ os_log("Database not initialized", log: logger, type: .error)
194
+ return false
195
+ }
196
+
145
197
  let deleteSQL = "DELETE FROM \(tableName) WHERE key = ?"
146
198
  var statement: OpaquePointer?
147
-
199
+
148
200
  let result = sqlite3_prepare_v2(db, deleteSQL, -1, &statement, nil) == SQLITE_OK &&
149
201
  sqlite3_bind_text(statement, 1, key, -1, nil) == SQLITE_OK &&
150
202
  sqlite3_step(statement) == SQLITE_DONE
151
-
203
+
152
204
  sqlite3_finalize(statement)
153
205
  return result
154
206
  }
155
207
 
156
208
  @objc public func clear(prefix: String? = nil) -> Bool {
209
+ guard db != nil else {
210
+ os_log("Database not initialized", log: logger, type: .error)
211
+ return false
212
+ }
213
+
157
214
  let deleteSQL: String
158
215
  if let prefix = prefix {
159
216
  deleteSQL = "DELETE FROM \(tableName) WHERE key LIKE ?"
160
217
  } else {
161
218
  deleteSQL = "DELETE FROM \(tableName)"
162
219
  }
163
-
220
+
164
221
  var statement: OpaquePointer?
165
222
  var result = sqlite3_prepare_v2(db, deleteSQL, -1, &statement, nil) == SQLITE_OK
166
-
223
+
167
224
  if result && prefix != nil {
168
225
  result = sqlite3_bind_text(statement, 1, "\(prefix!)%", -1, nil) == SQLITE_OK
169
226
  }
170
-
227
+
171
228
  if result {
172
229
  result = sqlite3_step(statement) == SQLITE_DONE
173
230
  }
174
-
231
+
175
232
  sqlite3_finalize(statement)
176
233
  return result
177
234
  }
178
235
 
179
236
  @objc public func keys(pattern: String? = nil) -> [String] {
237
+ guard db != nil else {
238
+ os_log("Database not initialized", log: logger, type: .error)
239
+ return []
240
+ }
241
+
180
242
  let querySQL: String
181
243
  if let pattern = pattern {
182
244
  querySQL = "SELECT key FROM \(tableName) WHERE key LIKE ?"
183
245
  } else {
184
246
  querySQL = "SELECT key FROM \(tableName)"
185
247
  }
186
-
248
+
187
249
  var statement: OpaquePointer?
188
250
  var keys: [String] = []
189
-
251
+
190
252
  if sqlite3_prepare_v2(db, querySQL, -1, &statement, nil) == SQLITE_OK {
191
253
  if let pattern = pattern {
192
254
  // Use % wildcard for SQL LIKE pattern matching
193
255
  sqlite3_bind_text(statement, 1, "%\(pattern)%", -1, nil)
194
256
  }
195
-
257
+
196
258
  while sqlite3_step(statement) == SQLITE_ROW {
197
259
  if let key = sqlite3_column_text(statement, 0) {
198
260
  keys.append(String(cString: key))
199
261
  }
200
262
  }
201
263
  }
202
-
264
+
203
265
  sqlite3_finalize(statement)
204
266
  return keys
205
267
  }
206
268
 
207
269
  @objc public func size() throws -> (total: Int, count: Int) {
270
+ guard db != nil else {
271
+ throw NSError(
272
+ domain: "StrataStorage.SQLiteStorage",
273
+ code: 1000,
274
+ userInfo: [NSLocalizedDescriptionKey: "Database not initialized"]
275
+ )
276
+ }
277
+
208
278
  let querySQL = "SELECT COUNT(*), SUM(LENGTH(value)) FROM \(tableName)"
209
279
  var statement: OpaquePointer?
210
-
280
+
211
281
  var totalSize = 0
212
282
  var count = 0
213
-
283
+
214
284
  if sqlite3_prepare_v2(db, querySQL, -1, &statement, nil) == SQLITE_OK {
215
285
  if sqlite3_step(statement) == SQLITE_ROW {
216
286
  count = Int(sqlite3_column_int(statement, 0))
217
287
  totalSize = Int(sqlite3_column_int64(statement, 1))
218
288
  }
219
289
  }
220
-
290
+
221
291
  sqlite3_finalize(statement)
222
292
  return (total: totalSize, count: count)
223
293
  }
@@ -6,7 +6,11 @@ import Foundation
6
6
 
7
7
  @objc public init(suiteName: String? = nil) {
8
8
  self.suiteName = suiteName
9
- self.userDefaults = suiteName != nil ? UserDefaults(suiteName: suiteName)! : UserDefaults.standard
9
+ if let suiteName = suiteName, let customDefaults = UserDefaults(suiteName: suiteName) {
10
+ self.userDefaults = customDefaults
11
+ } else {
12
+ self.userDefaults = UserDefaults.standard
13
+ }
10
14
  super.init()
11
15
  }
12
16
 
@@ -36,7 +40,14 @@ import Foundation
36
40
  if let suiteName = suiteName {
37
41
  UserDefaults(suiteName: suiteName)?.removePersistentDomain(forName: suiteName)
38
42
  } else {
39
- let domain = Bundle.main.bundleIdentifier!
43
+ guard let domain = Bundle.main.bundleIdentifier else {
44
+ // Fallback: manually clear all keys
45
+ let keys = Array(userDefaults.dictionaryRepresentation().keys)
46
+ for key in keys {
47
+ userDefaults.removeObject(forKey: key)
48
+ }
49
+ return userDefaults.synchronize()
50
+ }
40
51
  userDefaults.removePersistentDomain(forName: domain)
41
52
  }
42
53
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strata-storage",
3
- "version": "2.3.0",
3
+ "version": "2.4.1",
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": "./index.js",
@@ -44,10 +44,10 @@
44
44
  "android"
45
45
  ],
46
46
  "peerDependencies": {
47
- "@angular/core": ">=20.3.0",
48
- "@capacitor/core": ">=7.4.0",
49
- "react": ">=19.1.0",
50
- "vue": ">=3.6.0"
47
+ "@angular/core": ">=21.0.6",
48
+ "@capacitor/core": ">=8.0.0",
49
+ "react": ">=19.2.3",
50
+ "vue": ">=3.5.26"
51
51
  },
52
52
  "peerDependenciesMeta": {
53
53
  "@capacitor/core": {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,mBAAmB,EASpB,MAAM,eAAe,CAAC;AA+GvB,eAAO,MAAM,aAAa,EAAE,mBAAmD,CAAC;AAEhF,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,mBAAmB,EASpB,MAAM,eAAe,CAAC;AA8IvB,eAAO,MAAM,aAAa,EAAE,mBAAmD,CAAC;AAEhF,cAAc,eAAe,CAAC"}
@@ -3,15 +3,40 @@
3
3
  * Main plugin registration and web implementation
4
4
  * This is now optional and only loaded when Capacitor adapters are used
5
5
  */
6
+ import { NotSupportedError } from "../utils/errors.js";
6
7
  // Mock implementation for when Capacitor is not available
7
8
  const mockPlugin = {
8
9
  isAvailable: async () => ({ available: false }),
9
- get: async () => ({ value: null }),
10
- set: async () => { },
11
- remove: async () => { },
12
- clear: async () => { },
13
- keys: async () => ({ keys: [] }),
14
- size: async () => ({ total: 0, count: 0 }),
10
+ get: async () => {
11
+ throw new NotSupportedError('Native storage', 'web platform without Capacitor', {
12
+ suggestion: 'Use web adapters: localStorage, sessionStorage, indexedDB, cookies, or cache instead',
13
+ });
14
+ },
15
+ set: async () => {
16
+ throw new NotSupportedError('Native storage', 'web platform without Capacitor', {
17
+ suggestion: 'Use web adapters: localStorage, sessionStorage, indexedDB, cookies, or cache instead',
18
+ });
19
+ },
20
+ remove: async () => {
21
+ throw new NotSupportedError('Native storage', 'web platform without Capacitor', {
22
+ suggestion: 'Use web adapters: localStorage, sessionStorage, indexedDB, cookies, or cache instead',
23
+ });
24
+ },
25
+ clear: async () => {
26
+ throw new NotSupportedError('Native storage', 'web platform without Capacitor', {
27
+ suggestion: 'Use web adapters: localStorage, sessionStorage, indexedDB, cookies, or cache instead',
28
+ });
29
+ },
30
+ keys: async () => {
31
+ throw new NotSupportedError('Native storage', 'web platform without Capacitor', {
32
+ suggestion: 'Use web adapters: localStorage, sessionStorage, indexedDB, cookies, or cache instead',
33
+ });
34
+ },
35
+ size: async () => {
36
+ throw new NotSupportedError('Native storage', 'web platform without Capacitor', {
37
+ suggestion: 'Use web adapters: localStorage, sessionStorage, indexedDB, cookies, or cache instead',
38
+ });
39
+ },
15
40
  };
16
41
  // Create a lazy-loading wrapper that only attempts to load Capacitor when actually used
17
42
  class LazyStrataStoragePlugin {
@@ -5,7 +5,11 @@
5
5
  import type { StrataStoragePlugin, NativeStorageType, NativeGetOptions, NativeSetOptions, NativeRemoveOptions, NativeClearOptions, NativeKeysOptions, NativeSizeOptions, NativeSizeResult } from './definitions';
6
6
  import type { StorageValue } from '@/types';
7
7
  export declare class StrataStorageWeb implements StrataStoragePlugin {
8
- isAvailable(_options: {
8
+ private adapters;
9
+ private initialized;
10
+ private initializeAdapters;
11
+ private getAdapter;
12
+ isAvailable(options: {
9
13
  storage: NativeStorageType;
10
14
  }): Promise<{
11
15
  available: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/plugin/web.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,qBAAa,gBAAiB,YAAW,mBAAmB;IACpD,WAAW,CAAC,QAAQ,EAAE;QAAE,OAAO,EAAE,iBAAiB,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAWtF,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAAA;KAAE,CAAC;IAOvE,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAO7C,MAAM,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnD,KAAK,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAO7D,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAOjE;;OAEG;IACH,OAAO,CAAC,aAAa;CAatB"}
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/plugin/web.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,SAAS,CAAC;AAM5D,qBAAa,gBAAiB,YAAW,mBAAmB;IAC1D,OAAO,CAAC,QAAQ,CAAqD;IACrE,OAAO,CAAC,WAAW,CAAS;YAEd,kBAAkB;IAahC,OAAO,CAAC,UAAU;IAUZ,WAAW,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,iBAAiB,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAUrF,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAAA;KAAE,CAAC;IAOvE,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7C,MAAM,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnD,KAAK,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjD,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAO7D,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAOjE;;OAEG;IACH,OAAO,CAAC,aAAa;CAatB"}
@@ -2,51 +2,74 @@
2
2
  * Strata Storage Web Implementation
3
3
  * Web platform implementation of the Capacitor plugin
4
4
  */
5
+ import { LocalStorageAdapter } from "../adapters/web/LocalStorageAdapter.js";
6
+ import { IndexedDBAdapter } from "../adapters/web/IndexedDBAdapter.js";
7
+ import { CacheAdapter } from "../adapters/web/CacheAdapter.js";
8
+ import { NotSupportedError } from "../utils/errors.js";
5
9
  export class StrataStorageWeb {
6
- async isAvailable(_options) {
7
- // Web platform doesn't support native storage types
8
- // This is handled by the web adapters instead
9
- return {
10
- available: false,
11
- platform: 'web',
12
- message: 'Native storage not available on web. Use web adapters: localStorage, sessionStorage, indexedDB, cookies, or cache instead.',
13
- };
10
+ adapters = new Map();
11
+ initialized = false;
12
+ async initializeAdapters() {
13
+ if (this.initialized)
14
+ return;
15
+ this.adapters.set('preferences', new LocalStorageAdapter('strata_prefs_'));
16
+ this.adapters.set('secure', new IndexedDBAdapter('strata-secure'));
17
+ this.adapters.set('sqlite', new IndexedDBAdapter('strata-db'));
18
+ this.adapters.set('filesystem', new CacheAdapter('strata-files'));
19
+ await Promise.all(Array.from(this.adapters.values()).map((adapter) => adapter.initialize()));
20
+ this.initialized = true;
21
+ }
22
+ getAdapter(storageType) {
23
+ const adapter = this.adapters.get(storageType);
24
+ if (!adapter) {
25
+ throw new NotSupportedError(`Storage type '${storageType}'`, 'web plugin', {
26
+ availableTypes: Array.from(this.adapters.keys()),
27
+ suggestion: this.getSuggestion(storageType),
28
+ });
29
+ }
30
+ return adapter;
31
+ }
32
+ async isAvailable(options) {
33
+ await this.initializeAdapters();
34
+ const adapter = this.adapters.get(options.storage);
35
+ if (!adapter) {
36
+ return { available: false };
37
+ }
38
+ const available = await adapter.isAvailable();
39
+ return { available };
14
40
  }
15
41
  async get(options) {
16
- // Not implemented for web - use web adapters instead
17
- const storageType = options.storage || 'preferences';
18
- const suggestion = this.getSuggestion(storageType);
19
- throw new Error(`Native storage '${storageType}' not available on web platform. ${suggestion}`);
42
+ await this.initializeAdapters();
43
+ const adapter = this.getAdapter(options.storage || 'preferences');
44
+ const value = await adapter.get(options.key);
45
+ return { value };
20
46
  }
21
47
  async set(options) {
22
- // Not implemented for web - use web adapters instead
23
- const storageType = options.storage || 'preferences';
24
- const suggestion = this.getSuggestion(storageType);
25
- throw new Error(`Native storage '${storageType}' not available on web platform. ${suggestion}`);
48
+ await this.initializeAdapters();
49
+ const adapter = this.getAdapter(options.storage || 'preferences');
50
+ await adapter.set(options.key, options.value);
26
51
  }
27
52
  async remove(options) {
28
- // Not implemented for web - use web adapters instead
29
- const storageType = options.storage || 'preferences';
30
- const suggestion = this.getSuggestion(storageType);
31
- throw new Error(`Native storage '${storageType}' not available on web platform. ${suggestion}`);
53
+ await this.initializeAdapters();
54
+ const adapter = this.getAdapter(options.storage || 'preferences');
55
+ await adapter.remove(options.key);
32
56
  }
33
57
  async clear(options) {
34
- // Not implemented for web - use web adapters instead
35
- const storageType = options.storage || 'preferences';
36
- const suggestion = this.getSuggestion(storageType);
37
- throw new Error(`Native storage '${storageType}' not available on web platform. ${suggestion}`);
58
+ await this.initializeAdapters();
59
+ const adapter = this.getAdapter(options.storage || 'preferences');
60
+ await adapter.clear();
38
61
  }
39
62
  async keys(options) {
40
- // Not implemented for web - use web adapters instead
41
- const storageType = options.storage || 'preferences';
42
- const suggestion = this.getSuggestion(storageType);
43
- throw new Error(`Native storage '${storageType}' not available on web platform. ${suggestion}`);
63
+ await this.initializeAdapters();
64
+ const adapter = this.getAdapter(options.storage || 'preferences');
65
+ const keys = await adapter.keys();
66
+ return { keys };
44
67
  }
45
68
  async size(options) {
46
- // Not implemented for web - use web adapters instead
47
- const storageType = options.storage || 'preferences';
48
- const suggestion = this.getSuggestion(storageType);
49
- throw new Error(`Native storage '${storageType}' not available on web platform. ${suggestion}`);
69
+ await this.initializeAdapters();
70
+ const adapter = this.getAdapter(options.storage || 'preferences');
71
+ const sizeInfo = await adapter.size();
72
+ return { total: sizeInfo.total, count: sizeInfo.count };
50
73
  }
51
74
  /**
52
75
  * Get suggestion for web alternative based on native storage type
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;GAEG;AACH,wBAAgB,MAAM,IAAI,OAAO,CAMhC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAKrC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAatC;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,MAAM,EAAE,CAAC,EACT,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,GACvB,CAAC,CAgBH;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEvE;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAInC;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAU/D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAoBvD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAChE,IAAI,EAAE,CAAC,EACP,IAAI,EAAE,MAAM,GACX,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAYlC;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAChE,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,MAAM,GACZ,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAUlC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC3B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,YAAY,SAAwB,GACnC,OAAO,CAAC,CAAC,CAAC,CAWZ;AAED;;GAEG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAC3B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE;IACP,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACZ,GACL,OAAO,CAAC,CAAC,CAAC,CAoBZ;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,KAAK;IACnC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC,CAUA;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAShD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAoBjD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAqClD;AAED;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA6D;IAE3E,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAO9D,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAI/D,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAU7C,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAQhE,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;CAOzC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAEtD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGpD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEvD;AAUD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,KAAK,CAKpF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@
2
2
  * Utility functions for Strata Storage
3
3
  * Zero dependencies - all utilities implemented from scratch
4
4
  */
5
+ import { ValidationError } from "./errors.js";
5
6
  /**
6
7
  * Check if code is running in a browser environment
7
8
  */
@@ -122,8 +123,12 @@ export function parseSize(size) {
122
123
  tb: 1024 * 1024 * 1024 * 1024,
123
124
  };
124
125
  const match = size.toLowerCase().match(/^(\d+(?:\.\d+)?)\s*([a-z]+)?$/);
125
- if (!match)
126
- throw new Error(`Invalid size format: ${size}`);
126
+ if (!match) {
127
+ throw new ValidationError('Invalid size format', {
128
+ provided: size,
129
+ expected: 'Number with unit (e.g., 5MB, 1GB)',
130
+ });
131
+ }
127
132
  const [, num, unit = 'b'] = match;
128
133
  const multiplier = units[unit] || 1;
129
134
  return parseFloat(num) * multiplier;