strata-storage 2.6.1 → 2.7.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/AI-INTEGRATION-GUIDE.md +88 -10
- package/README.md +42 -64
- package/android/AGENTS.md +18 -3
- package/android/CLAUDE.md +36 -3
- package/android/build.gradle +5 -1
- package/android/src/main/java/com/strata/storage/EncryptedStorage.java +31 -18
- package/android/src/main/java/com/strata/storage/FilesystemStorage.java +62 -10
- package/android/src/main/java/com/strata/storage/SQLiteStorage.java +65 -13
- package/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +63 -51
- package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +80 -11
- package/dist/README.md +42 -64
- package/dist/adapters/capacitor/FilesystemAdapter.d.ts +2 -2
- package/dist/adapters/capacitor/FilesystemAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/FilesystemAdapter.js +6 -2
- package/dist/adapters/capacitor/PreferencesAdapter.d.ts +2 -2
- package/dist/adapters/capacitor/PreferencesAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/PreferencesAdapter.js +6 -2
- package/dist/adapters/capacitor/SecureAdapter.d.ts +3 -3
- package/dist/adapters/capacitor/SecureAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/SecureAdapter.js +6 -2
- package/dist/adapters/capacitor/SqliteAdapter.d.ts +24 -3
- package/dist/adapters/capacitor/SqliteAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/SqliteAdapter.js +105 -23
- package/dist/adapters/capacitor/index.d.ts +4 -4
- package/dist/adapters/web/CacheAdapter.d.ts +2 -2
- package/dist/adapters/web/CookieAdapter.d.ts +2 -2
- package/dist/adapters/web/IndexedDBAdapter.d.ts +10 -3
- package/dist/adapters/web/IndexedDBAdapter.d.ts.map +1 -1
- package/dist/adapters/web/IndexedDBAdapter.js +14 -3
- package/dist/adapters/web/LocalStorageAdapter.d.ts +2 -2
- package/dist/adapters/web/MemoryAdapter.d.ts +2 -2
- package/dist/adapters/web/SessionStorageAdapter.d.ts +10 -10
- package/dist/adapters/web/SessionStorageAdapter.d.ts.map +1 -1
- package/dist/adapters/web/SessionStorageAdapter.js +3 -2
- package/dist/adapters/web/URLAdapter.d.ts +2 -2
- package/dist/adapters/web/index.d.ts +7 -7
- package/dist/capacitor.d.ts +6 -6
- package/dist/capacitor.d.ts.map +1 -1
- package/dist/capacitor.js +5 -4
- package/dist/core/AdapterRegistry.d.ts +1 -1
- package/dist/core/BaseAdapter.d.ts +21 -5
- package/dist/core/BaseAdapter.d.ts.map +1 -1
- package/dist/core/BaseAdapter.js +29 -1
- package/dist/core/Strata.d.ts +41 -7
- package/dist/core/Strata.d.ts.map +1 -1
- package/dist/core/Strata.js +476 -118
- package/dist/features/compression/index.d.ts +1 -1
- package/dist/features/compression.d.ts +5 -1
- package/dist/features/compression.d.ts.map +1 -1
- package/dist/features/encryption/index.d.ts +1 -1
- package/dist/features/encryption.d.ts +55 -2
- package/dist/features/encryption.d.ts.map +1 -1
- package/dist/features/encryption.js +139 -26
- package/dist/features/migration.d.ts +1 -1
- package/dist/features/observer/index.d.ts +1 -1
- package/dist/features/observer.d.ts +1 -1
- package/dist/features/query/index.d.ts +1 -1
- package/dist/features/query.d.ts +1 -1
- package/dist/features/query.d.ts.map +1 -1
- package/dist/features/query.js +3 -1
- package/dist/features/sync/index.d.ts +1 -1
- package/dist/features/sync.d.ts +19 -3
- package/dist/features/sync.d.ts.map +1 -1
- package/dist/features/sync.js +57 -9
- package/dist/features/ttl/index.d.ts +1 -1
- package/dist/features/ttl.d.ts +2 -2
- package/dist/firebase.d.ts +1 -1
- package/dist/firebase.d.ts.map +1 -1
- package/dist/firebase.js +34 -9
- package/dist/index.d.ts +24 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/integrations/angular/index.d.ts +2 -2
- package/dist/integrations/angular/index.d.ts.map +1 -1
- package/dist/integrations/angular/index.js +7 -8
- package/dist/integrations/react/index.d.ts +3 -3
- package/dist/integrations/react/index.d.ts.map +1 -1
- package/dist/integrations/react/index.js +16 -4
- package/dist/integrations/vue/index.d.ts +2 -2
- package/dist/integrations/vue/index.d.ts.map +1 -1
- package/dist/integrations/vue/index.js +5 -2
- package/dist/package.json +11 -2
- package/dist/plugin/definitions.d.ts +29 -3
- package/dist/plugin/definitions.d.ts.map +1 -1
- package/dist/plugin/index.d.ts +2 -2
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +3 -0
- package/dist/plugin/web.d.ts +11 -2
- package/dist/plugin/web.d.ts.map +1 -1
- package/dist/plugin/web.js +23 -4
- package/dist/types/index.d.ts +50 -20
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -10
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +7 -0
- package/ios/AGENTS.md +14 -3
- package/ios/CLAUDE.md +25 -3
- package/ios/Plugin/FilesystemStorage.swift +19 -0
- package/ios/Plugin/SQLiteStorage.swift +59 -9
- package/ios/Plugin/StrataStoragePlugin.m +1 -0
- package/ios/Plugin/StrataStoragePlugin.swift +87 -34
- package/ios/Plugin/UserDefaultsStorage.swift +47 -46
- package/package.json +27 -24
- package/scripts/build.js +16 -14
- package/scripts/cli.js +1 -1
- package/scripts/configure.js +2 -2
- package/scripts/postinstall.js +3 -2
- package/dist/android/AGENTS.md +0 -51
- package/dist/android/CLAUDE.md +0 -89
- package/dist/android/build.gradle +0 -58
- package/dist/android/proguard-rules.pro +0 -11
- package/dist/android/settings.gradle +0 -2
- package/dist/android/src/main/AndroidManifest.xml +0 -2
- package/dist/android/src/main/java/com/strata/storage/EncryptedStorage.java +0 -218
- package/dist/android/src/main/java/com/strata/storage/FilesystemStorage.java +0 -287
- package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +0 -371
- package/dist/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +0 -209
- package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +0 -616
- package/dist/core/StorageStrategy.d.ts +0 -55
- package/dist/core/StorageStrategy.d.ts.map +0 -1
- package/dist/core/StorageStrategy.js +0 -200
- package/dist/ios/AGENTS.md +0 -48
- package/dist/ios/CLAUDE.md +0 -84
- package/dist/ios/Plugin/FilesystemStorage.swift +0 -218
- package/dist/ios/Plugin/KeychainStorage.swift +0 -233
- package/dist/ios/Plugin/SQLiteStorage.swift +0 -426
- package/dist/ios/Plugin/StrataStoragePlugin.m +0 -23
- package/dist/ios/Plugin/StrataStoragePlugin.swift +0 -411
- package/dist/ios/Plugin/UserDefaultsStorage.swift +0 -87
package/dist/README.md
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
[](https://www.npmjs.com/package/strata-storage)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
[](https://www.typescriptlang.org/)
|
|
10
|
-
[](https://
|
|
10
|
+
[](https://stratastorage.aoneahsan.com)
|
|
11
11
|
|
|
12
|
-
- **Version:** `2.
|
|
12
|
+
- **Version:** `2.7.0`
|
|
13
13
|
- **License:** Apache-2.0
|
|
14
14
|
- **Node.js:** `>= 24.13.0`
|
|
15
15
|
- **Module format:** ESM only
|
|
@@ -71,7 +71,7 @@ await storage.set('token', '...', { encrypt: true });
|
|
|
71
71
|
|
|
72
72
|
## Provider-Free Usage
|
|
73
73
|
|
|
74
|
-
The recommended pattern across all frameworks: create one instance and bind to it. No Provider, plugin, or module is required. The Provider-based styles remain available and are documented in [
|
|
74
|
+
The recommended pattern across all frameworks: create one instance and bind to it. No Provider, plugin, or module is required. The Provider-based styles remain available and are documented in the [examples](https://stratastorage-docs.aoneahsan.com/examples).
|
|
75
75
|
|
|
76
76
|
### Vanilla JavaScript / TypeScript
|
|
77
77
|
|
|
@@ -396,14 +396,14 @@ Register the native adapters you need when running under Capacitor. All four are
|
|
|
396
396
|
import { defineStorage } from 'strata-storage';
|
|
397
397
|
import {
|
|
398
398
|
PreferencesAdapter,
|
|
399
|
-
|
|
399
|
+
SecureAdapter,
|
|
400
400
|
SqliteAdapter,
|
|
401
401
|
FilesystemAdapter,
|
|
402
402
|
} from 'strata-storage/capacitor';
|
|
403
403
|
|
|
404
404
|
const storage = defineStorage();
|
|
405
405
|
storage.registerAdapter(new PreferencesAdapter()); // UserDefaults / SharedPreferences
|
|
406
|
-
storage.registerAdapter(new
|
|
406
|
+
storage.registerAdapter(new SecureAdapter()); // Keychain / EncryptedSharedPreferences
|
|
407
407
|
storage.registerAdapter(new SqliteAdapter()); // native SQLite
|
|
408
408
|
storage.registerAdapter(new FilesystemAdapter()); // native files
|
|
409
409
|
|
|
@@ -432,7 +432,7 @@ audit.registerAdapter(new SqliteAdapter({ database: 'audit', table: 'rows' }));
|
|
|
432
432
|
|
|
433
433
|
`await storage.size(true)` aggregates `{ total, count, byStorage, ... }`; native SQLite and filesystem additionally report a per-column byte breakdown (keys / values / metadata) when called on those adapters directly.
|
|
434
434
|
|
|
435
|
-
> **Honest note:** the native iOS/Android adapters depend on your downstream Capacitor project setup and platform configuration, and native behavior cannot be exercised
|
|
435
|
+
> **Honest note:** the native iOS/Android adapters depend on your downstream Capacitor project setup and platform configuration, and native behavior cannot be exercised in a web/Node environment. Follow the [device-verification guide](https://stratastorage-docs.aoneahsan.com/guides/platforms/device-verification) to verify on a real iOS and Android device after integrating.
|
|
436
436
|
|
|
437
437
|
### Firebase (optional cloud sync)
|
|
438
438
|
|
|
@@ -441,7 +441,12 @@ import { defineStorage } from 'strata-storage';
|
|
|
441
441
|
import { enableFirebaseSync } from 'strata-storage/firebase';
|
|
442
442
|
|
|
443
443
|
const storage = defineStorage();
|
|
444
|
-
await enableFirebaseSync(storage, {
|
|
444
|
+
await enableFirebaseSync(storage, {
|
|
445
|
+
apiKey: '…', authDomain: '…', projectId: '…', appId: '…',
|
|
446
|
+
firestore: true,
|
|
447
|
+
});
|
|
448
|
+
// 'firestore' / 'realtime' are runtime adapter names (not in the StorageType
|
|
449
|
+
// union, so strict TS may need a cast on the options object).
|
|
445
450
|
await storage.set('data', value, { storage: 'firestore' });
|
|
446
451
|
```
|
|
447
452
|
|
|
@@ -473,59 +478,24 @@ Optional peer dependencies (install only the ones you use): `react >= 19.2.3`, `
|
|
|
473
478
|
|
|
474
479
|
## Documentation
|
|
475
480
|
|
|
481
|
+
📚 **Full documentation: [stratastorage-docs.aoneahsan.com](https://stratastorage-docs.aoneahsan.com)**
|
|
482
|
+
🤖 **For AI agents: [stratastorage-docs.aoneahsan.com/ai](https://stratastorage-docs.aoneahsan.com/ai)** (plus [`/llms.txt`](https://stratastorage-docs.aoneahsan.com/llms.txt) and [`/llms-full.txt`](https://stratastorage-docs.aoneahsan.com/llms-full.txt))
|
|
483
|
+
|
|
476
484
|
### Getting Started
|
|
477
|
-
- [Installation](
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
- [API Reference](./docs/api/README.md) — complete API
|
|
483
|
-
- [Core API (`Strata`)](./docs/api/core/strata.md) — the main class
|
|
484
|
-
- [Type Definitions](./docs/api/core/types.md) — TypeScript types
|
|
485
|
-
- [Error Handling](./docs/api/core/errors.md) — error classes
|
|
486
|
-
|
|
487
|
-
### Storage Adapters
|
|
488
|
-
- [Web Adapters](./docs/api/adapters/README.md#web-adapters)
|
|
489
|
-
- [localStorage](./docs/api/adapters/web/localstorage.md)
|
|
490
|
-
- [sessionStorage](./docs/api/adapters/web/sessionstorage.md)
|
|
491
|
-
- [IndexedDB](./docs/api/adapters/web/indexeddb.md)
|
|
492
|
-
- [Cookies](./docs/api/adapters/web/cookies.md)
|
|
493
|
-
- [Cache API](./docs/api/adapters/web/cache.md)
|
|
494
|
-
- [Memory](./docs/api/adapters/web/memory.md)
|
|
495
|
-
- [URL](./docs/api/adapters/web/url.md)
|
|
496
|
-
- [Capacitor Adapters](./docs/api/adapters/README.md#capacitor-adapters)
|
|
497
|
-
- [Preferences](./docs/api/adapters/capacitor/preferences.md)
|
|
498
|
-
- [Secure Storage](./docs/api/adapters/capacitor/secure.md)
|
|
499
|
-
- [SQLite](./docs/api/adapters/capacitor/sqlite.md)
|
|
500
|
-
- [Filesystem](./docs/api/adapters/capacitor/filesystem.md)
|
|
485
|
+
- [Installation](https://stratastorage-docs.aoneahsan.com/installation) · [Quick Start](https://stratastorage-docs.aoneahsan.com/quick-start) · [Configuration](https://stratastorage-docs.aoneahsan.com/configuration)
|
|
486
|
+
|
|
487
|
+
### API
|
|
488
|
+
- [API Reference](https://stratastorage-docs.aoneahsan.com/api) · [Core (`Strata`)](https://stratastorage-docs.aoneahsan.com/api/core/strata) · [Types](https://stratastorage-docs.aoneahsan.com/api/core/types) · [Errors](https://stratastorage-docs.aoneahsan.com/api/core/errors)
|
|
489
|
+
- [All adapters](https://stratastorage-docs.aoneahsan.com/api/adapters) — web (localStorage, IndexedDB, cookies, Cache, URL, …) + Capacitor (Preferences, Secure, SQLite, Filesystem) + remote (Firebase)
|
|
501
490
|
|
|
502
491
|
### Features
|
|
503
|
-
- [Encryption](
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
- [
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
- [
|
|
510
|
-
|
|
511
|
-
### Platform Guides
|
|
512
|
-
- [Web](./docs/guides/platforms/web.md)
|
|
513
|
-
- [iOS](./docs/guides/platforms/ios.md)
|
|
514
|
-
- [Android](./docs/guides/platforms/android.md)
|
|
515
|
-
- [Capacitor](./docs/guides/platforms/capacitor.md)
|
|
516
|
-
|
|
517
|
-
### Examples
|
|
518
|
-
- [Basic Usage](./docs/examples/basic-usage.md)
|
|
519
|
-
- [React Integration](./docs/examples/frameworks/react.md)
|
|
520
|
-
- [Vue Integration](./docs/examples/frameworks/vue.md)
|
|
521
|
-
- [Angular Integration](./docs/examples/frameworks/angular.md)
|
|
522
|
-
- [All Examples](./docs/examples/README.md)
|
|
523
|
-
|
|
524
|
-
### Reference
|
|
525
|
-
- [Changelog](./docs/reference/changelog.md)
|
|
526
|
-
- [FAQ](./docs/reference/faq.md)
|
|
527
|
-
- [Troubleshooting](./docs/reference/troubleshooting.md)
|
|
528
|
-
- [Migration Guide](./docs/MIGRATION.md)
|
|
492
|
+
- [Encryption](https://stratastorage-docs.aoneahsan.com/guides/features/encryption) · [Compression](https://stratastorage-docs.aoneahsan.com/guides/features/compression) · [TTL](https://stratastorage-docs.aoneahsan.com/api/features/ttl) · [Sync](https://stratastorage-docs.aoneahsan.com/guides/features/sync) · [Queries](https://stratastorage-docs.aoneahsan.com/guides/features/queries) · [Migrations](https://stratastorage-docs.aoneahsan.com/guides/features/migrations) · [Recovery & Integrity](https://stratastorage-docs.aoneahsan.com/api/features/recovery)
|
|
493
|
+
|
|
494
|
+
### Platforms
|
|
495
|
+
- [Web](https://stratastorage-docs.aoneahsan.com/guides/platforms/web) · [iOS](https://stratastorage-docs.aoneahsan.com/guides/platforms/ios) · [Android](https://stratastorage-docs.aoneahsan.com/guides/platforms/android) · [Capacitor](https://stratastorage-docs.aoneahsan.com/guides/platforms/capacitor) · [Firebase](https://stratastorage-docs.aoneahsan.com/guides/platforms/firebase)
|
|
496
|
+
|
|
497
|
+
### Examples & Reference
|
|
498
|
+
- [Examples](https://stratastorage-docs.aoneahsan.com/examples) · [Changelog](https://stratastorage-docs.aoneahsan.com/reference/changelog) · [FAQ](https://stratastorage-docs.aoneahsan.com/reference/faq) · [Troubleshooting](https://stratastorage-docs.aoneahsan.com/reference/troubleshooting) · [Migration](https://stratastorage-docs.aoneahsan.com/migration)
|
|
529
499
|
|
|
530
500
|
## Contributing
|
|
531
501
|
|
|
@@ -547,17 +517,25 @@ Apache License 2.0 — see [LICENSE](LICENSE). Free for commercial use, modifica
|
|
|
547
517
|
|
|
548
518
|
## Links
|
|
549
519
|
|
|
550
|
-
- **NPM Package:**
|
|
551
|
-
- **
|
|
552
|
-
- **
|
|
553
|
-
- **Documentation:** [github.com/aoneahsan/strata-storage/tree/main/docs](https://github.com/aoneahsan/strata-storage/tree/main/docs)
|
|
520
|
+
- **NPM Package:** https://www.npmjs.com/package/strata-storage
|
|
521
|
+
- **Documentation:** https://stratastorage-docs.aoneahsan.com
|
|
522
|
+
- **Website:** https://stratastorage.aoneahsan.com
|
|
554
523
|
|
|
555
524
|
## Support
|
|
556
525
|
|
|
557
|
-
1. Check the [FAQ](
|
|
558
|
-
2.
|
|
559
|
-
3.
|
|
526
|
+
1. Check the [FAQ](https://stratastorage-docs.aoneahsan.com/reference/faq) and [Troubleshooting](https://stratastorage-docs.aoneahsan.com/reference/troubleshooting)
|
|
527
|
+
2. Browse the [documentation](https://stratastorage-docs.aoneahsan.com)
|
|
528
|
+
3. [Contact us / report an issue](https://stratastorage.aoneahsan.com/contact)
|
|
560
529
|
|
|
561
530
|
---
|
|
562
531
|
|
|
563
532
|
Made by [Ahsan Mahmood](https://aoneahsan.com). **One API. Every Storage. Everywhere.**
|
|
533
|
+
|
|
534
|
+
<!-- project-links:start -->
|
|
535
|
+
## Links
|
|
536
|
+
|
|
537
|
+
- Live: https://www.npmjs.com/package/strata-storage
|
|
538
|
+
- NPM: https://www.npmjs.com/package/strata-storage
|
|
539
|
+
|
|
540
|
+
_URL source of truth: `01-code/projects/project-live-urls.json` (auto-generated — do not hand-edit between these markers)._
|
|
541
|
+
<!-- project-links:end -->
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Filesystem Adapter - Native file system storage
|
|
3
3
|
* Direct file access on iOS and Android
|
|
4
4
|
*/
|
|
5
|
-
import { BaseAdapter } from
|
|
6
|
-
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo } from
|
|
5
|
+
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
|
+
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo } from "../../types/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* Native filesystem adapter using Capacitor plugin
|
|
9
9
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilesystemAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/capacitor/FilesystemAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,QAAQ,EACT,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAgB;IAC1C,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAWrC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAwBpE;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"FilesystemAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/capacitor/FilesystemAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,QAAQ,EACT,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAgB;IAC1C,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAWrC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAwBpE;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1E;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBxC;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlD;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAwBxD;;OAEG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;CAYlD"}
|
|
@@ -71,7 +71,9 @@ export class FilesystemAdapter extends BaseAdapter {
|
|
|
71
71
|
* Set a value in filesystem
|
|
72
72
|
*/
|
|
73
73
|
async set(key, value) {
|
|
74
|
-
|
|
74
|
+
// Only pay for a read-before-write (a native bridge round-trip) when a
|
|
75
|
+
// subscriber actually needs the previous value for the change event.
|
|
76
|
+
const oldValue = this.hasChangeListeners() ? await this.get(key) : null;
|
|
75
77
|
try {
|
|
76
78
|
await StrataStorage.set({
|
|
77
79
|
key,
|
|
@@ -88,7 +90,9 @@ export class FilesystemAdapter extends BaseAdapter {
|
|
|
88
90
|
* Remove a value from filesystem
|
|
89
91
|
*/
|
|
90
92
|
async remove(key) {
|
|
91
|
-
|
|
93
|
+
// Only pay for a read-before-write (a native bridge round-trip) when a
|
|
94
|
+
// subscriber actually needs the previous value for the change event.
|
|
95
|
+
const oldValue = this.hasChangeListeners() ? await this.get(key) : null;
|
|
92
96
|
try {
|
|
93
97
|
await StrataStorage.remove({
|
|
94
98
|
key,
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Preferences Adapter - Native preferences storage
|
|
3
3
|
* iOS: UserDefaults, Android: SharedPreferences
|
|
4
4
|
*/
|
|
5
|
-
import { BaseAdapter } from
|
|
6
|
-
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo } from
|
|
5
|
+
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
|
+
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo } from "../../types/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* Native preferences adapter using Capacitor plugin
|
|
9
9
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PreferencesAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/capacitor/PreferencesAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,QAAQ,EACT,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,WAAW;IACjD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAiB;IAC3C,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAWrC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAwBpE;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"PreferencesAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/capacitor/PreferencesAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,QAAQ,EACT,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,WAAW;IACjD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAiB;IAC3C,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAWrC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAwBpE;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1E;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBxC;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlD;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAwBxD;;OAEG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;CAYlD"}
|
|
@@ -71,7 +71,9 @@ export class PreferencesAdapter extends BaseAdapter {
|
|
|
71
71
|
* Set a value in preferences
|
|
72
72
|
*/
|
|
73
73
|
async set(key, value) {
|
|
74
|
-
|
|
74
|
+
// Only pay for a read-before-write (a native bridge round-trip) when a
|
|
75
|
+
// subscriber actually needs the previous value for the change event.
|
|
76
|
+
const oldValue = this.hasChangeListeners() ? await this.get(key) : null;
|
|
75
77
|
try {
|
|
76
78
|
await StrataStorage.set({
|
|
77
79
|
key,
|
|
@@ -88,7 +90,9 @@ export class PreferencesAdapter extends BaseAdapter {
|
|
|
88
90
|
* Remove a value from preferences
|
|
89
91
|
*/
|
|
90
92
|
async remove(key) {
|
|
91
|
-
|
|
93
|
+
// Only pay for a read-before-write (a native bridge round-trip) when a
|
|
94
|
+
// subscriber actually needs the previous value for the change event.
|
|
95
|
+
const oldValue = this.hasChangeListeners() ? await this.get(key) : null;
|
|
92
96
|
try {
|
|
93
97
|
await StrataStorage.remove({
|
|
94
98
|
key,
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Secure Adapter - Native secure storage
|
|
3
3
|
* iOS: Keychain, Android: EncryptedSharedPreferences
|
|
4
4
|
*/
|
|
5
|
-
import { BaseAdapter } from
|
|
6
|
-
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo } from
|
|
5
|
+
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
|
+
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo } from "../../types/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* Native secure storage adapter using Capacitor plugin
|
|
9
9
|
*/
|
|
@@ -48,7 +48,7 @@ export declare class SecureAdapter extends BaseAdapter {
|
|
|
48
48
|
setKeychainItem(key: string, value: string, options?: {
|
|
49
49
|
service?: string;
|
|
50
50
|
accessGroup?: string;
|
|
51
|
-
accessible?: import(
|
|
51
|
+
accessible?: import("../../plugin/definitions.js").KeychainAccessible;
|
|
52
52
|
}): Promise<void>;
|
|
53
53
|
/**
|
|
54
54
|
* iOS-specific: Get from Keychain
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecureAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/capacitor/SecureAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,QAAQ,EACT,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAY;IACtC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAWrC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAwBpE;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"SecureAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/capacitor/SecureAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,QAAQ,EACT,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAY;IACtC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAWrC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAwBpE;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1E;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBxC;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlD;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAwBxD;;OAEG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAajD;;OAEG;IACG,eAAe,CACnB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,OAAO,sBAAsB,EAAE,kBAAkB,CAAC;KAChE,GACA,OAAO,CAAC,IAAI,CAAC;IAYhB;;OAEG;IACG,eAAe,CACnB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GACA,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAazB;;OAEG;IACG,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY3F;;OAEG;IACG,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAY/E"}
|
|
@@ -71,7 +71,9 @@ export class SecureAdapter extends BaseAdapter {
|
|
|
71
71
|
* Set a value in secure storage
|
|
72
72
|
*/
|
|
73
73
|
async set(key, value) {
|
|
74
|
-
|
|
74
|
+
// Only pay for a read-before-write (a native bridge round-trip) when a
|
|
75
|
+
// subscriber actually needs the previous value for the change event.
|
|
76
|
+
const oldValue = this.hasChangeListeners() ? await this.get(key) : null;
|
|
75
77
|
try {
|
|
76
78
|
await StrataStorage.set({
|
|
77
79
|
key,
|
|
@@ -88,7 +90,9 @@ export class SecureAdapter extends BaseAdapter {
|
|
|
88
90
|
* Remove a value from secure storage
|
|
89
91
|
*/
|
|
90
92
|
async remove(key) {
|
|
91
|
-
|
|
93
|
+
// Only pay for a read-before-write (a native bridge round-trip) when a
|
|
94
|
+
// subscriber actually needs the previous value for the change event.
|
|
95
|
+
const oldValue = this.hasChangeListeners() ? await this.get(key) : null;
|
|
92
96
|
try {
|
|
93
97
|
await StrataStorage.remove({
|
|
94
98
|
key,
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* SQLite Adapter - Native SQLite database storage
|
|
3
3
|
* Available on iOS and Android
|
|
4
4
|
*/
|
|
5
|
-
import { BaseAdapter } from
|
|
6
|
-
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo, QueryCondition, Transaction } from
|
|
5
|
+
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
|
+
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo, QueryCondition, Transaction } from "../../types/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* Configuration options for SQLite adapter
|
|
9
9
|
*/
|
|
@@ -61,7 +61,28 @@ export declare class SqliteAdapter extends BaseAdapter {
|
|
|
61
61
|
*/
|
|
62
62
|
size(detailed?: boolean): Promise<SizeInfo>;
|
|
63
63
|
/**
|
|
64
|
-
*
|
|
64
|
+
* Reclaim expired rows in a single native round-trip and return the count.
|
|
65
|
+
*
|
|
66
|
+
* Because `keys()` and `query()` now exclude expired rows in SQL (there is no
|
|
67
|
+
* lazy per-key deletion on read anymore), this is what physically deletes
|
|
68
|
+
* them — driven by both the automatic TTL tick and `Strata.cleanupExpired()`.
|
|
69
|
+
*
|
|
70
|
+
* If the native bulk delete is present but fails at runtime, we log and return
|
|
71
|
+
* 0 (reads stay correct — expired rows are filtered — and the next tick
|
|
72
|
+
* retries); we deliberately do NOT fall back to the base per-key sweep, which
|
|
73
|
+
* cannot see expired rows on a build whose `keys()` already filters them. The
|
|
74
|
+
* base sweep is used only when no native bulk delete exists at all (an older
|
|
75
|
+
* native build whose `keys()` still surfaces expired rows).
|
|
76
|
+
*/
|
|
77
|
+
cleanupExpired(): Promise<number>;
|
|
78
|
+
/**
|
|
79
|
+
* Begin a transaction.
|
|
80
|
+
*
|
|
81
|
+
* NOTE: this is a best-effort batch, not an atomic native SQLite transaction.
|
|
82
|
+
* Operations are queued and executed sequentially on commit(); there is no
|
|
83
|
+
* native BEGIN/COMMIT/ROLLBACK across the connection, so a failure midway
|
|
84
|
+
* cannot roll back already-applied writes. `capabilities.transactional` is
|
|
85
|
+
* therefore reported as `false`.
|
|
65
86
|
*/
|
|
66
87
|
transaction(): Promise<Transaction>;
|
|
67
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqliteAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/capacitor/SqliteAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,WAAW,EACZ,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"SqliteAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/capacitor/SqliteAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,WAAW,EACZ,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAyBD;;GAEG;AACH,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAY;IACtC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAcxC;IAEF,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;gBAEV,MAAM,GAAE,YAAiB;IAQrC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAWrC;;OAEG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAatD;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IA0BpE;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB1E;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBxC;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBlD;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAmBxD;;OAEG;IACG,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IA0C9F;;OAEG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAejD;;;;;;;;;;;;;OAaG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAiBvC;;;;;;;;OAQG;IACG,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC;CAG1C"}
|
|
@@ -7,6 +7,25 @@ import { StrataStorage } from "../../plugin/index.js";
|
|
|
7
7
|
import { StorageError, TransactionError } from "../../utils/errors.js";
|
|
8
8
|
import { isCapacitor } from "../../utils/index.js";
|
|
9
9
|
import { logger } from "../../utils/logger.js";
|
|
10
|
+
/**
|
|
11
|
+
* Strict SQL-identifier allow-list for the `database` (file stem) and `table`
|
|
12
|
+
* names. These two cannot be bound as parameters, so they are the only place a
|
|
13
|
+
* SQL injection could occur; everything else (keys, values) is bound.
|
|
14
|
+
*/
|
|
15
|
+
const SQLITE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
16
|
+
/**
|
|
17
|
+
* Reject — loudly — any `database`/`table` that is not a strict SQL identifier,
|
|
18
|
+
* instead of silently stripping illegal characters (which could let two
|
|
19
|
+
* distinct logical stores collapse into one physical table). This is the
|
|
20
|
+
* authoritative guard: hostile identifiers never reach the native layer, which
|
|
21
|
+
* also applies the same allow-list as defense-in-depth.
|
|
22
|
+
*/
|
|
23
|
+
function assertValidIdentifier(kind, value) {
|
|
24
|
+
if (!SQLITE_IDENTIFIER.test(value)) {
|
|
25
|
+
throw new StorageError(`Invalid SQLite ${kind} name "${value}": must match ${SQLITE_IDENTIFIER.source} ` +
|
|
26
|
+
'(letters, digits and underscore only, not starting with a digit).');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
10
29
|
/**
|
|
11
30
|
* Native SQLite adapter using Capacitor plugin
|
|
12
31
|
*/
|
|
@@ -16,7 +35,11 @@ export class SqliteAdapter extends BaseAdapter {
|
|
|
16
35
|
persistent: true,
|
|
17
36
|
synchronous: false,
|
|
18
37
|
observable: false,
|
|
19
|
-
|
|
38
|
+
// `transaction()` queues operations and runs them sequentially on commit();
|
|
39
|
+
// it is NOT a single atomic native SQLite transaction (no BEGIN/COMMIT/
|
|
40
|
+
// ROLLBACK across the connection), so we report this honestly. See the
|
|
41
|
+
// SqliteTransaction note below.
|
|
42
|
+
transactional: false,
|
|
20
43
|
queryable: true,
|
|
21
44
|
maxSize: -1, // Limited by device storage
|
|
22
45
|
binary: true,
|
|
@@ -29,6 +52,8 @@ export class SqliteAdapter extends BaseAdapter {
|
|
|
29
52
|
super();
|
|
30
53
|
this.database = config.database || 'strata_storage';
|
|
31
54
|
this.table = config.table || 'storage';
|
|
55
|
+
assertValidIdentifier('database', this.database);
|
|
56
|
+
assertValidIdentifier('table', this.table);
|
|
32
57
|
}
|
|
33
58
|
/**
|
|
34
59
|
* Check if SQLite is available
|
|
@@ -48,10 +73,14 @@ export class SqliteAdapter extends BaseAdapter {
|
|
|
48
73
|
* Initialize the adapter
|
|
49
74
|
*/
|
|
50
75
|
async initialize(config) {
|
|
51
|
-
if (config?.database)
|
|
76
|
+
if (config?.database) {
|
|
77
|
+
assertValidIdentifier('database', config.database);
|
|
52
78
|
this.database = config.database;
|
|
53
|
-
|
|
79
|
+
}
|
|
80
|
+
if (config?.table) {
|
|
81
|
+
assertValidIdentifier('table', config.table);
|
|
54
82
|
this.table = config.table;
|
|
83
|
+
}
|
|
55
84
|
this.startTTLCleanup();
|
|
56
85
|
}
|
|
57
86
|
/**
|
|
@@ -84,7 +113,9 @@ export class SqliteAdapter extends BaseAdapter {
|
|
|
84
113
|
* Set a value in SQLite
|
|
85
114
|
*/
|
|
86
115
|
async set(key, value) {
|
|
87
|
-
|
|
116
|
+
// Only pay for a read-before-write (a native bridge round-trip) when a
|
|
117
|
+
// subscriber actually needs the previous value for the change event.
|
|
118
|
+
const oldValue = this.hasChangeListeners() ? await this.get(key) : null;
|
|
88
119
|
try {
|
|
89
120
|
await StrataStorage.set({
|
|
90
121
|
key,
|
|
@@ -103,7 +134,9 @@ export class SqliteAdapter extends BaseAdapter {
|
|
|
103
134
|
* Remove a value from SQLite
|
|
104
135
|
*/
|
|
105
136
|
async remove(key) {
|
|
106
|
-
|
|
137
|
+
// Only pay for a read-before-write (a native bridge round-trip) when a
|
|
138
|
+
// subscriber actually needs the previous value for the change event.
|
|
139
|
+
const oldValue = this.hasChangeListeners() ? await this.get(key) : null;
|
|
107
140
|
try {
|
|
108
141
|
await StrataStorage.remove({
|
|
109
142
|
key,
|
|
@@ -151,16 +184,11 @@ export class SqliteAdapter extends BaseAdapter {
|
|
|
151
184
|
table: this.table,
|
|
152
185
|
pattern: pattern instanceof RegExp ? pattern.source : pattern,
|
|
153
186
|
});
|
|
154
|
-
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (value) {
|
|
160
|
-
validKeys.push(key);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return this.filterKeys(validKeys, pattern);
|
|
187
|
+
// The native layer excludes expired rows in SQL (a single round-trip),
|
|
188
|
+
// so there is no per-key `get()` loop here. We still run `filterKeys`
|
|
189
|
+
// for the adapter's exact prefix/glob/RegExp semantics — native `LIKE`
|
|
190
|
+
// is only a coarse pre-filter.
|
|
191
|
+
return this.filterKeys(result.keys, pattern);
|
|
164
192
|
}
|
|
165
193
|
catch (error) {
|
|
166
194
|
throw new StorageError(`Failed to get keys from SQLite: ${error}`);
|
|
@@ -180,12 +208,27 @@ export class SqliteAdapter extends BaseAdapter {
|
|
|
180
208
|
table: this.table,
|
|
181
209
|
condition,
|
|
182
210
|
});
|
|
183
|
-
//
|
|
211
|
+
// The native layer returns the full non-expired wrapper for every
|
|
212
|
+
// candidate row in ONE round-trip, so the real query filter runs here in
|
|
213
|
+
// JS (mirroring BaseAdapter.query) without an N+1 `get()` per key.
|
|
214
|
+
const isStorageQuery = this.isStorageMetadataQuery(condition);
|
|
215
|
+
const normalizedCondition = isStorageQuery
|
|
216
|
+
? condition
|
|
217
|
+
: this.normalizeValueQueryCondition(condition);
|
|
184
218
|
const validResults = [];
|
|
185
219
|
for (const item of result.results) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
220
|
+
// Use the batched wrapper; fall back to a per-key `get()` only for
|
|
221
|
+
// older native builds that surface keys alone (item.value undefined).
|
|
222
|
+
const stored = item.value ?? (await this.get(item.key));
|
|
223
|
+
if (!stored)
|
|
224
|
+
continue; // missing
|
|
225
|
+
if (this.isExpired(stored))
|
|
226
|
+
continue; // defensive: native already filters
|
|
227
|
+
const matches = isStorageQuery
|
|
228
|
+
? this.queryEngine.matches(stored, normalizedCondition)
|
|
229
|
+
: this.queryEngine.matches(stored.value, normalizedCondition);
|
|
230
|
+
if (matches) {
|
|
231
|
+
validResults.push({ key: item.key, value: stored.value });
|
|
189
232
|
}
|
|
190
233
|
}
|
|
191
234
|
return validResults;
|
|
@@ -212,16 +255,55 @@ export class SqliteAdapter extends BaseAdapter {
|
|
|
212
255
|
}
|
|
213
256
|
}
|
|
214
257
|
/**
|
|
215
|
-
*
|
|
258
|
+
* Reclaim expired rows in a single native round-trip and return the count.
|
|
259
|
+
*
|
|
260
|
+
* Because `keys()` and `query()` now exclude expired rows in SQL (there is no
|
|
261
|
+
* lazy per-key deletion on read anymore), this is what physically deletes
|
|
262
|
+
* them — driven by both the automatic TTL tick and `Strata.cleanupExpired()`.
|
|
263
|
+
*
|
|
264
|
+
* If the native bulk delete is present but fails at runtime, we log and return
|
|
265
|
+
* 0 (reads stay correct — expired rows are filtered — and the next tick
|
|
266
|
+
* retries); we deliberately do NOT fall back to the base per-key sweep, which
|
|
267
|
+
* cannot see expired rows on a build whose `keys()` already filters them. The
|
|
268
|
+
* base sweep is used only when no native bulk delete exists at all (an older
|
|
269
|
+
* native build whose `keys()` still surfaces expired rows).
|
|
270
|
+
*/
|
|
271
|
+
async cleanupExpired() {
|
|
272
|
+
if (StrataStorage.cleanupExpired) {
|
|
273
|
+
try {
|
|
274
|
+
const result = await StrataStorage.cleanupExpired({
|
|
275
|
+
storage: 'sqlite',
|
|
276
|
+
database: this.database,
|
|
277
|
+
table: this.table,
|
|
278
|
+
});
|
|
279
|
+
return result.removed;
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
logger.error('Native SQLite cleanupExpired failed; will retry next tick:', error);
|
|
283
|
+
return 0;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return super.cleanupExpired();
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Begin a transaction.
|
|
290
|
+
*
|
|
291
|
+
* NOTE: this is a best-effort batch, not an atomic native SQLite transaction.
|
|
292
|
+
* Operations are queued and executed sequentially on commit(); there is no
|
|
293
|
+
* native BEGIN/COMMIT/ROLLBACK across the connection, so a failure midway
|
|
294
|
+
* cannot roll back already-applied writes. `capabilities.transactional` is
|
|
295
|
+
* therefore reported as `false`.
|
|
216
296
|
*/
|
|
217
297
|
async transaction() {
|
|
218
|
-
// Transactions are handled natively
|
|
219
|
-
// For now, return a simple implementation
|
|
220
298
|
return new SqliteTransaction(this);
|
|
221
299
|
}
|
|
222
300
|
}
|
|
223
301
|
/**
|
|
224
|
-
* SQLite transaction implementation
|
|
302
|
+
* SQLite transaction implementation.
|
|
303
|
+
*
|
|
304
|
+
* Best-effort sequential batch (see SqliteAdapter.transaction): rollback() only
|
|
305
|
+
* discards queued-but-not-yet-committed operations; it cannot undo writes that
|
|
306
|
+
* commit() has already applied. Do not rely on this for atomic multi-key writes.
|
|
225
307
|
*/
|
|
226
308
|
class SqliteTransaction {
|
|
227
309
|
adapter;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Capacitor Native Storage Adapters
|
|
3
3
|
* Export all native platform storage implementations
|
|
4
4
|
*/
|
|
5
|
-
export { PreferencesAdapter } from
|
|
6
|
-
export { SqliteAdapter } from
|
|
7
|
-
export { SecureAdapter } from
|
|
8
|
-
export { FilesystemAdapter } from
|
|
5
|
+
export { PreferencesAdapter } from "./PreferencesAdapter.js";
|
|
6
|
+
export { SqliteAdapter } from "./SqliteAdapter.js";
|
|
7
|
+
export { SecureAdapter } from "./SecureAdapter.js";
|
|
8
|
+
export { FilesystemAdapter } from "./FilesystemAdapter.js";
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Cache Adapter - Service Worker Cache API implementation
|
|
3
3
|
* Provides network-aware storage for offline support
|
|
4
4
|
*/
|
|
5
|
-
import { BaseAdapter } from
|
|
6
|
-
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo, QueryCondition } from
|
|
5
|
+
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
|
+
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo, QueryCondition } from "../../types/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* Cache API adapter for Service Worker environments
|
|
9
9
|
*/
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Cookie Adapter - Browser cookie implementation
|
|
3
3
|
* Provides limited storage with 4KB per cookie limit
|
|
4
4
|
*/
|
|
5
|
-
import { BaseAdapter } from
|
|
6
|
-
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo } from
|
|
5
|
+
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
|
+
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo } from "../../types/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* Cookie options.
|
|
9
9
|
*
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* IndexedDB Adapter - Browser IndexedDB implementation
|
|
3
3
|
* Provides large-scale persistent storage with advanced features
|
|
4
4
|
*/
|
|
5
|
-
import { BaseAdapter } from
|
|
6
|
-
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo, QueryCondition, Transaction } from
|
|
5
|
+
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
|
+
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo, QueryCondition, Transaction } from "../../types/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* Browser IndexedDB adapter
|
|
9
9
|
*/
|
|
@@ -63,7 +63,14 @@ export declare class IndexedDBAdapter extends BaseAdapter {
|
|
|
63
63
|
*/
|
|
64
64
|
size(detailed?: boolean): Promise<SizeInfo>;
|
|
65
65
|
/**
|
|
66
|
-
* Begin a transaction
|
|
66
|
+
* Begin a transaction.
|
|
67
|
+
*
|
|
68
|
+
* IMPORTANT — IndexedDB transactions auto-commit as soon as control returns to
|
|
69
|
+
* the event loop with no pending requests. Issue all `set`/`remove`/`get`
|
|
70
|
+
* calls back-to-back and `await` them together (e.g. `Promise.all([...])`)
|
|
71
|
+
* BEFORE awaiting anything unrelated. Awaiting a non-IndexedDB promise between
|
|
72
|
+
* operations lets the transaction close, after which further calls fail with
|
|
73
|
+
* `TransactionInactiveError`. For most multi-write needs prefer `setMany()`.
|
|
67
74
|
*/
|
|
68
75
|
transaction(): Promise<Transaction>;
|
|
69
76
|
/**
|