strata-storage 1.5.0 → 2.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.
- package/Readme.md +66 -20
- package/dist/README.md +162 -0
- package/dist/adapters/capacitor/FilesystemAdapter.js +4 -4
- package/dist/adapters/capacitor/PreferencesAdapter.js +4 -4
- package/dist/adapters/capacitor/SecureAdapter.js +4 -4
- package/dist/adapters/capacitor/SqliteAdapter.js +4 -4
- package/dist/adapters/capacitor/index.js +4 -4
- package/dist/adapters/web/CacheAdapter.js +3 -3
- package/dist/adapters/web/CookieAdapter.js +2 -2
- package/dist/adapters/web/IndexedDBAdapter.js +3 -3
- package/dist/adapters/web/LocalStorageAdapter.js +3 -3
- package/dist/adapters/web/MemoryAdapter.js +3 -3
- package/dist/adapters/web/SessionStorageAdapter.js +1 -1
- package/dist/adapters/web/index.js +6 -6
- package/dist/android/src/main/java/com/strata/storage/EncryptedStorage.java +65 -0
- package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +147 -0
- package/dist/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +74 -0
- package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +256 -0
- package/dist/capacitor.d.ts +20 -0
- package/dist/capacitor.d.ts.map +1 -0
- package/dist/capacitor.js +48 -0
- package/dist/core/AdapterRegistry.js +1 -1
- package/dist/core/BaseAdapter.js +3 -3
- package/dist/core/StorageStrategy.js +1 -0
- package/dist/core/Strata.d.ts +28 -3
- package/dist/core/Strata.d.ts.map +1 -1
- package/dist/core/Strata.js +57 -58
- package/dist/features/compression/index.d.ts +2 -0
- package/dist/features/compression/index.d.ts.map +1 -0
- package/dist/features/compression/index.js +1 -0
- package/dist/features/compression.js +1 -1
- package/dist/features/encryption/index.d.ts +2 -0
- package/dist/features/encryption/index.d.ts.map +1 -0
- package/dist/features/encryption/index.js +1 -0
- package/dist/features/encryption.d.ts.map +1 -1
- package/dist/features/encryption.js +6 -5
- package/dist/features/observer/index.d.ts +2 -0
- package/dist/features/observer/index.d.ts.map +1 -0
- package/dist/features/observer/index.js +1 -0
- package/dist/features/observer.d.ts +20 -0
- package/dist/features/observer.d.ts.map +1 -0
- package/dist/features/observer.js +32 -0
- package/dist/features/query/index.d.ts +2 -0
- package/dist/features/query/index.d.ts.map +1 -0
- package/dist/features/query/index.js +1 -0
- package/dist/features/query.d.ts.map +1 -1
- package/dist/features/query.js +8 -1
- package/dist/features/sync/index.d.ts +2 -0
- package/dist/features/sync/index.d.ts.map +1 -0
- package/dist/features/sync/index.js +1 -0
- package/dist/features/sync.js +1 -1
- package/dist/features/ttl/index.d.ts +2 -0
- package/dist/features/ttl/index.d.ts.map +1 -0
- package/dist/features/ttl/index.js +1 -0
- package/dist/features/ttl.js +1 -1
- package/dist/firebase.d.ts +26 -0
- package/dist/firebase.d.ts.map +1 -0
- package/dist/firebase.js +147 -0
- package/dist/index.d.ts +13 -47
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -58
- package/dist/ios/Plugin/KeychainStorage.swift +87 -0
- package/dist/ios/Plugin/SQLiteStorage.swift +167 -0
- package/dist/ios/Plugin/StrataStoragePlugin.swift +204 -0
- package/dist/ios/Plugin/UserDefaultsStorage.swift +44 -0
- package/dist/package.json +22 -4
- package/dist/plugin/definitions.d.ts +2 -2
- package/dist/plugin/definitions.d.ts.map +1 -1
- package/dist/plugin/index.d.ts +2 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +77 -11
- package/dist/types/index.d.ts +190 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +13 -0
- package/dist/utils/index.d.ts +20 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +34 -0
- package/package.json +15 -24
- package/scripts/build.js +127 -14
- package/scripts/cli.js +6 -2
- package/scripts/configure.js +7 -3
- package/scripts/postinstall.js +21 -10
package/dist/core/Strata.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Strata Storage - Main entry point
|
|
3
3
|
* Zero-dependency universal storage solution
|
|
4
4
|
*/
|
|
5
|
-
import { AdapterRegistry } from
|
|
6
|
-
import { isBrowser, isNode
|
|
7
|
-
import { StorageError, EncryptionError } from
|
|
8
|
-
import { EncryptionManager } from
|
|
9
|
-
import { CompressionManager } from
|
|
10
|
-
import { SyncManager } from
|
|
11
|
-
import { TTLManager } from
|
|
5
|
+
import { AdapterRegistry } from "./AdapterRegistry.js";
|
|
6
|
+
import { isBrowser, isNode } from "../utils/index.js";
|
|
7
|
+
import { StorageError, EncryptionError } from "../utils/errors.js";
|
|
8
|
+
import { EncryptionManager } from "../features/encryption.js";
|
|
9
|
+
import { CompressionManager } from "../features/compression.js";
|
|
10
|
+
import { SyncManager } from "../features/sync.js";
|
|
11
|
+
import { TTLManager } from "../features/ttl.js";
|
|
12
12
|
/**
|
|
13
13
|
* Main Strata class - unified storage interface
|
|
14
14
|
*/
|
|
@@ -17,22 +17,35 @@ export class Strata {
|
|
|
17
17
|
registry;
|
|
18
18
|
defaultAdapter;
|
|
19
19
|
adapters = new Map();
|
|
20
|
-
|
|
20
|
+
_platform;
|
|
21
21
|
encryptionManager;
|
|
22
22
|
compressionManager;
|
|
23
23
|
syncManager;
|
|
24
24
|
ttlManager;
|
|
25
|
+
_initialized = false;
|
|
25
26
|
constructor(config = {}) {
|
|
26
27
|
this.config = this.normalizeConfig(config);
|
|
27
|
-
this.
|
|
28
|
+
this._platform = this.detectPlatform();
|
|
28
29
|
this.registry = new AdapterRegistry();
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Check if Strata has been initialized
|
|
33
|
+
*/
|
|
34
|
+
get isInitialized() {
|
|
35
|
+
return this._initialized;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get the detected platform
|
|
39
|
+
*/
|
|
40
|
+
get platform() {
|
|
41
|
+
return this._platform;
|
|
42
|
+
}
|
|
30
43
|
/**
|
|
31
44
|
* Initialize Strata with available adapters
|
|
32
45
|
*/
|
|
33
46
|
async initialize() {
|
|
34
|
-
//
|
|
35
|
-
|
|
47
|
+
// No automatic adapter registration - adapters should be registered before initialize()
|
|
48
|
+
// This allows for zero-dependency operation and explicit opt-in for features
|
|
36
49
|
// Find and set default adapter
|
|
37
50
|
await this.selectDefaultAdapter();
|
|
38
51
|
// Initialize configured adapters
|
|
@@ -64,6 +77,8 @@ export class Strata {
|
|
|
64
77
|
if (this.defaultAdapter && this.config.ttl?.autoCleanup !== false) {
|
|
65
78
|
this.ttlManager.startAutoCleanup(() => this.defaultAdapter.keys(), (key) => this.defaultAdapter.get(key), (key) => this.defaultAdapter.remove(key));
|
|
66
79
|
}
|
|
80
|
+
// Mark as initialized
|
|
81
|
+
this._initialized = true;
|
|
67
82
|
}
|
|
68
83
|
/**
|
|
69
84
|
* Get a value from storage
|
|
@@ -429,6 +444,26 @@ export class Strata {
|
|
|
429
444
|
const expired = await this.ttlManager.cleanup(() => adapter.keys(), (key) => adapter.get(key), (key) => adapter.remove(key));
|
|
430
445
|
return expired.length;
|
|
431
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* Register a custom storage adapter
|
|
449
|
+
* This allows external adapters to be registered after initialization
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* ```typescript
|
|
453
|
+
* import { MyCustomAdapter } from "./my-adapter.js";
|
|
454
|
+
* storage.registerAdapter(new MyCustomAdapter());
|
|
455
|
+
* ```
|
|
456
|
+
*/
|
|
457
|
+
registerAdapter(adapter) {
|
|
458
|
+
this.registry.register(adapter);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Get the adapter registry (for advanced use cases)
|
|
462
|
+
* @internal
|
|
463
|
+
*/
|
|
464
|
+
getRegistry() {
|
|
465
|
+
return this.registry;
|
|
466
|
+
}
|
|
432
467
|
/**
|
|
433
468
|
* Close all adapters
|
|
434
469
|
*/
|
|
@@ -456,13 +491,11 @@ export class Strata {
|
|
|
456
491
|
normalizeConfig(config) {
|
|
457
492
|
return {
|
|
458
493
|
platform: config.platform || this.detectPlatform(),
|
|
459
|
-
defaultStorages: config.defaultStorages ||
|
|
494
|
+
defaultStorages: config.defaultStorages || ['memory'], // Default to memory adapter
|
|
460
495
|
...config,
|
|
461
496
|
};
|
|
462
497
|
}
|
|
463
498
|
detectPlatform() {
|
|
464
|
-
if (isCapacitor())
|
|
465
|
-
return 'web'; // Capacitor runs in web context
|
|
466
499
|
if (isBrowser())
|
|
467
500
|
return 'web';
|
|
468
501
|
if (isNode())
|
|
@@ -470,50 +503,16 @@ export class Strata {
|
|
|
470
503
|
return 'web'; // Default to web
|
|
471
504
|
}
|
|
472
505
|
getDefaultStorages() {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
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
|
|
506
|
+
// Only return adapters that are actually registered
|
|
507
|
+
const registered = Array.from(this.registry.getAll().keys()).map((key) => String(key));
|
|
508
|
+
// Prefer these storages in order if available
|
|
509
|
+
const preferredOrder = ['indexedDB', 'localStorage', 'sessionStorage', 'memory'];
|
|
510
|
+
const available = preferredOrder.filter((storage) => registered.includes(storage));
|
|
511
|
+
// Always include memory as fallback if registered
|
|
512
|
+
if (available.length === 0 && registered.includes('memory')) {
|
|
513
|
+
return ['memory'];
|
|
514
|
+
}
|
|
515
|
+
return (available.length > 0 ? available : registered);
|
|
517
516
|
}
|
|
518
517
|
async selectDefaultAdapter() {
|
|
519
518
|
const storages = this.config.defaultStorages || this.getDefaultStorages();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/compression/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../compression.js";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Compression Feature - Pure JavaScript LZ-string implementation
|
|
3
3
|
* Zero-dependency compression/decompression for storage values
|
|
4
4
|
*/
|
|
5
|
-
import { CompressionError } from
|
|
5
|
+
import { CompressionError } from "../utils/errors.js";
|
|
6
6
|
/**
|
|
7
7
|
* Compression manager using pure JavaScript LZ-string algorithm
|
|
8
8
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/encryption/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../encryption.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/features/encryption.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAClC,SAAS,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,QAAQ,CAAqC;gBAEzC,MAAM,GAAE,gBAAqB;IASzC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACG,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/features/encryption.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAClC,SAAS,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,QAAQ,CAAqC;gBAEzC,MAAM,GAAE,gBAAqB;IASzC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACG,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA6CtE;;OAEG;IACG,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAiCtF;;OAEG;YACW,SAAS;IA8CvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,gBAAgB,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM;IAc7C;;OAEG;IACG,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAU1C"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Encryption Feature - Web Crypto API implementation
|
|
3
3
|
* Zero-dependency encryption/decryption for storage values
|
|
4
4
|
*/
|
|
5
|
-
import { EncryptionError } from
|
|
5
|
+
import { EncryptionError } from "../utils/errors.js";
|
|
6
6
|
/**
|
|
7
7
|
* Encryption manager using Web Crypto API
|
|
8
8
|
*/
|
|
@@ -48,8 +48,8 @@ export class EncryptionManager {
|
|
|
48
48
|
// Convert to base64 for storage
|
|
49
49
|
return {
|
|
50
50
|
data: this.bufferToBase64(encryptedBuffer),
|
|
51
|
-
salt: this.bufferToBase64(salt),
|
|
52
|
-
iv: this.bufferToBase64(iv),
|
|
51
|
+
salt: this.bufferToBase64(salt.buffer.slice(salt.byteOffset, salt.byteOffset + salt.byteLength)),
|
|
52
|
+
iv: this.bufferToBase64(iv.buffer.slice(iv.byteOffset, iv.byteOffset + iv.byteLength)),
|
|
53
53
|
algorithm: this.config.algorithm,
|
|
54
54
|
iterations: this.config.iterations,
|
|
55
55
|
};
|
|
@@ -91,7 +91,8 @@ export class EncryptionManager {
|
|
|
91
91
|
*/
|
|
92
92
|
async deriveKey(password, salt, iterations = this.config.iterations) {
|
|
93
93
|
// Check cache
|
|
94
|
-
const
|
|
94
|
+
const saltBuffer = salt.buffer.slice(salt.byteOffset, salt.byteOffset + salt.byteLength);
|
|
95
|
+
const cacheKey = `${password}-${this.bufferToBase64(saltBuffer)}-${iterations}`;
|
|
95
96
|
if (this.keyCache.has(cacheKey)) {
|
|
96
97
|
return this.keyCache.get(cacheKey);
|
|
97
98
|
}
|
|
@@ -105,7 +106,7 @@ export class EncryptionManager {
|
|
|
105
106
|
// Derive key using PBKDF2
|
|
106
107
|
const key = await crypto.subtle.deriveKey({
|
|
107
108
|
name: 'PBKDF2',
|
|
108
|
-
salt:
|
|
109
|
+
salt: saltBuffer,
|
|
109
110
|
iterations: iterations,
|
|
110
111
|
hash: 'SHA-256',
|
|
111
112
|
}, keyMaterial, {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/observer/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../observer.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Observer - Watch for storage changes
|
|
3
|
+
*/
|
|
4
|
+
import type { ObserverCallback, StorageEvent } from '@/types';
|
|
5
|
+
export declare class StorageObserver {
|
|
6
|
+
private observers;
|
|
7
|
+
/**
|
|
8
|
+
* Subscribe to storage events
|
|
9
|
+
*/
|
|
10
|
+
subscribe(callback: ObserverCallback): () => void;
|
|
11
|
+
/**
|
|
12
|
+
* Emit a storage event
|
|
13
|
+
*/
|
|
14
|
+
emit(event: StorageEvent): void;
|
|
15
|
+
/**
|
|
16
|
+
* Clear all observers
|
|
17
|
+
*/
|
|
18
|
+
clear(): void;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=observer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../../src/features/observer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE9D,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAoC;IAErD;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,IAAI;IAKjD;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAU/B;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Observer - Watch for storage changes
|
|
3
|
+
*/
|
|
4
|
+
export class StorageObserver {
|
|
5
|
+
observers = new Set();
|
|
6
|
+
/**
|
|
7
|
+
* Subscribe to storage events
|
|
8
|
+
*/
|
|
9
|
+
subscribe(callback) {
|
|
10
|
+
this.observers.add(callback);
|
|
11
|
+
return () => this.observers.delete(callback);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Emit a storage event
|
|
15
|
+
*/
|
|
16
|
+
emit(event) {
|
|
17
|
+
this.observers.forEach((callback) => {
|
|
18
|
+
try {
|
|
19
|
+
callback(event);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.error('Error in storage observer:', error);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Clear all observers
|
|
28
|
+
*/
|
|
29
|
+
clear() {
|
|
30
|
+
this.observers.clear();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/query/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../query.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/features/query.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,SAAS,CAAC;AAE9D;;GAEG;AACH,qBAAa,WAAW;IACtB;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO;IAwB3D;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;IACH,OAAO,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/features/query.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,SAAS,CAAC;AAE9D;;GAEG;AACH,qBAAa,WAAW;IACtB;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO;IAwB3D;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;IACH,OAAO,CAAC,eAAe;IA2DvB;;OAEG;IACH,OAAO,CAAC,aAAa;IAkBrB;;OAEG;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACH,OAAO,CAAC,MAAM;IA+Bd;;OAEG;IACH,OAAO,CAAC,OAAO;IAyBf;;OAEG;IACH,OAAO,CAAC,YAAY;IAOpB;;OAEG;IACH,OAAO,CAAC,OAAO;IASf;;OAEG;IACH,OAAO,CAAC,WAAW;IAcnB;;OAEG;IACH,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;IAoBxD;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA2B5E;;OAEG;IACH,OAAO,CAAC,cAAc;IAetB;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAc1B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,WAAW,CAE/C"}
|
package/dist/features/query.js
CHANGED
|
@@ -63,7 +63,14 @@ export class QueryEngine {
|
|
|
63
63
|
case '$lte':
|
|
64
64
|
return this.compare(value, operand) <= 0;
|
|
65
65
|
case '$in':
|
|
66
|
-
|
|
66
|
+
if (!Array.isArray(operand))
|
|
67
|
+
return false;
|
|
68
|
+
// If value is an array, check if any operand value is in the array
|
|
69
|
+
if (Array.isArray(value)) {
|
|
70
|
+
return operand.some((v) => value.some((item) => this.equals(item, v)));
|
|
71
|
+
}
|
|
72
|
+
// Otherwise check if value equals any operand value
|
|
73
|
+
return operand.some((v) => this.equals(value, v));
|
|
67
74
|
case '$nin':
|
|
68
75
|
return Array.isArray(operand) && !operand.some((v) => this.equals(value, v));
|
|
69
76
|
case '$regex':
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/sync/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../sync.js";
|
package/dist/features/sync.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/ttl/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../ttl.js";
|
package/dist/features/ttl.js
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Strata } from './core/Strata';
|
|
2
|
+
/**
|
|
3
|
+
* Firebase sync configuration
|
|
4
|
+
*/
|
|
5
|
+
export interface FirebaseSyncConfig {
|
|
6
|
+
apiKey: string;
|
|
7
|
+
authDomain: string;
|
|
8
|
+
projectId: string;
|
|
9
|
+
storageBucket?: string;
|
|
10
|
+
messagingSenderId?: string;
|
|
11
|
+
appId: string;
|
|
12
|
+
realtimeDatabase?: boolean;
|
|
13
|
+
firestore?: boolean;
|
|
14
|
+
collectionName?: string;
|
|
15
|
+
syncInterval?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Enable Firebase sync for Strata Storage
|
|
19
|
+
* This dynamically imports Firebase SDK only when needed
|
|
20
|
+
*/
|
|
21
|
+
export declare function enableFirebaseSync(storage: Strata, config: FirebaseSyncConfig): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Check if Firebase is available in the environment
|
|
24
|
+
*/
|
|
25
|
+
export declare function isFirebaseAvailable(): Promise<boolean>;
|
|
26
|
+
//# sourceMappingURL=firebase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase.d.ts","sourceRoot":"","sources":["../src/firebase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C;;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,CA2If;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO5D"}
|
package/dist/firebase.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enable Firebase sync for Strata Storage
|
|
3
|
+
* This dynamically imports Firebase SDK only when needed
|
|
4
|
+
*/
|
|
5
|
+
export async function enableFirebaseSync(storage, config) {
|
|
6
|
+
// Dynamically import Firebase only when this function is called
|
|
7
|
+
try {
|
|
8
|
+
const { initializeApp, getApps } = await import('firebase/app');
|
|
9
|
+
// Initialize Firebase if not already initialized
|
|
10
|
+
if (!getApps().length) {
|
|
11
|
+
initializeApp({
|
|
12
|
+
apiKey: config.apiKey,
|
|
13
|
+
authDomain: config.authDomain,
|
|
14
|
+
projectId: config.projectId,
|
|
15
|
+
storageBucket: config.storageBucket,
|
|
16
|
+
messagingSenderId: config.messagingSenderId,
|
|
17
|
+
appId: config.appId,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
if (config.firestore) {
|
|
21
|
+
const { getFirestore, doc, setDoc, getDoc, deleteDoc } = await import('firebase/firestore');
|
|
22
|
+
const db = getFirestore();
|
|
23
|
+
const collectionName = config.collectionName || 'strata-storage';
|
|
24
|
+
// Create custom adapter for Firestore
|
|
25
|
+
const firestoreAdapter = {
|
|
26
|
+
name: 'firestore',
|
|
27
|
+
capabilities: {
|
|
28
|
+
persistent: true,
|
|
29
|
+
synchronous: false,
|
|
30
|
+
observable: true,
|
|
31
|
+
transactional: false,
|
|
32
|
+
queryable: true,
|
|
33
|
+
maxSize: -1,
|
|
34
|
+
binary: true,
|
|
35
|
+
encrypted: false,
|
|
36
|
+
crossTab: true,
|
|
37
|
+
},
|
|
38
|
+
async get(key) {
|
|
39
|
+
const docRef = doc(db, collectionName, key);
|
|
40
|
+
const docSnap = await getDoc(docRef);
|
|
41
|
+
return docSnap.exists() ? docSnap.data() : null;
|
|
42
|
+
},
|
|
43
|
+
async set(key, value) {
|
|
44
|
+
const docRef = doc(db, collectionName, key);
|
|
45
|
+
await setDoc(docRef, { value, timestamp: Date.now() });
|
|
46
|
+
},
|
|
47
|
+
async remove(key) {
|
|
48
|
+
const docRef = doc(db, collectionName, key);
|
|
49
|
+
await deleteDoc(docRef);
|
|
50
|
+
},
|
|
51
|
+
async has(key) {
|
|
52
|
+
const docRef = doc(db, collectionName, key);
|
|
53
|
+
const docSnap = await getDoc(docRef);
|
|
54
|
+
return docSnap.exists();
|
|
55
|
+
},
|
|
56
|
+
async clear() {
|
|
57
|
+
// Firestore doesn't have a direct clear method
|
|
58
|
+
console.warn('Clear operation not supported for Firestore adapter');
|
|
59
|
+
},
|
|
60
|
+
async keys() {
|
|
61
|
+
// Would need to implement with queries
|
|
62
|
+
return [];
|
|
63
|
+
},
|
|
64
|
+
async size() {
|
|
65
|
+
return { total: 0, count: 0 };
|
|
66
|
+
},
|
|
67
|
+
async initialize() {
|
|
68
|
+
// Already initialized
|
|
69
|
+
},
|
|
70
|
+
async isAvailable() {
|
|
71
|
+
return true;
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
// Register the Firestore adapter
|
|
75
|
+
storage.registerAdapter(firestoreAdapter);
|
|
76
|
+
}
|
|
77
|
+
if (config.realtimeDatabase) {
|
|
78
|
+
const { getDatabase, ref, set, get, remove } = await import('firebase/database');
|
|
79
|
+
const db = getDatabase();
|
|
80
|
+
// Create custom adapter for Realtime Database
|
|
81
|
+
const realtimeAdapter = {
|
|
82
|
+
name: 'realtime',
|
|
83
|
+
capabilities: {
|
|
84
|
+
persistent: true,
|
|
85
|
+
synchronous: false,
|
|
86
|
+
observable: true,
|
|
87
|
+
transactional: false,
|
|
88
|
+
queryable: false,
|
|
89
|
+
maxSize: -1,
|
|
90
|
+
binary: false,
|
|
91
|
+
encrypted: false,
|
|
92
|
+
crossTab: true,
|
|
93
|
+
},
|
|
94
|
+
async get(key) {
|
|
95
|
+
const snapshot = await get(ref(db, `strata-storage/${key}`));
|
|
96
|
+
return snapshot.exists() ? snapshot.val() : null;
|
|
97
|
+
},
|
|
98
|
+
async set(key, value) {
|
|
99
|
+
await set(ref(db, `strata-storage/${key}`), value);
|
|
100
|
+
},
|
|
101
|
+
async remove(key) {
|
|
102
|
+
await remove(ref(db, `strata-storage/${key}`));
|
|
103
|
+
},
|
|
104
|
+
async has(key) {
|
|
105
|
+
const snapshot = await get(ref(db, `strata-storage/${key}`));
|
|
106
|
+
return snapshot.exists();
|
|
107
|
+
},
|
|
108
|
+
async clear() {
|
|
109
|
+
await remove(ref(db, 'strata-storage'));
|
|
110
|
+
},
|
|
111
|
+
async keys() {
|
|
112
|
+
const snapshot = await get(ref(db, 'strata-storage'));
|
|
113
|
+
return snapshot.exists() ? Object.keys(snapshot.val()) : [];
|
|
114
|
+
},
|
|
115
|
+
async size() {
|
|
116
|
+
const snapshot = await get(ref(db, 'strata-storage'));
|
|
117
|
+
const count = snapshot.exists() ? Object.keys(snapshot.val()).length : 0;
|
|
118
|
+
return { total: count * 100, count }; // Rough estimate
|
|
119
|
+
},
|
|
120
|
+
async initialize() {
|
|
121
|
+
// Already initialized
|
|
122
|
+
},
|
|
123
|
+
async isAvailable() {
|
|
124
|
+
return true;
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
// Register the Realtime Database adapter
|
|
128
|
+
storage.registerAdapter(realtimeAdapter);
|
|
129
|
+
}
|
|
130
|
+
console.log('Firebase sync enabled successfully');
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
throw new Error(`Failed to enable Firebase sync: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check if Firebase is available in the environment
|
|
138
|
+
*/
|
|
139
|
+
export async function isFirebaseAvailable() {
|
|
140
|
+
try {
|
|
141
|
+
await import('firebase/app');
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|