strata-storage 2.4.3 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/AI-INTEGRATION-GUIDE.md +115 -261
  2. package/README.md +426 -182
  3. package/android/AGENTS.md +51 -0
  4. package/android/CLAUDE.md +89 -0
  5. package/android/build.gradle +1 -1
  6. package/android/src/main/java/com/strata/storage/FilesystemStorage.java +287 -0
  7. package/android/src/main/java/com/strata/storage/SQLiteStorage.java +260 -203
  8. package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +357 -69
  9. package/dist/README.md +426 -182
  10. package/dist/adapters/capacitor/FilesystemAdapter.d.ts.map +1 -1
  11. package/dist/adapters/capacitor/FilesystemAdapter.js +2 -1
  12. package/dist/adapters/capacitor/PreferencesAdapter.d.ts.map +1 -1
  13. package/dist/adapters/capacitor/PreferencesAdapter.js +2 -1
  14. package/dist/adapters/capacitor/SecureAdapter.d.ts.map +1 -1
  15. package/dist/adapters/capacitor/SecureAdapter.js +2 -1
  16. package/dist/adapters/capacitor/SqliteAdapter.d.ts.map +1 -1
  17. package/dist/adapters/capacitor/SqliteAdapter.js +2 -1
  18. package/dist/adapters/web/CacheAdapter.d.ts.map +1 -1
  19. package/dist/adapters/web/CacheAdapter.js +11 -3
  20. package/dist/adapters/web/CookieAdapter.d.ts +37 -1
  21. package/dist/adapters/web/CookieAdapter.d.ts.map +1 -1
  22. package/dist/adapters/web/CookieAdapter.js +89 -9
  23. package/dist/adapters/web/IndexedDBAdapter.d.ts.map +1 -1
  24. package/dist/adapters/web/IndexedDBAdapter.js +10 -2
  25. package/dist/adapters/web/LocalStorageAdapter.d.ts +31 -0
  26. package/dist/adapters/web/LocalStorageAdapter.d.ts.map +1 -1
  27. package/dist/adapters/web/LocalStorageAdapter.js +92 -19
  28. package/dist/adapters/web/MemoryAdapter.d.ts +24 -0
  29. package/dist/adapters/web/MemoryAdapter.d.ts.map +1 -1
  30. package/dist/adapters/web/MemoryAdapter.js +69 -18
  31. package/dist/adapters/web/SessionStorageAdapter.d.ts +24 -0
  32. package/dist/adapters/web/SessionStorageAdapter.d.ts.map +1 -1
  33. package/dist/adapters/web/SessionStorageAdapter.js +71 -9
  34. package/dist/adapters/web/URLAdapter.d.ts +59 -0
  35. package/dist/adapters/web/URLAdapter.d.ts.map +1 -0
  36. package/dist/adapters/web/URLAdapter.js +234 -0
  37. package/dist/adapters/web/index.d.ts +1 -0
  38. package/dist/adapters/web/index.d.ts.map +1 -1
  39. package/dist/adapters/web/index.js +1 -0
  40. package/dist/android/AGENTS.md +51 -0
  41. package/dist/android/CLAUDE.md +89 -0
  42. package/dist/android/build.gradle +1 -1
  43. package/dist/android/src/main/java/com/strata/storage/FilesystemStorage.java +287 -0
  44. package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +260 -203
  45. package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +357 -69
  46. package/dist/capacitor.d.ts.map +1 -1
  47. package/dist/capacitor.js +2 -1
  48. package/dist/core/BaseAdapter.d.ts +8 -0
  49. package/dist/core/BaseAdapter.d.ts.map +1 -1
  50. package/dist/core/BaseAdapter.js +34 -14
  51. package/dist/core/Strata.d.ts +56 -2
  52. package/dist/core/Strata.d.ts.map +1 -1
  53. package/dist/core/Strata.js +501 -53
  54. package/dist/features/encryption.d.ts.map +1 -1
  55. package/dist/features/encryption.js +3 -2
  56. package/dist/features/integrity.d.ts +16 -0
  57. package/dist/features/integrity.d.ts.map +1 -0
  58. package/dist/features/integrity.js +28 -0
  59. package/dist/features/observer.d.ts.map +1 -1
  60. package/dist/features/observer.js +2 -1
  61. package/dist/features/query.d.ts +7 -1
  62. package/dist/features/query.d.ts.map +1 -1
  63. package/dist/features/query.js +9 -2
  64. package/dist/features/sync.d.ts.map +1 -1
  65. package/dist/features/sync.js +4 -3
  66. package/dist/index.d.ts +35 -2
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +55 -30
  69. package/dist/integrations/angular/index.d.ts +158 -0
  70. package/dist/integrations/angular/index.d.ts.map +1 -0
  71. package/dist/integrations/angular/index.js +395 -0
  72. package/dist/integrations/index.d.ts +15 -0
  73. package/dist/integrations/index.d.ts.map +1 -0
  74. package/dist/integrations/index.js +18 -0
  75. package/dist/integrations/react/index.d.ts +75 -0
  76. package/dist/integrations/react/index.d.ts.map +1 -0
  77. package/dist/integrations/react/index.js +191 -0
  78. package/dist/integrations/vue/index.d.ts +103 -0
  79. package/dist/integrations/vue/index.d.ts.map +1 -0
  80. package/dist/integrations/vue/index.js +274 -0
  81. package/dist/ios/AGENTS.md +48 -0
  82. package/dist/ios/CLAUDE.md +84 -0
  83. package/dist/ios/Plugin/FilesystemStorage.swift +218 -0
  84. package/dist/ios/Plugin/KeychainStorage.swift +139 -50
  85. package/dist/ios/Plugin/SQLiteStorage.swift +279 -147
  86. package/dist/ios/Plugin/StrataStoragePlugin.m +23 -0
  87. package/dist/ios/Plugin/StrataStoragePlugin.swift +272 -65
  88. package/dist/package.json +21 -5
  89. package/dist/plugin/index.d.ts.map +1 -1
  90. package/dist/plugin/index.js +2 -1
  91. package/dist/types/index.d.ts +58 -9
  92. package/dist/types/index.d.ts.map +1 -1
  93. package/dist/types/index.js +0 -13
  94. package/dist/utils/errors.d.ts +7 -0
  95. package/dist/utils/errors.d.ts.map +1 -1
  96. package/dist/utils/errors.js +15 -3
  97. package/dist/utils/index.d.ts +63 -5
  98. package/dist/utils/index.d.ts.map +1 -1
  99. package/dist/utils/index.js +109 -16
  100. package/dist/utils/logger.d.ts +31 -0
  101. package/dist/utils/logger.d.ts.map +1 -0
  102. package/dist/utils/logger.js +63 -0
  103. package/ios/AGENTS.md +48 -0
  104. package/ios/CLAUDE.md +84 -0
  105. package/ios/Plugin/FilesystemStorage.swift +218 -0
  106. package/ios/Plugin/KeychainStorage.swift +139 -50
  107. package/ios/Plugin/SQLiteStorage.swift +279 -147
  108. package/ios/Plugin/StrataStoragePlugin.m +23 -0
  109. package/ios/Plugin/StrataStoragePlugin.swift +272 -65
  110. package/package.json +31 -20
  111. package/scripts/build.js +16 -5
  112. package/scripts/configure.js +2 -6
  113. package/scripts/postinstall.js +2 -2
  114. package/Readme.md +0 -271
