strata-storage 1.0.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 (102) hide show
  1. package/Readme.md +113 -0
  2. package/android/src/main/java/com/strata/storage/EncryptedStorage.java +65 -0
  3. package/android/src/main/java/com/strata/storage/SQLiteStorage.java +147 -0
  4. package/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +74 -0
  5. package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +256 -0
  6. package/dist/adapters/capacitor/FilesystemAdapter.d.ts +46 -0
  7. package/dist/adapters/capacitor/FilesystemAdapter.d.ts.map +1 -0
  8. package/dist/adapters/capacitor/FilesystemAdapter.js +162 -0
  9. package/dist/adapters/capacitor/PreferencesAdapter.d.ts +46 -0
  10. package/dist/adapters/capacitor/PreferencesAdapter.d.ts.map +1 -0
  11. package/dist/adapters/capacitor/PreferencesAdapter.js +162 -0
  12. package/dist/adapters/capacitor/SecureAdapter.d.ts +69 -0
  13. package/dist/adapters/capacitor/SecureAdapter.d.ts.map +1 -0
  14. package/dist/adapters/capacitor/SecureAdapter.js +214 -0
  15. package/dist/adapters/capacitor/SqliteAdapter.d.ts +68 -0
  16. package/dist/adapters/capacitor/SqliteAdapter.d.ts.map +1 -0
  17. package/dist/adapters/capacitor/SqliteAdapter.js +277 -0
  18. package/dist/adapters/capacitor/index.d.ts +9 -0
  19. package/dist/adapters/capacitor/index.d.ts.map +1 -0
  20. package/dist/adapters/capacitor/index.js +8 -0
  21. package/dist/adapters/web/CacheAdapter.d.ts +91 -0
  22. package/dist/adapters/web/CacheAdapter.d.ts.map +1 -0
  23. package/dist/adapters/web/CacheAdapter.js +291 -0
  24. package/dist/adapters/web/CookieAdapter.d.ts +77 -0
  25. package/dist/adapters/web/CookieAdapter.d.ts.map +1 -0
  26. package/dist/adapters/web/CookieAdapter.js +260 -0
  27. package/dist/adapters/web/IndexedDBAdapter.d.ts +78 -0
  28. package/dist/adapters/web/IndexedDBAdapter.d.ts.map +1 -0
  29. package/dist/adapters/web/IndexedDBAdapter.js +371 -0
  30. package/dist/adapters/web/LocalStorageAdapter.d.ts +63 -0
  31. package/dist/adapters/web/LocalStorageAdapter.d.ts.map +1 -0
  32. package/dist/adapters/web/LocalStorageAdapter.js +238 -0
  33. package/dist/adapters/web/MemoryAdapter.d.ts +69 -0
  34. package/dist/adapters/web/MemoryAdapter.d.ts.map +1 -0
  35. package/dist/adapters/web/MemoryAdapter.js +165 -0
  36. package/dist/adapters/web/SessionStorageAdapter.d.ts +53 -0
  37. package/dist/adapters/web/SessionStorageAdapter.d.ts.map +1 -0
  38. package/dist/adapters/web/SessionStorageAdapter.js +180 -0
  39. package/dist/adapters/web/index.d.ts +10 -0
  40. package/dist/adapters/web/index.d.ts.map +1 -0
  41. package/dist/adapters/web/index.js +9 -0
  42. package/dist/core/AdapterRegistry.d.ts +52 -0
  43. package/dist/core/AdapterRegistry.d.ts.map +1 -0
  44. package/dist/core/AdapterRegistry.js +102 -0
  45. package/dist/core/BaseAdapter.d.ts +79 -0
  46. package/dist/core/BaseAdapter.d.ts.map +1 -0
  47. package/dist/core/BaseAdapter.js +197 -0
  48. package/dist/core/StorageStrategy.d.ts +55 -0
  49. package/dist/core/StorageStrategy.d.ts.map +1 -0
  50. package/dist/core/StorageStrategy.js +199 -0
  51. package/dist/core/Strata.d.ts +122 -0
  52. package/dist/core/Strata.d.ts.map +1 -0
  53. package/dist/core/Strata.js +568 -0
  54. package/dist/features/compression.d.ts +65 -0
  55. package/dist/features/compression.d.ts.map +1 -0
  56. package/dist/features/compression.js +205 -0
  57. package/dist/features/encryption.d.ts +68 -0
  58. package/dist/features/encryption.d.ts.map +1 -0
  59. package/dist/features/encryption.js +172 -0
  60. package/dist/features/migration.d.ts +17 -0
  61. package/dist/features/migration.d.ts.map +1 -0
  62. package/dist/features/migration.js +43 -0
  63. package/dist/features/query.d.ts +75 -0
  64. package/dist/features/query.d.ts.map +1 -0
  65. package/dist/features/query.js +305 -0
  66. package/dist/features/sync.d.ts +87 -0
  67. package/dist/features/sync.d.ts.map +1 -0
  68. package/dist/features/sync.js +233 -0
  69. package/dist/features/ttl.d.ts +124 -0
  70. package/dist/features/ttl.d.ts.map +1 -0
  71. package/dist/features/ttl.js +236 -0
  72. package/dist/index.d.ts +44 -0
  73. package/dist/index.d.ts.map +1 -0
  74. package/dist/index.js +46 -0
  75. package/dist/package.json +60 -0
  76. package/dist/plugin/definitions.d.ts +219 -0
  77. package/dist/plugin/definitions.d.ts.map +1 -0
  78. package/dist/plugin/definitions.js +5 -0
  79. package/dist/plugin/index.d.ts +8 -0
  80. package/dist/plugin/index.d.ts.map +1 -0
  81. package/dist/plugin/index.js +27 -0
  82. package/dist/plugin/web.d.ts +24 -0
  83. package/dist/plugin/web.d.ts.map +1 -0
  84. package/dist/plugin/web.js +35 -0
  85. package/dist/types/index.d.ts +558 -0
  86. package/dist/types/index.d.ts.map +1 -0
  87. package/dist/types/index.js +14 -0
  88. package/dist/utils/errors.d.ts +92 -0
  89. package/dist/utils/errors.d.ts.map +1 -0
  90. package/dist/utils/errors.js +153 -0
  91. package/dist/utils/index.d.ts +105 -0
  92. package/dist/utils/index.d.ts.map +1 -0
  93. package/dist/utils/index.js +329 -0
  94. package/ios/Plugin/KeychainStorage.swift +87 -0
  95. package/ios/Plugin/SQLiteStorage.swift +167 -0
  96. package/ios/Plugin/StrataStoragePlugin.swift +204 -0
  97. package/ios/Plugin/UserDefaultsStorage.swift +44 -0
  98. package/package.json +126 -0
  99. package/scripts/build.js +52 -0
  100. package/scripts/cli.js +60 -0
  101. package/scripts/configure.js +444 -0
  102. package/scripts/postinstall.js +33 -0
