strata-storage 2.4.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.
- package/android/src/main/java/com/strata/storage/EncryptedStorage.java +27 -18
- package/android/src/main/java/com/strata/storage/SQLiteStorage.java +85 -58
- package/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +9 -2
- package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +83 -10
- package/dist/adapters/web/MemoryAdapter.d.ts.map +1 -1
- package/dist/adapters/web/MemoryAdapter.js +7 -1
- package/dist/adapters/web/SessionStorageAdapter.d.ts.map +1 -1
- package/dist/adapters/web/SessionStorageAdapter.js +3 -2
- package/dist/android/src/main/java/com/strata/storage/EncryptedStorage.java +27 -18
- package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +85 -58
- package/dist/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +9 -2
- package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +83 -10
- package/dist/core/Strata.d.ts.map +1 -1
- package/dist/core/Strata.js +4 -6
- package/dist/firebase.d.ts.map +1 -1
- package/dist/firebase.js +75 -13
- package/dist/ios/Plugin/SQLiteStorage.swift +100 -30
- package/dist/ios/Plugin/UserDefaultsStorage.swift +13 -2
- package/dist/package.json +5 -5
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +31 -6
- package/dist/plugin/web.d.ts +5 -1
- package/dist/plugin/web.d.ts.map +1 -1
- package/dist/plugin/web.js +55 -32
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +7 -2
- package/ios/Plugin/SQLiteStorage.swift +100 -30
- package/ios/Plugin/UserDefaultsStorage.swift +13 -2
- package/package.json +17 -19
|
@@ -5,6 +5,7 @@ import android.database.Cursor;
|
|
|
5
5
|
import android.database.sqlite.SQLiteDatabase;
|
|
6
6
|
import android.database.sqlite.SQLiteOpenHelper;
|
|
7
7
|
import android.content.ContentValues;
|
|
8
|
+
import android.util.Log;
|
|
8
9
|
import java.util.ArrayList;
|
|
9
10
|
import java.util.List;
|
|
10
11
|
import java.util.HashMap;
|
|
@@ -78,7 +79,7 @@ public class SQLiteStorage extends SQLiteOpenHelper {
|
|
|
78
79
|
valueBytes = json.getBytes(StandardCharsets.UTF_8);
|
|
79
80
|
}
|
|
80
81
|
} catch (Exception e) {
|
|
81
|
-
e
|
|
82
|
+
Log.e("StrataStorage", "Failed to set value in SQLite", e);
|
|
82
83
|
return false;
|
|
83
84
|
}
|
|
84
85
|
SQLiteDatabase db = this.getWritableDatabase();
|
|
@@ -112,36 +113,41 @@ public class SQLiteStorage extends SQLiteOpenHelper {
|
|
|
112
113
|
|
|
113
114
|
public Map<String, Object> get(String key) {
|
|
114
115
|
SQLiteDatabase db = this.getReadableDatabase();
|
|
115
|
-
Cursor cursor =
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
result =
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
116
|
+
Cursor cursor = null;
|
|
117
|
+
try {
|
|
118
|
+
cursor = db.query(TABLE_NAME, null, KEY_ID + "=?",
|
|
119
|
+
new String[]{key}, null, null, null, null);
|
|
120
|
+
|
|
121
|
+
Map<String, Object> result = null;
|
|
122
|
+
if (cursor != null && cursor.moveToFirst()) {
|
|
123
|
+
result = new HashMap<>();
|
|
124
|
+
result.put("key", key);
|
|
125
|
+
result.put("value", cursor.getBlob(cursor.getColumnIndex(KEY_VALUE)));
|
|
126
|
+
result.put("created", cursor.getLong(cursor.getColumnIndex(KEY_CREATED)));
|
|
127
|
+
result.put("updated", cursor.getLong(cursor.getColumnIndex(KEY_UPDATED)));
|
|
128
|
+
|
|
129
|
+
int expiresIndex = cursor.getColumnIndex(KEY_EXPIRES);
|
|
130
|
+
if (!cursor.isNull(expiresIndex)) {
|
|
131
|
+
result.put("expires", cursor.getLong(expiresIndex));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
int tagsIndex = cursor.getColumnIndex(KEY_TAGS);
|
|
135
|
+
if (!cursor.isNull(tagsIndex)) {
|
|
136
|
+
result.put("tags", cursor.getString(tagsIndex));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
int metadataIndex = cursor.getColumnIndex(KEY_METADATA);
|
|
140
|
+
if (!cursor.isNull(metadataIndex)) {
|
|
141
|
+
result.put("metadata", cursor.getString(metadataIndex));
|
|
142
|
+
}
|
|
134
143
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if (
|
|
138
|
-
|
|
144
|
+
return result;
|
|
145
|
+
} finally {
|
|
146
|
+
if (cursor != null) {
|
|
147
|
+
cursor.close();
|
|
139
148
|
}
|
|
140
|
-
|
|
141
|
-
cursor.close();
|
|
149
|
+
db.close();
|
|
142
150
|
}
|
|
143
|
-
db.close();
|
|
144
|
-
return result;
|
|
145
151
|
}
|
|
146
152
|
|
|
147
153
|
public boolean remove(String key) {
|
|
@@ -179,52 +185,73 @@ public class SQLiteStorage extends SQLiteOpenHelper {
|
|
|
179
185
|
List<String> keys = new ArrayList<>();
|
|
180
186
|
String selectQuery;
|
|
181
187
|
String[] selectionArgs = null;
|
|
182
|
-
|
|
188
|
+
|
|
183
189
|
if (pattern != null) {
|
|
184
190
|
selectQuery = "SELECT " + KEY_ID + " FROM " + TABLE_NAME + " WHERE " + KEY_ID + " LIKE ?";
|
|
185
|
-
selectionArgs = new String[]{"%
|
|
191
|
+
selectionArgs = new String[]{"%" + pattern + "%"};
|
|
186
192
|
} else {
|
|
187
193
|
selectQuery = "SELECT " + KEY_ID + " FROM " + TABLE_NAME;
|
|
188
194
|
}
|
|
189
|
-
|
|
195
|
+
|
|
190
196
|
SQLiteDatabase db = this.getReadableDatabase();
|
|
191
|
-
Cursor cursor =
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
+
Cursor cursor = null;
|
|
198
|
+
try {
|
|
199
|
+
cursor = db.rawQuery(selectQuery, selectionArgs);
|
|
200
|
+
|
|
201
|
+
if (cursor != null && cursor.moveToFirst()) {
|
|
202
|
+
do {
|
|
203
|
+
keys.add(cursor.getString(0));
|
|
204
|
+
} while (cursor.moveToNext());
|
|
205
|
+
}
|
|
206
|
+
return keys;
|
|
207
|
+
} finally {
|
|
208
|
+
if (cursor != null) {
|
|
209
|
+
cursor.close();
|
|
210
|
+
}
|
|
211
|
+
db.close();
|
|
197
212
|
}
|
|
198
|
-
cursor.close();
|
|
199
|
-
db.close();
|
|
200
|
-
return keys;
|
|
201
213
|
}
|
|
202
214
|
|
|
203
215
|
public boolean has(String key) {
|
|
204
216
|
SQLiteDatabase db = this.getReadableDatabase();
|
|
205
|
-
Cursor cursor =
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
217
|
+
Cursor cursor = null;
|
|
218
|
+
try {
|
|
219
|
+
cursor = db.query(TABLE_NAME, new String[]{KEY_ID}, KEY_ID + "=?",
|
|
220
|
+
new String[]{key}, null, null, null, null);
|
|
221
|
+
boolean exists = cursor != null && cursor.getCount() > 0;
|
|
222
|
+
return exists;
|
|
223
|
+
} finally {
|
|
224
|
+
if (cursor != null) {
|
|
225
|
+
cursor.close();
|
|
226
|
+
}
|
|
227
|
+
db.close();
|
|
228
|
+
}
|
|
211
229
|
}
|
|
212
230
|
|
|
213
231
|
public SizeInfo size() {
|
|
214
232
|
SQLiteDatabase db = this.getReadableDatabase();
|
|
215
|
-
Cursor cursor =
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
233
|
+
Cursor cursor = null;
|
|
234
|
+
try {
|
|
235
|
+
cursor = db.rawQuery("SELECT COUNT(*), SUM(LENGTH(" + KEY_VALUE + ")) FROM " + TABLE_NAME, null);
|
|
236
|
+
|
|
237
|
+
long totalSize = 0;
|
|
238
|
+
int count = 0;
|
|
239
|
+
|
|
240
|
+
if (cursor != null && cursor.moveToFirst()) {
|
|
241
|
+
count = cursor.getInt(0);
|
|
242
|
+
// Check for NULL values from SQL SUM function
|
|
243
|
+
if (!cursor.isNull(1)) {
|
|
244
|
+
totalSize = cursor.getLong(1);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return new SizeInfo(totalSize, count);
|
|
249
|
+
} finally {
|
|
250
|
+
if (cursor != null) {
|
|
251
|
+
cursor.close();
|
|
252
|
+
}
|
|
253
|
+
db.close();
|
|
224
254
|
}
|
|
225
|
-
|
|
226
|
-
db.close();
|
|
227
|
-
return new SizeInfo(totalSize, count);
|
|
228
255
|
}
|
|
229
256
|
|
|
230
257
|
/**
|
|
@@ -2,6 +2,7 @@ package com.strata.storage;
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context;
|
|
4
4
|
import android.content.SharedPreferences;
|
|
5
|
+
import android.util.Log;
|
|
5
6
|
import java.util.Map;
|
|
6
7
|
import java.util.Set;
|
|
7
8
|
import java.util.HashSet;
|
|
@@ -37,7 +38,13 @@ public class SharedPreferencesStorage {
|
|
|
37
38
|
} else if (value instanceof Boolean) {
|
|
38
39
|
editor.putBoolean(key, (Boolean) value);
|
|
39
40
|
} else if (value instanceof Set) {
|
|
40
|
-
|
|
41
|
+
// Safely convert to Set<String>
|
|
42
|
+
Set<?> rawSet = (Set<?>) value;
|
|
43
|
+
Set<String> stringSet = new HashSet<>();
|
|
44
|
+
for (Object item : rawSet) {
|
|
45
|
+
stringSet.add(item != null ? item.toString() : "null");
|
|
46
|
+
}
|
|
47
|
+
editor.putStringSet(key, stringSet);
|
|
41
48
|
} else {
|
|
42
49
|
// Convert complex objects to JSON
|
|
43
50
|
String json;
|
|
@@ -56,7 +63,7 @@ public class SharedPreferencesStorage {
|
|
|
56
63
|
}
|
|
57
64
|
return editor.commit();
|
|
58
65
|
} catch (Exception e) {
|
|
59
|
-
e
|
|
66
|
+
Log.e("StrataStorage", "Failed to set value in SharedPreferences", e);
|
|
60
67
|
return false;
|
|
61
68
|
}
|
|
62
69
|
}
|
|
@@ -8,6 +8,7 @@ import com.getcapacitor.annotation.CapacitorPlugin;
|
|
|
8
8
|
import com.strata.storage.SharedPreferencesStorage;
|
|
9
9
|
import com.strata.storage.EncryptedStorage;
|
|
10
10
|
import com.strata.storage.SQLiteStorage;
|
|
11
|
+
import android.util.Log;
|
|
11
12
|
import org.json.JSONArray;
|
|
12
13
|
import org.json.JSONException;
|
|
13
14
|
import java.util.List;
|
|
@@ -30,7 +31,7 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
30
31
|
sqliteStorage = new SQLiteStorage(getContext());
|
|
31
32
|
} catch (Exception e) {
|
|
32
33
|
// Log error but don't crash - some storage types may not be available
|
|
33
|
-
e
|
|
34
|
+
Log.e("StrataStorage", "Failed to initialize storage", e);
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
|
|
@@ -68,20 +69,32 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
68
69
|
|
|
69
70
|
try {
|
|
70
71
|
Object value = null;
|
|
71
|
-
|
|
72
|
+
|
|
72
73
|
switch (storage) {
|
|
73
74
|
case "secure":
|
|
75
|
+
if (encryptedStorage == null) {
|
|
76
|
+
call.reject("Encrypted storage not available");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
74
79
|
value = encryptedStorage.get(key);
|
|
75
80
|
break;
|
|
76
81
|
case "sqlite":
|
|
82
|
+
if (sqliteStorage == null) {
|
|
83
|
+
call.reject("SQLite storage not available");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
77
86
|
value = sqliteStorage.get(key);
|
|
78
87
|
break;
|
|
79
88
|
case "preferences":
|
|
80
89
|
default:
|
|
90
|
+
if (sharedPrefsStorage == null) {
|
|
91
|
+
call.reject("Preferences storage not available");
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
81
94
|
value = sharedPrefsStorage.get(key);
|
|
82
95
|
break;
|
|
83
96
|
}
|
|
84
|
-
|
|
97
|
+
|
|
85
98
|
JSObject result = new JSObject();
|
|
86
99
|
result.put("value", value);
|
|
87
100
|
call.resolve(result);
|
|
@@ -107,17 +120,29 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
107
120
|
try {
|
|
108
121
|
switch (storage) {
|
|
109
122
|
case "secure":
|
|
123
|
+
if (encryptedStorage == null) {
|
|
124
|
+
call.reject("Encrypted storage not available");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
110
127
|
encryptedStorage.set(key, value);
|
|
111
128
|
break;
|
|
112
129
|
case "sqlite":
|
|
130
|
+
if (sqliteStorage == null) {
|
|
131
|
+
call.reject("SQLite storage not available");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
113
134
|
sqliteStorage.set(key, value);
|
|
114
135
|
break;
|
|
115
136
|
case "preferences":
|
|
116
137
|
default:
|
|
138
|
+
if (sharedPrefsStorage == null) {
|
|
139
|
+
call.reject("Preferences storage not available");
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
117
142
|
sharedPrefsStorage.set(key, value);
|
|
118
143
|
break;
|
|
119
144
|
}
|
|
120
|
-
|
|
145
|
+
|
|
121
146
|
call.resolve();
|
|
122
147
|
} catch (Exception e) {
|
|
123
148
|
call.reject("Failed to set value", e);
|
|
@@ -140,17 +165,29 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
140
165
|
try {
|
|
141
166
|
switch (storage) {
|
|
142
167
|
case "secure":
|
|
168
|
+
if (encryptedStorage == null) {
|
|
169
|
+
call.reject("Encrypted storage not available");
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
143
172
|
encryptedStorage.remove(key);
|
|
144
173
|
break;
|
|
145
174
|
case "sqlite":
|
|
175
|
+
if (sqliteStorage == null) {
|
|
176
|
+
call.reject("SQLite storage not available");
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
146
179
|
sqliteStorage.remove(key);
|
|
147
180
|
break;
|
|
148
181
|
case "preferences":
|
|
149
182
|
default:
|
|
183
|
+
if (sharedPrefsStorage == null) {
|
|
184
|
+
call.reject("Preferences storage not available");
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
150
187
|
sharedPrefsStorage.remove(key);
|
|
151
188
|
break;
|
|
152
189
|
}
|
|
153
|
-
|
|
190
|
+
|
|
154
191
|
call.resolve();
|
|
155
192
|
} catch (Exception e) {
|
|
156
193
|
call.reject("Failed to remove value", e);
|
|
@@ -168,17 +205,29 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
168
205
|
try {
|
|
169
206
|
switch (storage) {
|
|
170
207
|
case "secure":
|
|
208
|
+
if (encryptedStorage == null) {
|
|
209
|
+
call.reject("Encrypted storage not available");
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
171
212
|
encryptedStorage.clear(prefix);
|
|
172
213
|
break;
|
|
173
214
|
case "sqlite":
|
|
215
|
+
if (sqliteStorage == null) {
|
|
216
|
+
call.reject("SQLite storage not available");
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
174
219
|
sqliteStorage.clear(prefix);
|
|
175
220
|
break;
|
|
176
221
|
case "preferences":
|
|
177
222
|
default:
|
|
223
|
+
if (sharedPrefsStorage == null) {
|
|
224
|
+
call.reject("Preferences storage not available");
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
178
227
|
sharedPrefsStorage.clear(prefix);
|
|
179
228
|
break;
|
|
180
229
|
}
|
|
181
|
-
|
|
230
|
+
|
|
182
231
|
call.resolve();
|
|
183
232
|
} catch (Exception e) {
|
|
184
233
|
call.reject("Failed to clear storage", e);
|
|
@@ -195,20 +244,32 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
195
244
|
|
|
196
245
|
try {
|
|
197
246
|
List<String> keys = null;
|
|
198
|
-
|
|
247
|
+
|
|
199
248
|
switch (storage) {
|
|
200
249
|
case "secure":
|
|
250
|
+
if (encryptedStorage == null) {
|
|
251
|
+
call.reject("Encrypted storage not available");
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
201
254
|
keys = encryptedStorage.keys(pattern);
|
|
202
255
|
break;
|
|
203
256
|
case "sqlite":
|
|
257
|
+
if (sqliteStorage == null) {
|
|
258
|
+
call.reject("SQLite storage not available");
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
204
261
|
keys = sqliteStorage.keys(pattern);
|
|
205
262
|
break;
|
|
206
263
|
case "preferences":
|
|
207
264
|
default:
|
|
265
|
+
if (sharedPrefsStorage == null) {
|
|
266
|
+
call.reject("Preferences storage not available");
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
208
269
|
keys = sharedPrefsStorage.keys(pattern);
|
|
209
270
|
break;
|
|
210
271
|
}
|
|
211
|
-
|
|
272
|
+
|
|
212
273
|
JSObject result = new JSObject();
|
|
213
274
|
result.put("keys", new JSONArray(keys));
|
|
214
275
|
call.resolve(result);
|
|
@@ -226,26 +287,38 @@ public class StrataStoragePlugin extends Plugin {
|
|
|
226
287
|
|
|
227
288
|
try {
|
|
228
289
|
JSObject result = new JSObject();
|
|
229
|
-
|
|
290
|
+
|
|
230
291
|
switch (storage) {
|
|
231
292
|
case "secure":
|
|
293
|
+
if (encryptedStorage == null) {
|
|
294
|
+
call.reject("Encrypted storage not available");
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
232
297
|
EncryptedStorage.SizeInfo encryptedSizeInfo = encryptedStorage.size();
|
|
233
298
|
result.put("total", encryptedSizeInfo.total);
|
|
234
299
|
result.put("count", encryptedSizeInfo.count);
|
|
235
300
|
break;
|
|
236
301
|
case "sqlite":
|
|
302
|
+
if (sqliteStorage == null) {
|
|
303
|
+
call.reject("SQLite storage not available");
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
237
306
|
SQLiteStorage.SizeInfo sqliteSizeInfo = sqliteStorage.size();
|
|
238
307
|
result.put("total", sqliteSizeInfo.total);
|
|
239
308
|
result.put("count", sqliteSizeInfo.count);
|
|
240
309
|
break;
|
|
241
310
|
case "preferences":
|
|
242
311
|
default:
|
|
312
|
+
if (sharedPrefsStorage == null) {
|
|
313
|
+
call.reject("Preferences storage not available");
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
243
316
|
SharedPreferencesStorage.SizeInfo prefsSizeInfo = sharedPrefsStorage.size();
|
|
244
317
|
result.put("total", prefsSizeInfo.total);
|
|
245
318
|
result.put("count", prefsSizeInfo.count);
|
|
246
319
|
break;
|
|
247
320
|
}
|
|
248
|
-
|
|
321
|
+
|
|
249
322
|
call.resolve(result);
|
|
250
323
|
} catch (Exception e) {
|
|
251
324
|
call.reject("Failed to get size", e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Strata.d.ts","sourceRoot":"","sources":["../../src/core/Strata.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,cAAc,EACd,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAQpD;;GAEG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAA+C;IAC/D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,iBAAiB,CAAC,CAAoB;IAC9C,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAChD,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,UAAU,CAAC,CAAa;IAChC,OAAO,CAAC,YAAY,CAAkB;gBAE1B,MAAM,GAAE,YAAiB;IAMrC;;OAEG;IACH,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,QAAQ,CAEvB;IAED;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAmDjC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IA2DhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAwDtF;;;;;;;;;;;;;;;;OAgBG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAelE;;;;;;;;;;;;;;;;;OAiBG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAKlE;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAYnE;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBlF;;OAEG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAiCjD;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,mBAAmB;IAuBxF;;OAEG;IACG,KAAK,CAAC,CAAC,GAAG,OAAO,EACrB,SAAS,EAAE,cAAc,EACzB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IAU5C;;OAEG;IACG,MAAM,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBtD;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"Strata.d.ts","sourceRoot":"","sources":["../../src/core/Strata.ts"],"names":[],"mappings":"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"}
|
package/dist/core/Strata.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Zero-dependency universal storage solution
|
|
4
4
|
*/
|
|
5
5
|
import { AdapterRegistry } from "./AdapterRegistry.js";
|
|
6
|
-
import { isBrowser, isNode } from "../utils/index.js";
|
|
6
|
+
import { isBrowser, isNode, deepMerge } from "../utils/index.js";
|
|
7
7
|
import { StorageError, EncryptionError } from "../utils/errors.js";
|
|
8
8
|
import { EncryptionManager } from "../features/encryption.js";
|
|
9
9
|
import { CompressionManager } from "../features/compression.js";
|
|
@@ -474,11 +474,9 @@ export class Strata {
|
|
|
474
474
|
else if (options?.merge) {
|
|
475
475
|
const existing = await this.get(key);
|
|
476
476
|
if (options.merge === 'deep' && typeof existing === 'object' && typeof value === 'object') {
|
|
477
|
-
//
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
...value,
|
|
481
|
-
});
|
|
477
|
+
// Use deep merge utility for proper nested object merging
|
|
478
|
+
const merged = deepMerge(existing, value);
|
|
479
|
+
await this.set(key, merged);
|
|
482
480
|
}
|
|
483
481
|
else {
|
|
484
482
|
await this.set(key, value);
|
package/dist/firebase.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"firebase.d.ts","sourceRoot":"","sources":["../src/firebase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"firebase.d.ts","sourceRoot":"","sources":["../src/firebase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAI5C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,IAAI,CAAC,CAyOf;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CAQ5D"}
|
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
|
-
|
|
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
|
-
|
|
60
|
-
|
|
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
|
-
|
|
64
|
-
|
|
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
|
-
|
|
77
|
-
|
|
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
|
-
|
|
139
|
-
|
|
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
|
|
211
|
+
throw new StorageError('Failed to enable Firebase sync', {
|
|
212
|
+
originalError: error,
|
|
213
|
+
config,
|
|
214
|
+
});
|
|
153
215
|
}
|
|
154
216
|
}
|
|
155
217
|
/**
|