strata-storage 2.6.0 → 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 +97 -10
- package/README.md +70 -70
- 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 +70 -70
- 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 +29 -26
- 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
|
|
|
@@ -390,15 +390,22 @@ const active = await storage.query({
|
|
|
390
390
|
|
|
391
391
|
### iOS and Android (via Capacitor)
|
|
392
392
|
|
|
393
|
-
Register native adapters
|
|
393
|
+
Register the native adapters you need when running under Capacitor. All four are zero-runtime-dependency: SQLite is hand-rolled (no plugin dependency) and filesystem uses the platform's native `FileManager` / `java.io.File`.
|
|
394
394
|
|
|
395
395
|
```typescript
|
|
396
396
|
import { defineStorage } from 'strata-storage';
|
|
397
|
-
import {
|
|
397
|
+
import {
|
|
398
|
+
PreferencesAdapter,
|
|
399
|
+
SecureAdapter,
|
|
400
|
+
SqliteAdapter,
|
|
401
|
+
FilesystemAdapter,
|
|
402
|
+
} from 'strata-storage/capacitor';
|
|
398
403
|
|
|
399
404
|
const storage = defineStorage();
|
|
400
|
-
storage.registerAdapter(new PreferencesAdapter());
|
|
401
|
-
storage.registerAdapter(new
|
|
405
|
+
storage.registerAdapter(new PreferencesAdapter()); // UserDefaults / SharedPreferences
|
|
406
|
+
storage.registerAdapter(new SecureAdapter()); // Keychain / EncryptedSharedPreferences
|
|
407
|
+
storage.registerAdapter(new SqliteAdapter()); // native SQLite
|
|
408
|
+
storage.registerAdapter(new FilesystemAdapter()); // native files
|
|
402
409
|
|
|
403
410
|
await storage.set('secret', token, { storage: 'secure' });
|
|
404
411
|
```
|
|
@@ -407,10 +414,25 @@ await storage.set('secret', token, { storage: 'secure' });
|
|
|
407
414
|
|---------|-------------|-----------------|
|
|
408
415
|
| `preferences` | UserDefaults | SharedPreferences |
|
|
409
416
|
| `secure` | Keychain | EncryptedSharedPreferences |
|
|
410
|
-
| `sqlite` | SQLite | SQLite |
|
|
411
|
-
| `filesystem` | FileManager |
|
|
417
|
+
| `sqlite` | SQLite (multi-store) | SQLite (multi-store) |
|
|
418
|
+
| `filesystem` | FileManager | java.io.File |
|
|
412
419
|
|
|
413
|
-
|
|
420
|
+
**SQLite multi-store** (2.6.0+): each `SqliteAdapter` instance binds to a `(database, table)` pair, so distinct logical stores map to distinct physical SQLite files / tables and cannot collide.
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
import { SqliteAdapter } from 'strata-storage/capacitor';
|
|
424
|
+
|
|
425
|
+
const analytics = defineStorage();
|
|
426
|
+
analytics.registerAdapter(new SqliteAdapter({ database: 'analytics', table: 'events' }));
|
|
427
|
+
|
|
428
|
+
const audit = defineStorage();
|
|
429
|
+
audit.registerAdapter(new SqliteAdapter({ database: 'audit', table: 'rows' }));
|
|
430
|
+
// → separate physical .db files; writes to `analytics` can never bleed into `audit`.
|
|
431
|
+
```
|
|
432
|
+
|
|
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
|
+
|
|
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.
|
|
414
436
|
|
|
415
437
|
### Firebase (optional cloud sync)
|
|
416
438
|
|
|
@@ -419,7 +441,12 @@ import { defineStorage } from 'strata-storage';
|
|
|
419
441
|
import { enableFirebaseSync } from 'strata-storage/firebase';
|
|
420
442
|
|
|
421
443
|
const storage = defineStorage();
|
|
422
|
-
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).
|
|
423
450
|
await storage.set('data', value, { storage: 'firestore' });
|
|
424
451
|
```
|
|
425
452
|
|
|
@@ -436,8 +463,8 @@ await storage.set('data', value, { storage: 'firestore' });
|
|
|
436
463
|
| `url` | Web | ✅ | async only | Shareable UI state, length-limited |
|
|
437
464
|
| `preferences` | Mobile | ❌ | async only | UserDefaults / SharedPreferences |
|
|
438
465
|
| `secure` | Mobile | ❌ | async only | Keychain / EncryptedSharedPreferences |
|
|
439
|
-
| `sqlite` | Mobile | ❌ | async only | Native SQLite |
|
|
440
|
-
| `filesystem` | Mobile | ❌ | async only | Native files |
|
|
466
|
+
| `sqlite` | Mobile | ❌ | async only | Native SQLite — multi-store via `(database, table)` (2.6.0+) |
|
|
467
|
+
| `filesystem` | Mobile | ❌ | async only | Native files — file-per-key with atomic writes (2.6.0+) |
|
|
441
468
|
|
|
442
469
|
"async only" means encryption and compression require the `await storage.set(...)` path — the synchronous API cannot encrypt or compress.
|
|
443
470
|
|
|
@@ -451,59 +478,24 @@ Optional peer dependencies (install only the ones you use): `react >= 19.2.3`, `
|
|
|
451
478
|
|
|
452
479
|
## Documentation
|
|
453
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
|
+
|
|
454
484
|
### Getting Started
|
|
455
|
-
- [Installation](
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
- [API Reference](./docs/api/README.md) — complete API
|
|
461
|
-
- [Core API (`Strata`)](./docs/api/core/strata.md) — the main class
|
|
462
|
-
- [Type Definitions](./docs/api/core/types.md) — TypeScript types
|
|
463
|
-
- [Error Handling](./docs/api/core/errors.md) — error classes
|
|
464
|
-
|
|
465
|
-
### Storage Adapters
|
|
466
|
-
- [Web Adapters](./docs/api/adapters/README.md#web-adapters)
|
|
467
|
-
- [localStorage](./docs/api/adapters/web/localstorage.md)
|
|
468
|
-
- [sessionStorage](./docs/api/adapters/web/sessionstorage.md)
|
|
469
|
-
- [IndexedDB](./docs/api/adapters/web/indexeddb.md)
|
|
470
|
-
- [Cookies](./docs/api/adapters/web/cookies.md)
|
|
471
|
-
- [Cache API](./docs/api/adapters/web/cache.md)
|
|
472
|
-
- [Memory](./docs/api/adapters/web/memory.md)
|
|
473
|
-
- [URL](./docs/api/adapters/web/url.md)
|
|
474
|
-
- [Capacitor Adapters](./docs/api/adapters/README.md#capacitor-adapters)
|
|
475
|
-
- [Preferences](./docs/api/adapters/capacitor/preferences.md)
|
|
476
|
-
- [Secure Storage](./docs/api/adapters/capacitor/secure.md)
|
|
477
|
-
- [SQLite](./docs/api/adapters/capacitor/sqlite.md)
|
|
478
|
-
- [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)
|
|
479
490
|
|
|
480
491
|
### Features
|
|
481
|
-
- [Encryption](
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
- [
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
- [
|
|
488
|
-
|
|
489
|
-
### Platform Guides
|
|
490
|
-
- [Web](./docs/guides/platforms/web.md)
|
|
491
|
-
- [iOS](./docs/guides/platforms/ios.md)
|
|
492
|
-
- [Android](./docs/guides/platforms/android.md)
|
|
493
|
-
- [Capacitor](./docs/guides/platforms/capacitor.md)
|
|
494
|
-
|
|
495
|
-
### Examples
|
|
496
|
-
- [Basic Usage](./docs/examples/basic-usage.md)
|
|
497
|
-
- [React Integration](./docs/examples/frameworks/react.md)
|
|
498
|
-
- [Vue Integration](./docs/examples/frameworks/vue.md)
|
|
499
|
-
- [Angular Integration](./docs/examples/frameworks/angular.md)
|
|
500
|
-
- [All Examples](./docs/examples/README.md)
|
|
501
|
-
|
|
502
|
-
### Reference
|
|
503
|
-
- [Changelog](./docs/reference/changelog.md)
|
|
504
|
-
- [FAQ](./docs/reference/faq.md)
|
|
505
|
-
- [Troubleshooting](./docs/reference/troubleshooting.md)
|
|
506
|
-
- [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)
|
|
507
499
|
|
|
508
500
|
## Contributing
|
|
509
501
|
|
|
@@ -525,17 +517,25 @@ Apache License 2.0 — see [LICENSE](LICENSE). Free for commercial use, modifica
|
|
|
525
517
|
|
|
526
518
|
## Links
|
|
527
519
|
|
|
528
|
-
- **NPM Package:**
|
|
529
|
-
- **
|
|
530
|
-
- **
|
|
531
|
-
- **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
|
|
532
523
|
|
|
533
524
|
## Support
|
|
534
525
|
|
|
535
|
-
1. Check the [FAQ](
|
|
536
|
-
2.
|
|
537
|
-
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)
|
|
538
529
|
|
|
539
530
|
---
|
|
540
531
|
|
|
541
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
|
*/
|