@@ -0,0 +1,568 @@
1
+ /**
2
+ * Strata Storage - Main entry point
3
+ * Zero-dependency universal storage solution
4
+ */
5
+ import { AdapterRegistry } from './AdapterRegistry';
6
+ import { isBrowser, isNode, isCapacitor } from '@/utils';
7
+ import { StorageError, EncryptionError } from '@/utils/errors';
8
+ import { EncryptionManager } from '@/features/encryption';
9
+ import { CompressionManager } from '@/features/compression';
10
+ import { SyncManager } from '@/features/sync';
11
+ import { TTLManager } from '@/features/ttl';
12
+ /**
13
+ * Main Strata class - unified storage interface
14
+ */
15
+ export class Strata {
16
+ config;
17
+ registry;
18
+ defaultAdapter;
19
+ adapters = new Map();
20
+ platform;
21
+ encryptionManager;
22
+ compressionManager;
23
+ syncManager;
24
+ ttlManager;
25
+ constructor(config = {}) {
26
+ this.config = this.normalizeConfig(config);
27
+ this.platform = this.detectPlatform();
28
+ this.registry = new AdapterRegistry();
29
+ }
30
+ /**
31
+ * Initialize Strata with available adapters
32
+ */
33
+ async initialize() {
34
+ // Register all adapters based on platform
35
+ await this.registerAdapters();
36
+ // Find and set default adapter
37
+ await this.selectDefaultAdapter();
38
+ // Initialize configured adapters
39
+ await this.initializeAdapters();
40
+ // Initialize encryption if enabled
41
+ if (this.config.encryption?.enabled) {
42
+ this.encryptionManager = new EncryptionManager(this.config.encryption);
43
+ if (!this.encryptionManager.isAvailable()) {
44
+ console.warn('Encryption enabled but Web Crypto API not available');
45
+ }
46
+ }
47
+ // Initialize compression if enabled
48
+ if (this.config.compression?.enabled) {
49
+ this.compressionManager = new CompressionManager(this.config.compression);
50
+ }
51
+ // Initialize sync if enabled
52
+ if (this.config.sync?.enabled) {
53
+ this.syncManager = new SyncManager(this.config.sync);
54
+ await this.syncManager.initialize();
55
+ // Subscribe to sync events
56
+ this.syncManager.subscribe((_change) => {
57
+ // Forward sync events to subscribers
58
+ // The adapters will handle their own change events
59
+ });
60
+ }
61
+ // Initialize TTL manager
62
+ this.ttlManager = new TTLManager(this.config.ttl);
63
+ // Set up TTL cleanup for default adapter
64
+ if (this.defaultAdapter && this.config.ttl?.autoCleanup !== false) {
65
+ this.ttlManager.startAutoCleanup(() => this.defaultAdapter.keys(), (key) => this.defaultAdapter.get(key), (key) => this.defaultAdapter.remove(key));
66
+ }
67
+ }
68
+ /**
69
+ * Get a value from storage
70
+ */
71
+ async get(key, options) {
72
+ const adapter = await this.selectAdapter(options?.storage);
73
+ const value = await adapter.get(key);
74
+ if (!value)
75
+ return null;
76
+ // Handle TTL
77
+ if (this.ttlManager && this.ttlManager.isExpired(value)) {
78
+ await adapter.remove(key);
79
+ return null;
80
+ }
81
+ // Update sliding TTL if configured
82
+ if (options?.sliding && value.expires && this.ttlManager) {
83
+ const updatedValue = this.ttlManager.updateExpiration(value, options);
84
+ if (updatedValue !== value) {
85
+ await adapter.set(key, updatedValue);
86
+ }
87
+ }
88
+ // Handle decryption if needed
89
+ if (value.encrypted && this.encryptionManager) {
90
+ try {
91
+ if (!options?.skipDecryption) {
92
+ const password = options?.encryptionPassword || this.config.encryption?.password;
93
+ if (!password) {
94
+ throw new EncryptionError('Encrypted value requires password for decryption');
95
+ }
96
+ const decrypted = await this.encryptionManager.decrypt(value.value, password);
97
+ return decrypted;
98
+ }
99
+ }
100
+ catch (error) {
101
+ if (options?.ignoreDecryptionErrors) {
102
+ console.warn(`Failed to decrypt key ${key}:`, error);
103
+ return null;
104
+ }
105
+ throw error;
106
+ }
107
+ }
108
+ // Handle decompression if needed
109
+ if (value.compressed && this.compressionManager) {
110
+ try {
111
+ const decompressed = await this.compressionManager.decompress(value.value);
112
+ return decompressed;
113
+ }
114
+ catch (error) {
115
+ console.warn(`Failed to decompress key ${key}:`, error);
116
+ return value.value;
117
+ }
118
+ }
119
+ return value.value;
120
+ }
121
+ /**
122
+ * Set a value in storage
123
+ */
124
+ async set(key, value, options) {
125
+ const adapter = await this.selectAdapter(options?.storage);
126
+ const now = Date.now();
127
+ let processedValue = value;
128
+ let compressed = false;
129
+ // Handle compression if needed
130
+ const shouldCompress = options?.compress ?? this.config.compression?.enabled;
131
+ if (shouldCompress && this.compressionManager) {
132
+ const compressedResult = await this.compressionManager.compress(value);
133
+ if (this.compressionManager.isCompressedData(compressedResult)) {
134
+ processedValue = compressedResult;
135
+ compressed = true;
136
+ }
137
+ }
138
+ // Handle encryption if needed
139
+ const shouldEncrypt = options?.encrypt ?? this.config.encryption?.enabled;
140
+ let encrypted = false;
141
+ if (shouldEncrypt && this.encryptionManager) {
142
+ const password = options?.encryptionPassword || this.config.encryption?.password;
143
+ if (!password) {
144
+ throw new EncryptionError('Encryption enabled but no password provided');
145
+ }
146
+ processedValue = await this.encryptionManager.encrypt(value, password);
147
+ encrypted = true;
148
+ }
149
+ const storageValue = {
150
+ value: processedValue,
151
+ created: now,
152
+ updated: now,
153
+ expires: this.ttlManager ? this.ttlManager.calculateExpiration(options) : undefined,
154
+ tags: options?.tags,
155
+ metadata: options?.metadata,
156
+ encrypted: encrypted,
157
+ compressed: compressed,
158
+ };
159
+ await adapter.set(key, storageValue);
160
+ // Broadcast change for sync
161
+ if (this.syncManager) {
162
+ this.syncManager.broadcast({
163
+ type: 'set',
164
+ key,
165
+ value: storageValue,
166
+ storage: adapter.name,
167
+ timestamp: now,
168
+ });
169
+ }
170
+ }
171
+ /**
172
+ * Remove a value from storage
173
+ */
174
+ async remove(key, options) {
175
+ const adapter = await this.selectAdapter(options?.storage);
176
+ await adapter.remove(key);
177
+ // Broadcast removal for sync
178
+ if (this.syncManager) {
179
+ this.syncManager.broadcast({
180
+ type: 'remove',
181
+ key,
182
+ storage: adapter.name,
183
+ timestamp: Date.now(),
184
+ });
185
+ }
186
+ }
187
+ /**
188
+ * Check if a key exists
189
+ */
190
+ async has(key, options) {
191
+ const adapter = await this.selectAdapter(options?.storage);
192
+ return adapter.has(key);
193
+ }
194
+ /**
195
+ * Clear storage
196
+ */
197
+ async clear(options) {
198
+ if (options?.storage) {
199
+ const adapter = await this.selectAdapter(options.storage);
200
+ await adapter.clear(options);
201
+ }
202
+ else {
203
+ // Clear all adapters
204
+ for (const adapter of this.adapters.values()) {
205
+ await adapter.clear(options);
206
+ }
207
+ }
208
+ }
209
+ /**
210
+ * Get all keys
211
+ */
212
+ async keys(pattern, options) {
213
+ if (options?.storage) {
214
+ const adapter = await this.selectAdapter(options.storage);
215
+ return adapter.keys(pattern);
216
+ }
217
+ // Get keys from all adapters and deduplicate
218
+ const allKeys = new Set();
219
+ for (const adapter of this.adapters.values()) {
220
+ const keys = await adapter.keys(pattern);
221
+ keys.forEach((key) => allKeys.add(key));
222
+ }
223
+ return Array.from(allKeys);
224
+ }
225
+ /**
226
+ * Get storage size information
227
+ */
228
+ async size(detailed) {
229
+ let total = 0;
230
+ let count = 0;
231
+ const byStorage = {};
232
+ for (const [type, adapter] of this.adapters.entries()) {
233
+ const sizeInfo = await adapter.size(detailed);
234
+ total += sizeInfo.total;
235
+ count += sizeInfo.count;
236
+ byStorage[type] = sizeInfo.total;
237
+ }
238
+ return {
239
+ total,
240
+ count,
241
+ byStorage: byStorage,
242
+ };
243
+ }
244
+ /**
245
+ * Subscribe to storage changes
246
+ */
247
+ subscribe(callback, options) {
248
+ const unsubscribers = [];
249
+ if (options?.storage) {
250
+ const adapter = this.adapters.get(options.storage);
251
+ if (adapter?.subscribe) {
252
+ unsubscribers.push(adapter.subscribe(callback));
253
+ }
254
+ }
255
+ else {
256
+ // Subscribe to all adapters that support it
257
+ for (const adapter of this.adapters.values()) {
258
+ if (adapter.subscribe) {
259
+ unsubscribers.push(adapter.subscribe(callback));
260
+ }
261
+ }
262
+ }
263
+ // Return function to unsubscribe from all
264
+ return () => {
265
+ unsubscribers.forEach((unsub) => unsub());
266
+ };
267
+ }
268
+ /**
269
+ * Query storage (if supported)
270
+ */
271
+ async query(condition, options) {
272
+ const adapter = await this.selectAdapter(options?.storage);
273
+ if (!adapter.query) {
274
+ throw new StorageError(`Adapter ${adapter.name} does not support queries`);
275
+ }
276
+ return adapter.query(condition);
277
+ }
278
+ /**
279
+ * Export storage data
280
+ */
281
+ async export(options) {
282
+ const data = {};
283
+ const keys = options?.keys || (await this.keys());
284
+ for (const key of keys) {
285
+ const value = await this.get(key);
286
+ if (value !== null) {
287
+ if (options?.includeMetadata) {
288
+ const adapter = await this.selectAdapter();
289
+ const storageValue = await adapter.get(key);
290
+ data[key] = storageValue;
291
+ }
292
+ else {
293
+ data[key] = value;
294
+ }
295
+ }
296
+ }
297
+ const format = options?.format || 'json';
298
+ if (format === 'json') {
299
+ return JSON.stringify(data, null, options?.pretty ? 2 : 0);
300
+ }
301
+ throw new StorageError(`Export format ${format} not supported`);
302
+ }
303
+ /**
304
+ * Import storage data
305
+ */
306
+ async import(data, options) {
307
+ const format = options?.format || 'json';
308
+ if (format !== 'json') {
309
+ throw new StorageError(`Import format ${format} not supported`);
310
+ }
311
+ const parsed = JSON.parse(data);
312
+ for (const [key, value] of Object.entries(parsed)) {
313
+ const exists = await this.has(key);
314
+ if (!exists || options?.overwrite) {
315
+ await this.set(key, value);
316
+ }
317
+ else if (options?.merge) {
318
+ const existing = await this.get(key);
319
+ if (options.merge === 'deep' && typeof existing === 'object' && typeof value === 'object') {
320
+ // Deep merge will be implemented with utils
321
+ await this.set(key, {
322
+ ...existing,
323
+ ...value,
324
+ });
325
+ }
326
+ else {
327
+ await this.set(key, value);
328
+ }
329
+ }
330
+ }
331
+ }
332
+ /**
333
+ * Get available storage types
334
+ */
335
+ getAvailableStorageTypes() {
336
+ return Array.from(this.adapters.keys());
337
+ }
338
+ /**
339
+ * Get adapter capabilities
340
+ */
341
+ getCapabilities(storage) {
342
+ if (storage) {
343
+ const adapter = this.adapters.get(storage);
344
+ return adapter ? adapter.capabilities : {};
345
+ }
346
+ // Return capabilities of all adapters
347
+ const capabilities = {};
348
+ for (const [type, adapter] of this.adapters.entries()) {
349
+ capabilities[type] = adapter.capabilities;
350
+ }
351
+ return capabilities;
352
+ }
353
+ /**
354
+ * Generate a secure password for encryption
355
+ */
356
+ generatePassword(length) {
357
+ if (!this.encryptionManager) {
358
+ throw new EncryptionError('Encryption not initialized');
359
+ }
360
+ return this.encryptionManager.generatePassword(length);
361
+ }
362
+ /**
363
+ * Hash data using SHA-256
364
+ */
365
+ async hash(data) {
366
+ if (!this.encryptionManager) {
367
+ throw new EncryptionError('Encryption not initialized');
368
+ }
369
+ return this.encryptionManager.hash(data);
370
+ }
371
+ /**
372
+ * Get TTL (time to live) for a key
373
+ */
374
+ async getTTL(key, options) {
375
+ if (!this.ttlManager)
376
+ return null;
377
+ const adapter = await this.selectAdapter(options?.storage);
378
+ const value = await adapter.get(key);
379
+ if (!value)
380
+ return null;
381
+ return this.ttlManager.getTimeToLive(value);
382
+ }
383
+ /**
384
+ * Extend TTL for a key
385
+ */
386
+ async extendTTL(key, extension, options) {
387
+ if (!this.ttlManager) {
388
+ throw new StorageError('TTL manager not initialized');
389
+ }
390
+ const adapter = await this.selectAdapter(options?.storage);
391
+ const value = await adapter.get(key);
392
+ if (!value) {
393
+ throw new StorageError(`Key ${key} not found`);
394
+ }
395
+ const updated = this.ttlManager.extendTTL(value, extension);
396
+ await adapter.set(key, updated);
397
+ }
398
+ /**
399
+ * Make a key persistent (remove TTL)
400
+ */
401
+ async persist(key, options) {
402
+ if (!this.ttlManager) {
403
+ throw new StorageError('TTL manager not initialized');
404
+ }
405
+ const adapter = await this.selectAdapter(options?.storage);
406
+ const value = await adapter.get(key);
407
+ if (!value) {
408
+ throw new StorageError(`Key ${key} not found`);
409
+ }
410
+ const persisted = this.ttlManager.persist(value);
411
+ await adapter.set(key, persisted);
412
+ }
413
+ /**
414
+ * Get items expiring within a time window
415
+ */
416
+ async getExpiring(timeWindow, options) {
417
+ if (!this.ttlManager)
418
+ return [];
419
+ const adapter = await this.selectAdapter(options?.storage);
420
+ return this.ttlManager.getExpiring(timeWindow, () => adapter.keys(), (key) => adapter.get(key));
421
+ }
422
+ /**
423
+ * Manually trigger TTL cleanup
424
+ */
425
+ async cleanupExpired(options) {
426
+ if (!this.ttlManager)
427
+ return 0;
428
+ const adapter = await this.selectAdapter(options?.storage);
429
+ const expired = await this.ttlManager.cleanup(() => adapter.keys(), (key) => adapter.get(key), (key) => adapter.remove(key));
430
+ return expired.length;
431
+ }
432
+ /**
433
+ * Close all adapters
434
+ */
435
+ async close() {
436
+ for (const adapter of this.adapters.values()) {
437
+ if (adapter.close) {
438
+ await adapter.close();
439
+ }
440
+ }
441
+ this.adapters.clear();
442
+ // Clear encryption cache
443
+ if (this.encryptionManager) {
444
+ this.encryptionManager.clearCache();
445
+ }
446
+ // Close sync manager
447
+ if (this.syncManager) {
448
+ this.syncManager.close();
449
+ }
450
+ // Clear TTL manager
451
+ if (this.ttlManager) {
452
+ this.ttlManager.clear();
453
+ }
454
+ }
455
+ // Private methods
456
+ normalizeConfig(config) {
457
+ return {
458
+ platform: config.platform || this.detectPlatform(),
459
+ defaultStorages: config.defaultStorages || this.getDefaultStorages(),
460
+ ...config,
461
+ };
462
+ }
463
+ detectPlatform() {
464
+ if (isCapacitor())
465
+ return 'web'; // Capacitor runs in web context
466
+ if (isBrowser())
467
+ return 'web';
468
+ if (isNode())
469
+ return 'node';
470
+ return 'web'; // Default to web
471
+ }
472
+ getDefaultStorages() {
473
+ switch (this.platform) {
474
+ case 'web':
475
+ if (isCapacitor()) {
476
+ return ['preferences', 'sqlite', 'indexedDB', 'localStorage', 'memory'];
477
+ }
478
+ return ['indexedDB', 'localStorage', 'memory'];
479
+ case 'node':
480
+ return ['filesystem', 'memory'];
481
+ case 'ios':
482
+ case 'android':
483
+ return ['preferences', 'sqlite', 'secure', 'memory'];
484
+ default:
485
+ return ['memory'];
486
+ }
487
+ }
488
+ async registerAdapters() {
489
+ // Register adapters based on platform
490
+ if (this.platform === 'web') {
491
+ // Dynamically import and register web adapters
492
+ const { MemoryAdapter } = await import('@/adapters/web/MemoryAdapter');
493
+ const { LocalStorageAdapter } = await import('@/adapters/web/LocalStorageAdapter');
494
+ const { SessionStorageAdapter } = await import('@/adapters/web/SessionStorageAdapter');
495
+ const { IndexedDBAdapter } = await import('@/adapters/web/IndexedDBAdapter');
496
+ const { CookieAdapter } = await import('@/adapters/web/CookieAdapter');
497
+ const { CacheAdapter } = await import('@/adapters/web/CacheAdapter');
498
+ this.registry.register(new MemoryAdapter());
499
+ this.registry.register(new LocalStorageAdapter());
500
+ this.registry.register(new SessionStorageAdapter());
501
+ this.registry.register(new IndexedDBAdapter());
502
+ this.registry.register(new CookieAdapter());
503
+ this.registry.register(new CacheAdapter());
504
+ // If running in Capacitor, also register native adapters
505
+ if (isCapacitor()) {
506
+ const { PreferencesAdapter } = await import('@/adapters/capacitor/PreferencesAdapter');
507
+ const { SqliteAdapter } = await import('@/adapters/capacitor/SqliteAdapter');
508
+ const { SecureAdapter } = await import('@/adapters/capacitor/SecureAdapter');
509
+ const { FilesystemAdapter } = await import('@/adapters/capacitor/FilesystemAdapter');
510
+ this.registry.register(new PreferencesAdapter());
511
+ this.registry.register(new SqliteAdapter());
512
+ this.registry.register(new SecureAdapter());
513
+ this.registry.register(new FilesystemAdapter());
514
+ }
515
+ }
516
+ // Additional adapters will be registered as they are implemented
517
+ }
518
+ async selectDefaultAdapter() {
519
+ const storages = this.config.defaultStorages || this.getDefaultStorages();
520
+ for (const storage of storages) {
521
+ try {
522
+ const adapter = await this.registry.getInitialized(storage, this.config.adapters?.[storage]);
523
+ this.defaultAdapter = adapter;
524
+ this.adapters.set(storage, adapter);
525
+ return;
526
+ }
527
+ catch {
528
+ // Continue to next adapter
529
+ }
530
+ }
531
+ throw new StorageError('No available storage adapters found');
532
+ }
533
+ async initializeAdapters() {
534
+ for (const [type, adapter] of this.adapters.entries()) {
535
+ const config = this.config.adapters?.[type];
536
+ if (config && typeof config === 'object') {
537
+ await adapter.initialize(config);
538
+ }
539
+ else {
540
+ await adapter.initialize();
541
+ }
542
+ }
543
+ }
544
+ async selectAdapter(storage) {
545
+ if (!storage) {
546
+ if (!this.defaultAdapter) {
547
+ throw new StorageError('No default adapter available');
548
+ }
549
+ return this.defaultAdapter;
550
+ }
551
+ const storages = Array.isArray(storage) ? storage : [storage];
552
+ for (const s of storages) {
553
+ const adapter = this.adapters.get(s);
554
+ if (adapter)
555
+ return adapter;
556
+ }
557
+ // Try to load adapter if not already loaded
558
+ for (const s of storages) {
559
+ const adapter = this.registry.get(s);
560
+ if (adapter && (await adapter.isAvailable())) {
561
+ await adapter.initialize();
562
+ this.adapters.set(s, adapter);
563
+ return adapter;
564
+ }
565
+ }
566
+ throw new StorageError(`No available adapter found for storage types: ${storages.join(', ')}`);
567
+ }
568
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Compression Feature - Pure JavaScript LZ-string implementation
3
+ * Zero-dependency compression/decompression for storage values
4
+ */
5
+ /**
6
+ * Compression configuration
7
+ */
8
+ export interface CompressionConfig {
9
+ algorithm?: 'lz' | 'gzip';
10
+ threshold?: number;
11
+ level?: number;
12
+ }
13
+ /**
14
+ * Compressed data structure
15
+ */
16
+ export interface CompressedData {
17
+ data: string;
18
+ algorithm: string;
19
+ originalSize: number;
20
+ compressedSize: number;
21
+ }
22
+ /**
23
+ * Compression manager using pure JavaScript LZ-string algorithm
24
+ */
25
+ export declare class CompressionManager {
26
+ private config;
27
+ constructor(config?: CompressionConfig);
28
+ /**
29
+ * Compress data using LZ-string algorithm
30
+ */
31
+ compress(data: unknown): Promise<CompressedData | unknown>;
32
+ /**
33
+ * Decompress data
34
+ */
35
+ decompress<T = unknown>(compressedData: CompressedData): Promise<T>;
36
+ /**
37
+ * Check if data is compressed
38
+ */
39
+ isCompressedData(data: unknown): data is CompressedData;
40
+ /**
41
+ * LZ-string compression implementation
42
+ */
43
+ private lzCompress;
44
+ /**
45
+ * LZ-string decompression implementation
46
+ */
47
+ private lzDecompress;
48
+ /**
49
+ * Base64 encoding for compressed data
50
+ */
51
+ private encodeToBase64;
52
+ /**
53
+ * Base64 decoding for compressed data
54
+ */
55
+ private decodeFromBase64;
56
+ /**
57
+ * Get compression ratio
58
+ */
59
+ getCompressionRatio(compressedData: CompressedData): number;
60
+ /**
61
+ * Get savings percentage
62
+ */
63
+ getSavingsPercentage(compressedData: CompressedData): number;
64
+ }
65
+ //# sourceMappingURL=compression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../../src/features/compression.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAA8B;gBAEhC,MAAM,GAAE,iBAAsB;IAQ1C;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC;IA8BhE;;OAEG;IACG,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAazE;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,cAAc;IAWvD;;OAEG;IACH,OAAO,CAAC,UAAU;IAmClB;;OAEG;IACH,OAAO,CAAC,YAAY;IA+BpB;;OAEG;IACH,OAAO,CAAC,cAAc;IA2BtB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA6BxB;;OAEG;IACH,mBAAmB,CAAC,cAAc,EAAE,cAAc,GAAG,MAAM;IAI3D;;OAEG;IACH,oBAAoB,CAAC,cAAc,EAAE,cAAc,GAAG,MAAM;CAO7D"}