package/README.md CHANGED
@@ -1,271 +1,517 @@
1
1
  # Strata Storage
2
2
 
3
- - **[AI Integration Guide](./AI-INTEGRATION-GUIDE.md)** - Quick reference for AI development agents (Claude, Cursor, Copilot)
3
+ > Zero-dependency universal storage for the web, iOS, and Android. One API for `localStorage`, IndexedDB, cookies, the URL, native Keychain/Keystore, SQLite, and more — with optional React, Vue, Angular, Capacitor, and Firebase surfaces.
4
4
 
5
- > Zero-dependency universal storage plugin providing a unified API for all storage operations across web, Android, and iOS platforms.
5
+ - **[AI Integration Guide](./AI-INTEGRATION-GUIDE.md)** quick reference for AI development agents (Claude Code, Cursor, Copilot).
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/strata-storage.svg)](https://www.npmjs.com/package/strata-storage)
8
8
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
9
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.9+-blue.svg)](https://www.typescriptlang.org/)
9
+ [![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue.svg)](https://www.typescriptlang.org/)
10
10
  [![Platform](https://img.shields.io/badge/platform-Web%20%7C%20iOS%20%7C%20Android-lightgrey.svg)](https://github.com/aoneahsan/strata-storage)
11
11
 
12
- ## Features
12
+ - **Version:** `2.5.0`
13
+ - **License:** Apache-2.0
14
+ - **Node.js:** `>= 24.13.0`
15
+ - **Module format:** ESM only
13
16
 
14
- - **🚀 Zero Dependencies** - No external runtime dependencies, pure TypeScript implementation
15
- - **🌐 Universal API** - Single consistent API across web, iOS, and Android
16
- - **🔒 Built-in Encryption** - Secure data storage using native crypto APIs
17
- - **📦 Compression** - Automatic data compression for large objects
18
- - **⏱️ TTL Support** - Automatic expiration with time-to-live
19
- - **🔄 Cross-Tab Sync** - Real-time synchronization across browser tabs
20
- - **🎯 Advanced Queries** - Tag-based querying and filtering
21
- - **📱 Mobile Ready** - Native iOS and Android storage with Capacitor
22
- - **💾 Multiple Adapters** - localStorage, IndexedDB, SQLite, Keychain, and more
23
- - **🎨 Framework Integrations** - React hooks, Vue composables, Angular services
17
+ ## Why Strata Storage
24
18
 
25
- ## Installation
19
+ Every product re-solves the same storage problem: pick a backend per platform, learn its quirks, wrap it for your framework, and bolt on encryption, expiry, and cross-tab sync by hand. Strata Storage replaces that with one adapter-based API that runs everywhere and keeps the runtime package free of dependencies.
26
20
 
27
- ```bash
28
- npm install strata-storage
29
- ```
21
+ - **Zero runtime dependencies.** The core is pure TypeScript. React, Vue, Angular, and `@capacitor/core` are optional peer dependencies — install only what you use.
22
+ - **One API, every backend.** `get`/`set`/`remove`/`query`/`subscribe` behave the same whether the value lives in `localStorage`, IndexedDB, the URL, or the iOS Keychain.
23
+ - **Provider-free.** `defineStorage()` returns a ready-to-use instance you create once and import anywhere — no React context, Vue plugin, or Angular module required (the Provider/Plugin/Module styles still work if you prefer them).
24
+ - **Opt-in power features.** Encryption, compression, TTL, queries, cross-tab sync, integrity checksums, durable writes, mirroring, and snapshots are all off by default and added per call or per instance.
30
25
 
31
- Or using yarn:
26
+ ## Installation
32
27
 
33
28
  ```bash
34
29
  yarn add strata-storage
35
30
  ```
36
31
 
37
- Or using pnpm:
32
+ Framework adapters import from sub-paths; no extra install beyond the framework itself:
38
33
 
39
34
  ```bash
40
- pnpm add strata-storage
35
+ # React / Vue / Angular peers are optional — install the one you use
36
+ yarn add react # for strata-storage/react
37
+ yarn add vue # for strata-storage/vue
38
+ yarn add @angular/core @angular/forms # for strata-storage/angular
39
+ yarn add @capacitor/core # for strata-storage/capacitor
41
40
  ```
42
41
 
43
42
  ## Quick Start
44
43
 
45
- ### Basic Usage
44
+ The shortest path is the default `storage` instance. It registers the standard web adapters and initializes lazily on first use, so importing the package does no I/O.
46
45
 
47
46
  ```typescript
48
- import { Strata } from 'strata-storage';
49
-
50
- // Create and initialize storage
51
- const storage = new Strata();
52
- await storage.initialize();
53
-
54
- // Store data
55
- await storage.set('username', 'john_doe');
56
- await storage.set('user', {
57
- id: 123,
58
- name: 'John Doe',
59
- email: 'john@example.com'
47
+ import { storage } from 'strata-storage';
48
+
49
+ // No setup, no Provider, no initialize() call — works immediately.
50
+ await storage.set('user', { id: 123, name: 'John Doe' });
51
+ const user = await storage.get<{ id: number; name: string }>('user');
52
+
53
+ await storage.remove('user');
54
+ await storage.clear();
55
+ ```
56
+
57
+ Need your own configured instance? Use `defineStorage()` — it is the same factory the default instance is built from.
58
+
59
+ ```typescript
60
+ import { defineStorage } from 'strata-storage';
61
+
62
+ export const storage = defineStorage({
63
+ defaultStorages: ['indexedDB', 'localStorage'],
64
+ encryption: { enabled: true, password: process.env.STORAGE_KEY! },
60
65
  });
61
66
 
62
- // Retrieve data
63
- const username = await storage.get('username');
64
- const user = await storage.get('user');
67
+ await storage.set('token', '...', { encrypt: true });
68
+ ```
65
69
 
66
- // Remove data
67
- await storage.remove('username');
70
+ `defineStorage()` registers memory, `localStorage`, `sessionStorage`, IndexedDB, cookies, and the Cache API. Add the URL adapter or native adapters yourself when you need them (see below).
68
71
 
69
- // Clear all data
70
- await storage.clear();
72
+ ## Provider-Free Usage
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 [docs/examples/frameworks](./docs/examples/frameworks).
75
+
76
+ ### Vanilla JavaScript / TypeScript
77
+
78
+ ```typescript
79
+ import { defineStorage } from 'strata-storage';
80
+
81
+ export const storage = defineStorage();
82
+
83
+ await storage.set('theme', 'dark');
84
+ const theme = await storage.get<string>('theme');
85
+ ```
86
+
87
+ ### React
88
+
89
+ Bind the hooks to an instance once at module scope with `createStrataHooks`, then use them in any component — no `<StrataProvider>` needed.
90
+
91
+ ```tsx
92
+ // storage.ts
93
+ import { defineStorage } from 'strata-storage';
94
+ import { createStrataHooks } from 'strata-storage/react';
95
+
96
+ export const storage = defineStorage();
97
+ export const { useStorage, useStorageQuery, useStorageTTL } = createStrataHooks(storage);
98
+ ```
99
+
100
+ ```tsx
101
+ // Settings.tsx
102
+ import { useStorage } from './storage';
103
+
104
+ function Settings() {
105
+ // [value, setValue, loading]
106
+ const [theme, setTheme, loading] = useStorage<string>('theme', 'light');
107
+
108
+ if (loading) return <p>Loading…</p>;
109
+
110
+ return (
111
+ <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
112
+ Theme: {theme}
113
+ </button>
114
+ );
115
+ }
116
+ ```
117
+
118
+ Prefer context? `<StrataProvider>` still works and now accepts an `instance` prop so it can wrap an instance you created yourself:
119
+
120
+ ```tsx
121
+ import { StrataProvider, useStorage } from 'strata-storage/react';
122
+ import { storage } from './storage';
123
+
124
+ <StrataProvider instance={storage}>
125
+ <App />
126
+ </StrataProvider>;
71
127
  ```
72
128
 
73
- ### Advanced Features
129
+ ### Vue
74
130
 
75
- #### Encryption
131
+ `createStrataComposables` binds the composables to an instance. Each built-in composable also accepts an optional instance as its last argument, and the classic `StrataPlugin` still works.
76
132
 
77
133
  ```typescript
78
- const storage = new Strata({
79
- encryption: {
80
- enabled: true,
81
- password: 'your-secure-password'
82
- }
83
- });
134
+ // storage.ts
135
+ import { defineStorage } from 'strata-storage';
136
+ import { createStrataComposables } from 'strata-storage/vue';
137
+
138
+ export const storage = defineStorage();
139
+ export const { useStorage, useStorageQuery, useStorageTTL } = createStrataComposables(storage);
140
+ ```
84
141
 
85
- await storage.initialize();
86
- await storage.set('sensitiveData', { token: 'secret' });
142
+ ```vue
143
+ <script setup lang="ts">
144
+ import { useStorage } from './storage';
145
+
146
+ const { value: theme, update } = useStorage<string>('theme', 'light');
147
+ </script>
148
+
149
+ <template>
150
+ <button @click="update(theme === 'light' ? 'dark' : 'light')">Theme: {{ theme }}</button>
151
+ </template>
87
152
  ```
88
153
 
89
- #### Time-To-Live (TTL)
154
+ ### Angular
155
+
156
+ `provideStrata` accepts either a pre-created instance or a config object, and registers `StrataService` for injection. It works in `bootstrapApplication` (standalone) or a component's `providers`. The `STRATA_INSTANCE` token holds the instance; `StrataModule.forRoot(config)` remains for NgModule apps.
90
157
 
91
158
  ```typescript
92
- // Data expires in 1 hour
93
- await storage.set('sessionData', data, {
94
- ttl: 60 * 60 * 1000
159
+ // main.ts
160
+ import { bootstrapApplication } from '@angular/platform-browser';
161
+ import { defineStorage } from 'strata-storage';
162
+ import { provideStrata } from 'strata-storage/angular';
163
+ import { AppComponent } from './app/app.component';
164
+
165
+ const storage = defineStorage();
166
+
167
+ bootstrapApplication(AppComponent, {
168
+ providers: [provideStrata(storage)], // or provideStrata({ defaultStorages: ['indexedDB'] })
95
169
  });
96
170
  ```
97
171
 
98
- #### Compression
99
-
100
172
  ```typescript
101
- const storage = new Strata({
102
- compression: {
103
- enabled: true,
104
- threshold: 1024 // Compress data larger than 1KB
173
+ // any.component.ts
174
+ import { Component } from '@angular/core';
175
+ import { StrataService } from 'strata-storage/angular';
176
+
177
+ @Component({ /* ... */ })
178
+ export class AnyComponent {
179
+ constructor(private storage: StrataService) {}
180
+
181
+ save() {
182
+ // StrataService methods return RxJS Observables
183
+ this.storage.set('theme', 'dark').subscribe();
105
184
  }
106
- });
185
+ }
186
+ ```
187
+
188
+ ## Synchronous API
189
+
190
+ For UI code that must read or write without `await` — initial render, event handlers, synchronous state hydration — Strata exposes a synchronous API alongside the async one:
191
+
192
+ ```typescript
193
+ import { defineStorage } from 'strata-storage';
107
194
 
108
- await storage.initialize();
109
- await storage.set('largeData', bigObject);
195
+ const storage = defineStorage();
196
+
197
+ storage.setSync('lastTab', 'inbox');
198
+ const tab = storage.getSync<string>('lastTab'); // 'inbox'
199
+ storage.hasSync('lastTab'); // true
200
+ storage.keysSync(); // string[]
201
+ storage.removeSync('lastTab');
202
+ storage.clearSync();
110
203
  ```
111
204
 
112
- #### Cross-Tab Sync
205
+ ### Limitations (read these)
206
+
207
+ The sync API only works on adapters that are genuinely synchronous: **`memory`, `localStorage`, `sessionStorage`, `cookies`, and `url`**. It does not paper over async backends, and it cannot do work that is inherently asynchronous:
208
+
209
+ - Targeting an async-only adapter (`indexedDB`, `cache`, `sqlite`, `filesystem`, `secure`, `preferences`) throws a `StorageError` telling you to use the async API.
210
+ - `setSync` with `{ encrypt: true }` or `{ compress: true }` throws — Web Crypto and compression are async, so use `await storage.set(...)`.
211
+ - `getSync` on a value that was stored encrypted or compressed throws — read it with `await storage.get(...)`.
212
+
213
+ TTL, tags, and metadata work with the sync API; encryption and compression do not.
113
214
 
114
215
  ```typescript
115
- const storage = new Strata({
116
- sync: { enabled: true }
117
- });
216
+ // Pick a sync-capable backend explicitly when needed:
217
+ storage.setSync('filters', { status: 'open' }, { storage: 'localStorage', ttl: 60_000 });
218
+ ```
219
+
220
+ ## URL Adapter
221
+
222
+ The `URLAdapter` (storage type `'url'`) persists state in the page URL so it survives reloads and round-trips through shareable/bookmarkable links — filters, the active tab, pagination, and other small UI state. It is inherently synchronous and emits change events on `popstate`/`hashchange`, so back/forward navigation and manual URL edits notify subscribers.
223
+
224
+ ```typescript
225
+ import { defineStorage, URLAdapter } from 'strata-storage';
118
226
 
119
- await storage.initialize();
227
+ const storage = defineStorage();
228
+ storage.registerAdapter(new URLAdapter());
120
229
 
121
- // Subscribe to changes from other tabs
230
+ // Write to the URL (no await needed — URL access is synchronous)
231
+ storage.setSync('tab', 'pending', { storage: 'url' });
232
+ storage.setSync('page', 3, { storage: 'url' });
233
+
234
+ // Read it back (e.g. on reload)
235
+ const tab = storage.getSync<string>('tab', { storage: 'url' });
236
+
237
+ // React to back/forward navigation or manual edits
122
238
  storage.subscribe((change) => {
123
- console.log(`Key ${change.key} changed to:`, change.newValue);
124
- });
239
+ if (change.key === 'tab') applyTab(change.newValue);
240
+ }, { storage: 'url' });
125
241
  ```
126
242
 
127
- ## Platform Support
243
+ ### Configuration
128
244
 
129
- ### Web Browsers
130
- - **localStorage** - Simple key-value storage
131
- - **sessionStorage** - Session-scoped storage
132
- - **IndexedDB** - Large structured data
133
- - **Cookies** - Cookie-based storage
134
- - **Cache API** - HTTP cache storage
135
- - **Memory** - In-memory storage
245
+ Pass `URLAdapterConfig` when constructing the adapter:
136
246
 
137
- ### iOS (via Capacitor)
138
- - **UserDefaults** - User preferences
139
- - **Keychain** - Secure credential storage
140
- - **SQLite** - Database storage
141
- - **FileManager** - File-based storage
247
+ ```typescript
248
+ new URLAdapter(); // defaults below
249
+ ```
142
250
 
143
- ### Android (via Capacitor)
144
- - **SharedPreferences** - Simple key-value storage
145
- - **EncryptedSharedPreferences** - Secure storage
146
- - **SQLite** - Database storage
147
- - **File Storage** - File-based storage
251
+ | Option | Type | Default | Meaning |
252
+ |--------|------|---------|---------|
253
+ | `mode` | `'query'` \| `'hash'` | `'query'` | Store params in the query string (`?strata.tab=...`) or the hash fragment (`#strata.tab=...`). |
254
+ | `prefix` | `string` | `'strata.'` | Prefix on every param name to avoid collisions with your own query params. |
255
+ | `history` | `'push'` \| `'replace'` | `'replace'` | Whether each write adds a browser history entry or replaces the current one. |
256
+ | `maxLength` | `number` | `2000` | Soft warning threshold (chars) for total URL length. |
148
257
 
149
- ## Framework Integrations
258
+ The adapter is configured through `StrataConfig.adapters.url` when you let Strata manage it:
150
259
 
151
- ### React
260
+ ```typescript
261
+ const storage = defineStorage({ adapters: { url: { mode: 'hash', history: 'push' } } });
262
+ storage.registerAdapter(new URLAdapter());
263
+ ```
264
+
265
+ ### Limitations (read these)
266
+
267
+ - **Length limits.** URLs have practical limits (~2000 chars in some browsers and servers). This adapter is for small, simple, serializable state — not bulk data. Writes past `maxLength` are allowed but logged as a warning.
268
+ - **Server visibility.** In `'query'` mode the data is sent to the server on every navigation and appears in server/proxy logs. Use `'hash'` mode to keep it client-only (the fragment is never sent to the server).
269
+ - **Browser only.** Outside a browser (SSR/Node) the adapter reports unavailable; `isAvailable()` returns `false`.
270
+ - **Not persistent.** State lives only as long as the URL does — it is not durable storage.
271
+
272
+ ## Disaster Recovery
273
+
274
+ Strata includes opt-in recovery features for data you cannot afford to silently lose. **Everything here is off by default** — enable only what you need, since each adds overhead.
275
+
276
+ ### Integrity checksums
277
+
278
+ Set `integrity: true` (or per call `{ verify: true }`) to compute and store an FNV-1a checksum with each value and verify it on read. On corruption, Strata first attempts mirror read-repair (below); otherwise it honors `{ ignoreCorruption: true }` (returns `null`) or throws a typed `IntegrityError`.
152
279
 
153
280
  ```typescript
154
- import { useStrata } from 'strata-storage/react';
281
+ import { defineStorage } from 'strata-storage';
155
282
 
156
- function MyComponent() {
157
- const { data, loading, set, remove } = useStrata('myKey');
283
+ const storage = defineStorage({ integrity: true });
158
284
 
159
- return (
160
- <div>
161
- <p>{data}</p>
162
- <button onClick={() => set('newValue')}>Update</button>
163
- </div>
164
- );
165
- }
285
+ await storage.set('config', settings); // checksum stored
286
+ const config = await storage.get('config'); // verified; throws IntegrityError if corrupted
166
287
  ```
167
288
 
168
- ### Vue
289
+ > **Honest note:** checksums are **FNV-1a, non-cryptographic**. They cheaply detect *accidental* corruption (truncated writes, bit flips, partial storage). They do **not** resist tampering — for tamper resistance use the encryption feature.
290
+
291
+ ### Durable writes
292
+
293
+ `durableWrites: true` (or per call `{ durable: true }`) reads each value back after writing and retries on mismatch, throwing `StorageError` if it cannot confirm the write after a few attempts. This adds one read per write.
169
294
 
170
295
  ```typescript
171
- import { useStrata } from 'strata-storage/vue';
296
+ const storage = defineStorage({ durableWrites: true });
297
+ await storage.set('order', order); // confirmed written, or throws
298
+ ```
172
299
 
173
- export default {
174
- setup() {
175
- const { data, loading, set, remove } = useStrata('myKey');
300
+ ### Mirroring (read-repair)
176
301
 
177
- return { data, loading, set, remove };
178
- }
179
- };
302
+ `mirror: [...]` copies every write/remove to backup storage types. On a primary read miss or corruption, Strata recovers the value from a mirror and repairs the primary in place.
303
+
304
+ ```typescript
305
+ const storage = defineStorage({
306
+ defaultStorages: ['localStorage'],
307
+ integrity: true,
308
+ mirror: ['indexedDB'], // localStorage is primary; indexedDB backs it up
309
+ });
180
310
  ```
181
311
 
182
- ### Angular
312
+ ### Snapshots and scheduled backups
313
+
314
+ `snapshot()` produces a portable, integrity-verified backup string (embedding a checksum manifest); `restore()` validates that checksum and throws `IntegrityError` on a corrupted backup. `autoBackup` schedules periodic snapshots to a durable adapter.
183
315
 
184
316
  ```typescript
185
- import { StrataService } from 'strata-storage/angular';
317
+ const backup = await storage.snapshot(); // store/download this string
318
+ await storage.restore(backup); // validates, then restores
186
319
 
187
- @Component({ /* ... */ })
188
- export class MyComponent {
189
- constructor(private storage: StrataService) {}
320
+ // Scheduled, every 5 minutes, into indexedDB
321
+ const storage = defineStorage({
322
+ autoBackup: { interval: 5 * 60_000, storage: 'indexedDB' },
323
+ });
324
+ ```
190
325
 
191
- async saveData() {
192
- await this.storage.set('key', 'value');
193
- }
194
- }
326
+ Integrity helpers and error classes are exported for direct use:
327
+
328
+ ```typescript
329
+ import { computeChecksum, verifyChecksum, IntegrityError } from 'strata-storage';
195
330
  ```
196
331
 
197
- ## Documentation
332
+ ## Advanced Features
198
333
 
199
- - **[Getting Started](docs/getting-started/installation.md)** - Installation and setup guide
200
- - **[Quick Start](docs/getting-started/quick-start.md)** - Get up and running in minutes
201
- - **[API Reference](docs/api/README.md)** - Complete API documentation
202
- - **[Platform Guides](docs/guides/platforms/web.md)** - Platform-specific information
203
- - **[Examples](docs/examples/README.md)** - Real-world usage examples
204
- - **[Migration Guide](docs/MIGRATION.md)** - Migrating from other storage solutions
205
-
206
- ## Storage Adapters
207
-
208
- | Adapter | Platform | Use Case |
209
- |---------|----------|----------|
210
- | `localStorage` | Web | Simple key-value, persistent |
211
- | `sessionStorage` | Web | Session-scoped data |
212
- | `indexedDB` | Web | Large structured data |
213
- | `cookies` | Web | Cookie-based storage |
214
- | `cache` | Web | HTTP cache |
215
- | `memory` | All | Temporary in-memory |
216
- | `preferences` | Mobile | User preferences (UserDefaults/SharedPreferences) |
217
- | `secure` | Mobile | Encrypted storage (Keychain/EncryptedSharedPreferences) |
218
- | `sqlite` | Mobile | Database storage |
219
- | `filesystem` | Mobile | File-based storage |
334
+ ### Encryption (async only)
220
335
 
221
- ## Requirements
336
+ ```typescript
337
+ const storage = defineStorage({ encryption: { enabled: true, password: 'secret' } });
338
+ await storage.set('secret', { token: 'abc' }); // encrypted with AES-GCM
339
+ await storage.set('one-off', data, { encrypt: true }); // per-call override
340
+ ```
222
341
 
223
- - **Node.js**: 18.0.0 or higher
224
- - **TypeScript**: 5.0+ (optional, but recommended)
225
- - **Capacitor**: 5.x or 6.x (for mobile platforms)
342
+ ### TTL / expiration
226
343
 
227
- ## Browser Support
344
+ ```typescript
345
+ await storage.set('session', data, { ttl: 3_600_000 }); // expires in 1 hour
346
+ await storage.set('cache', data, { ttl: 600_000, sliding: true }); // reset on access
347
+ const ms = await storage.getTTL('session');
348
+ await storage.persist('session'); // remove expiry
349
+ ```
228
350
 
229
- - Chrome/Edge: Latest 2 versions
230
- - Firefox: Latest 2 versions
231
- - Safari: Latest 2 versions
232
- - iOS Safari: iOS 13+
233
- - Android WebView: Android 8+
351
+ ### Compression (async only)
234
352
 
235
- ## Why Strata Storage?
353
+ ```typescript
354
+ const storage = defineStorage({ compression: { enabled: true, threshold: 1024 } });
355
+ await storage.set('largePayload', bigObject); // compressed above 1KB
356
+ ```
236
357
 
237
- ### Zero Dependencies
238
- Unlike other storage solutions that depend on multiple packages, Strata Storage has **zero runtime dependencies**. Everything is built from scratch, ensuring:
239
- - Smaller bundle size
240
- - No dependency conflicts
241
- - Better security
242
- - Full control over implementation
358
+ ### Cross-tab sync
359
+
360
+ ```typescript
361
+ const storage = defineStorage({ sync: { enabled: true } });
362
+ storage.subscribe((change) => {
363
+ console.log(`${change.key} changed`, change.newValue);
364
+ });
365
+ ```
243
366
 
244
- ### Universal API
245
- One API works everywhere. No need to learn different APIs for web and mobile, or switch between libraries:
367
+ ### Queries
246
368
 
247
369
  ```typescript
248
- // Same code works on web, iOS, and Android
249
- await storage.set('key', 'value');
250
- const value = await storage.get('key');
370
+ await storage.set('user:1', user, { tags: ['users', 'active'] });
371
+ const active = await storage.query({
372
+ tags: { $in: ['active'] },
373
+ 'value.age': { $gte: 18 },
374
+ });
251
375
  ```
252
376
 
253
- ### Built-in Features
254
- Advanced features included out of the box:
255
- - Encryption (Web Crypto API / Native Crypto)
256
- - Compression (LZ-string algorithm)
257
- - TTL/Expiration
258
- - Cross-tab sync
259
- - Advanced queries
260
- - Data migrations
377
+ ## Platform Support
378
+
379
+ ### Web (works in any JS environment)
380
+
381
+ | Adapter | Backend | Use case |
382
+ |---------|---------|----------|
383
+ | `memory` | In-memory `Map` | Always-available fallback, tests |
384
+ | `localStorage` | `window.localStorage` | Persistent key-value (~5 MB) |
385
+ | `sessionStorage` | `window.sessionStorage` | Session-scoped data |
386
+ | `indexedDB` | IndexedDB | Large structured data |
387
+ | `cookies` | `document.cookie` | Small, server-accessible data |
388
+ | `cache` | Cache API | Service-worker / HTTP cache |
389
+ | `url` | `location` query/hash | Shareable UI state (see above) |
390
+
391
+ ### iOS and Android (via Capacitor)
392
+
393
+ Register native adapters yourself when running under Capacitor:
394
+
395
+ ```typescript
396
+ import { defineStorage } from 'strata-storage';
397
+ import { PreferencesAdapter, SecureStorageAdapter } from 'strata-storage/capacitor';
398
+
399
+ const storage = defineStorage();
400
+ storage.registerAdapter(new PreferencesAdapter()); // UserDefaults / SharedPreferences
401
+ storage.registerAdapter(new SecureStorageAdapter()); // Keychain / EncryptedSharedPreferences
402
+
403
+ await storage.set('secret', token, { storage: 'secure' });
404
+ ```
405
+
406
+ | Adapter | iOS backend | Android backend |
407
+ |---------|-------------|-----------------|
408
+ | `preferences` | UserDefaults | SharedPreferences |
409
+ | `secure` | Keychain | EncryptedSharedPreferences |
410
+ | `sqlite` | SQLite | SQLite |
411
+ | `filesystem` | FileManager | Filesystem |
412
+
413
+ > **Honest note:** the native iOS/Android adapters depend on your downstream Capacitor project setup and platform configuration. Behavior on a real device should be verified on-device — native storage cannot be exercised by the web/Node test suite.
414
+
415
+ ### Firebase (optional cloud sync)
416
+
417
+ ```typescript
418
+ import { defineStorage } from 'strata-storage';
419
+ import { enableFirebaseSync } from 'strata-storage/firebase';
420
+
421
+ const storage = defineStorage();
422
+ await enableFirebaseSync(storage, { apiKey: '…', projectId: '…', firestore: true });
423
+ await storage.set('data', value, { storage: 'firestore' });
424
+ ```
425
+
426
+ ## Storage Types
427
+
428
+ | Type | Platform | Synchronous | Encrypt/Compress | Notes |
429
+ |------|----------|-------------|-------------------|-------|
430
+ | `memory` | All | ✅ | async only | Always available |
431
+ | `localStorage` | Web | ✅ | async only | ~5 MB, persistent |
432
+ | `sessionStorage` | Web | ✅ | async only | Session-scoped |
433
+ | `indexedDB` | Web | ❌ | async only | Large structured data |
434
+ | `cookies` | Web | ✅ | async only | ~4 KB, server-readable |
435
+ | `cache` | Web | ❌ | async only | Cache API |
436
+ | `url` | Web | ✅ | async only | Shareable UI state, length-limited |
437
+ | `preferences` | Mobile | ❌ | async only | UserDefaults / SharedPreferences |
438
+ | `secure` | Mobile | ❌ | async only | Keychain / EncryptedSharedPreferences |
439
+ | `sqlite` | Mobile | ❌ | async only | Native SQLite |
440
+ | `filesystem` | Mobile | ❌ | async only | Native files |
441
+
442
+ "async only" means encryption and compression require the `await storage.set(...)` path — the synchronous API cannot encrypt or compress.
443
+
444
+ ## Requirements
445
+
446
+ - **Node.js:** `>= 24.13.0`
447
+ - **TypeScript:** strict mode supported (optional, recommended)
448
+ - **Capacitor:** `@capacitor/core >= 8.0.0` (for native platforms; optional peer dependency)
449
+
450
+ Optional peer dependencies (install only the ones you use): `react >= 19.2.3`, `vue >= 3.5.26`, `@angular/core` & `@angular/forms >= 21.0.6`.
451
+
452
+ ## Documentation
453
+
454
+ ### Getting Started
455
+ - [Installation](./docs/getting-started/installation.md) — install and set up
456
+ - [Quick Start](./docs/getting-started/quick-start.md) — running in minutes
457
+ - [Configuration](./docs/getting-started/configuration.md) — configuration options
458
+
459
+ ### Core
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)
479
+
480
+ ### Features
481
+ - [Encryption](./docs/guides/features/encryption.md)
482
+ - [Compression](./docs/guides/features/compression.md)
483
+ - [TTL Management](./docs/api/features/ttl.md)
484
+ - [Cross-Tab Sync](./docs/guides/features/sync.md)
485
+ - [Query Engine](./docs/guides/features/queries.md)
486
+ - [Migrations](./docs/guides/features/migrations.md)
487
+ - [Recovery & Integrity](./docs/api/features/recovery.md)
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)
261
507
 
262
508
  ## Contributing
263
509
 
264
- Contributions are welcome! Please read the [Contributing Guide](CONTRIBUTING.md) for details.
510
+ Contributions are welcome please read the [Contributing Guide](./.github/CONTRIBUTING.md).
265
511
 
266
512
  ## License
267
513
 
268
- Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
514
+ Apache License 2.0 see [LICENSE](LICENSE). Free for commercial use, modification, and distribution with patent protection; attribution required; provided without warranty.
269
515
 
270
516
  ## Author
271
517
 
@@ -279,19 +525,17 @@ Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
279
525
 
280
526
  ## Links
281
527
 
282
- - **NPM Package**: [npmjs.com/package/strata-storage](https://www.npmjs.com/package/strata-storage)
283
- - **GitHub Repository**: [github.com/aoneahsan/strata-storage](https://github.com/aoneahsan/strata-storage)
284
- - **Issue Tracker**: [github.com/aoneahsan/strata-storage/issues](https://github.com/aoneahsan/strata-storage/issues)
285
- - **Documentation**: [github.com/aoneahsan/strata-storage/tree/main/docs](https://github.com/aoneahsan/strata-storage/tree/main/docs)
528
+ - **NPM Package:** [npmjs.com/package/strata-storage](https://www.npmjs.com/package/strata-storage)
529
+ - **GitHub Repository:** [github.com/aoneahsan/strata-storage](https://github.com/aoneahsan/strata-storage)
530
+ - **Issue Tracker:** [github.com/aoneahsan/strata-storage/issues](https://github.com/aoneahsan/strata-storage/issues)
531
+ - **Documentation:** [github.com/aoneahsan/strata-storage/tree/main/docs](https://github.com/aoneahsan/strata-storage/tree/main/docs)
286
532
 
287
533
  ## Support
288
534
 
289
- If you encounter any issues or have questions:
290
-
291
- 1. Check the [FAQ](docs/reference/faq.md)
535
+ 1. Check the [FAQ](./docs/reference/faq.md)
292
536
  2. Search [existing issues](https://github.com/aoneahsan/strata-storage/issues)
293
- 3. Create a [new issue](https://github.com/aoneahsan/strata-storage/issues/new)
537
+ 3. Open a [new issue](https://github.com/aoneahsan/strata-storage/issues/new)
294
538
 
295
539
  ---
296
540
 
297
- Made with ❤️ by [Ahsan Mahmood](https://aoneahsan.com)
541
+ Made by [Ahsan Mahmood](https://aoneahsan.com). **One API. Every Storage. Everywhere.**