strata-storage 2.6.1 → 2.7.1
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 +129 -11
- 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/CacheAdapter.d.ts.map +1 -1
- package/dist/adapters/web/CacheAdapter.js +20 -5
- package/dist/adapters/web/CookieAdapter.d.ts +2 -2
- package/dist/adapters/web/CookieAdapter.d.ts.map +1 -1
- package/dist/adapters/web/CookieAdapter.js +27 -3
- 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 +19 -4
- package/dist/adapters/web/LocalStorageAdapter.d.ts +2 -2
- package/dist/adapters/web/LocalStorageAdapter.d.ts.map +1 -1
- package/dist/adapters/web/LocalStorageAdapter.js +15 -1
- package/dist/adapters/web/MemoryAdapter.d.ts +9 -2
- package/dist/adapters/web/MemoryAdapter.d.ts.map +1 -1
- package/dist/adapters/web/MemoryAdapter.js +22 -5
- 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 +17 -3
- 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 +53 -7
- package/dist/core/Strata.d.ts.map +1 -1
- package/dist/core/Strata.js +581 -125
- package/dist/features/compression/index.d.ts +1 -1
- package/dist/features/compression.d.ts +28 -9
- package/dist/features/compression.d.ts.map +1 -1
- package/dist/features/compression.js +164 -77
- 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/migration.d.ts.map +1 -1
- package/dist/features/migration.js +7 -2
- 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 +2 -1
- package/dist/features/query.d.ts.map +1 -1
- package/dist/features/query.js +32 -7
- 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 +75 -12
- package/dist/features/ttl/index.d.ts +1 -1
- package/dist/features/ttl.d.ts +2 -2
- package/dist/features/ttl.d.ts.map +1 -1
- package/dist/features/ttl.js +4 -2
- package/dist/firebase.d.ts +1 -1
- package/dist/firebase.d.ts.map +1 -1
- package/dist/firebase.js +72 -10
- 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 +46 -27
- 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
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Provides network-aware storage for offline support
|
|
4
4
|
*/
|
|
5
5
|
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
|
-
import { getObjectSize } from "../../utils/index.js";
|
|
6
|
+
import { getObjectSize, serialize, deserialize } from "../../utils/index.js";
|
|
7
7
|
import { StorageError, QuotaExceededError, NotSupportedError } from "../../utils/errors.js";
|
|
8
8
|
import { logger } from "../../utils/logger.js";
|
|
9
9
|
/**
|
|
@@ -84,7 +84,7 @@ export class CacheAdapter extends BaseAdapter {
|
|
|
84
84
|
const response = await cache.match(url);
|
|
85
85
|
if (!response)
|
|
86
86
|
return null;
|
|
87
|
-
const data = (await response.
|
|
87
|
+
const data = deserialize(await response.text());
|
|
88
88
|
// Check TTL
|
|
89
89
|
if (this.isExpired(data)) {
|
|
90
90
|
await this.remove(key);
|
|
@@ -105,8 +105,9 @@ export class CacheAdapter extends BaseAdapter {
|
|
|
105
105
|
const url = this.keyToUrl(key);
|
|
106
106
|
const oldValue = await this.get(key);
|
|
107
107
|
try {
|
|
108
|
-
// Create Response with the data
|
|
109
|
-
|
|
108
|
+
// Create Response with the data (shared serialize preserves Date/Map/Set
|
|
109
|
+
// etc., matching the other adapters instead of raw JSON).
|
|
110
|
+
const response = new Response(serialize(value), {
|
|
110
111
|
headers: {
|
|
111
112
|
'Content-Type': 'application/json',
|
|
112
113
|
'X-Strata-Created': value.created.toString(),
|
|
@@ -130,7 +131,21 @@ export class CacheAdapter extends BaseAdapter {
|
|
|
130
131
|
async remove(key) {
|
|
131
132
|
const cache = await this.openCache();
|
|
132
133
|
const url = this.keyToUrl(key);
|
|
133
|
-
|
|
134
|
+
// Read raw via cache.match — NOT via get(), which deletes an expired entry
|
|
135
|
+
// by awaiting remove(), recursing here and never resolving. Only read when
|
|
136
|
+
// a listener needs the old value.
|
|
137
|
+
let oldValue = null;
|
|
138
|
+
if (this.hasChangeListeners()) {
|
|
139
|
+
const response = await cache.match(url);
|
|
140
|
+
if (response) {
|
|
141
|
+
try {
|
|
142
|
+
oldValue = deserialize(await response.text());
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
oldValue = null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
134
149
|
const deleted = await cache.delete(url);
|
|
135
150
|
if (deleted && oldValue) {
|
|
136
151
|
this.emitChange(key, oldValue.value, undefined, 'local');
|
|
@@ -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
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CookieAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/web/CookieAdapter.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;
|
|
1
|
+
{"version":3,"file":"CookieAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/web/CookieAdapter.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;AAKjB;;;;;;;;;GASG;AACH,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAa;IACvC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,aAAa,CAAQ;gBAEjB,MAAM,SAAY,EAAE,OAAO,GAAE,aAAkB;IAY3D;;;OAGG;IACH,OAAO,CAAC,eAAe;IAUvB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAiBrC;;OAEG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvD;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAIpE;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAuBzD;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1E;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAqC/D;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAwB7B;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IA4CvC;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIxD;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE;IAmB7C;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAK7B;;OAEG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAmCjD;;OAEG;IACH,OAAO,CAAC,SAAS;IAgBjB;;OAEG;IACH,OAAO,CAAC,SAAS;IA4CjB;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACH,OAAO,CAAC,aAAa;CAmBtB"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Provides limited storage with 4KB per cookie limit
|
|
4
4
|
*/
|
|
5
5
|
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
|
+
import { serialize, deserialize } from "../../utils/index.js";
|
|
6
7
|
import { StorageError, QuotaExceededError } from "../../utils/errors.js";
|
|
7
8
|
import { logger } from "../../utils/logger.js";
|
|
8
9
|
/**
|
|
@@ -92,7 +93,7 @@ export class CookieAdapter extends BaseAdapter {
|
|
|
92
93
|
return null;
|
|
93
94
|
try {
|
|
94
95
|
const decoded = decodeURIComponent(value);
|
|
95
|
-
const parsed =
|
|
96
|
+
const parsed = deserialize(decoded);
|
|
96
97
|
// Check TTL
|
|
97
98
|
if (this.isExpired(parsed)) {
|
|
98
99
|
this.removeSync(key);
|
|
@@ -118,7 +119,7 @@ export class CookieAdapter extends BaseAdapter {
|
|
|
118
119
|
const cookieKey = this.prefix + key;
|
|
119
120
|
const oldValue = this.getSync(key);
|
|
120
121
|
try {
|
|
121
|
-
const serialized =
|
|
122
|
+
const serialized = serialize(value);
|
|
122
123
|
const encoded = encodeURIComponent(serialized);
|
|
123
124
|
// Check size limit
|
|
124
125
|
if (encoded.length > this.maxCookieSize) {
|
|
@@ -153,8 +154,21 @@ export class CookieAdapter extends BaseAdapter {
|
|
|
153
154
|
* Remove a value from cookies (synchronous)
|
|
154
155
|
*/
|
|
155
156
|
removeSync(key) {
|
|
156
|
-
const oldValue = this.getSync(key);
|
|
157
157
|
const cookieKey = this.prefix + key;
|
|
158
|
+
// Read raw — NOT via getSync(), which deletes expired cookies by calling
|
|
159
|
+
// removeSync() and would recurse here forever. Only read with a listener.
|
|
160
|
+
let oldValue = null;
|
|
161
|
+
if (this.hasChangeListeners()) {
|
|
162
|
+
const raw = this.getCookie(cookieKey);
|
|
163
|
+
if (raw) {
|
|
164
|
+
try {
|
|
165
|
+
oldValue = deserialize(decodeURIComponent(raw));
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
oldValue = null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
158
172
|
this.deleteCookie(cookieKey);
|
|
159
173
|
if (oldValue) {
|
|
160
174
|
this.emitChange(key, oldValue.value, undefined, 'local');
|
|
@@ -289,6 +303,16 @@ export class CookieAdapter extends BaseAdapter {
|
|
|
289
303
|
setCookie(name, value, options = {}) {
|
|
290
304
|
if (typeof document === 'undefined')
|
|
291
305
|
return;
|
|
306
|
+
// The value is percent-encoded by the caller, but the NAME is written raw —
|
|
307
|
+
// reject cookie-control characters in it so a crafted key cannot inject
|
|
308
|
+
// extra attributes (`; Path=/`) or additional cookies (`; evil=1`).
|
|
309
|
+
const hasControlChar = [...name].some((ch) => {
|
|
310
|
+
const code = ch.charCodeAt(0);
|
|
311
|
+
return code < 0x20 || code === 0x7f;
|
|
312
|
+
});
|
|
313
|
+
if (/[;=,\s]/.test(name) || hasControlChar) {
|
|
314
|
+
throw new StorageError(`Invalid cookie name "${name}": contains forbidden characters`);
|
|
315
|
+
}
|
|
292
316
|
let cookie = `${name}=${value}`;
|
|
293
317
|
if (options.maxAge !== undefined) {
|
|
294
318
|
cookie += `; max-age=${options.maxAge}`;
|
|
@@ -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
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IndexedDBAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/web/IndexedDBAdapter.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;AAKjB;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAe;IACzC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,EAAE,CAAC,CAAc;gBAEb,MAAM,SAAkB,EAAE,SAAS,SAAY,EAAE,OAAO,SAAI;IAOxE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;OAEG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC;IASjB;;OAEG;YACW,YAAY;IAgC1B;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAiCpE;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B1E;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"IndexedDBAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/web/IndexedDBAdapter.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;AAKjB;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAe;IACzC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,EAAE,CAAC,CAAc;gBAEb,MAAM,SAAkB,EAAE,SAAS,SAAY,EAAE,OAAO,SAAI;IAOxE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;OAEG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC;IASjB;;OAEG;YACW,YAAY;IAgC1B;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAiCpE;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B1E;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BxC;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBlD;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA4BxD;;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;IA2C9F;;OAEG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAwDjD;;;;;;;;;OASG;IACG,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC;IAQzC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B;;OAEG;IACH,OAAO,CAAC,YAAY;CAMrB"}
|
|
@@ -139,7 +139,11 @@ export class IndexedDBAdapter extends BaseAdapter {
|
|
|
139
139
|
*/
|
|
140
140
|
async remove(key) {
|
|
141
141
|
const db = await this.openDatabase();
|
|
142
|
-
|
|
142
|
+
// Only read the old value when a listener needs it. get() on an expired key
|
|
143
|
+
// fire-and-forgets remove(), so an unconditional read here spawns redundant
|
|
144
|
+
// remove→get cycles; gating also drops the read for this observable:false
|
|
145
|
+
// adapter.
|
|
146
|
+
const oldValue = this.hasChangeListeners() ? await this.get(key) : null;
|
|
143
147
|
const { promise, resolve, reject } = createDeferred();
|
|
144
148
|
const transaction = db.transaction([this.storeName], 'readwrite');
|
|
145
149
|
const store = transaction.objectStore(this.storeName);
|
|
@@ -281,7 +285,14 @@ export class IndexedDBAdapter extends BaseAdapter {
|
|
|
281
285
|
return promise;
|
|
282
286
|
}
|
|
283
287
|
/**
|
|
284
|
-
* Begin a transaction
|
|
288
|
+
* Begin a transaction.
|
|
289
|
+
*
|
|
290
|
+
* IMPORTANT — IndexedDB transactions auto-commit as soon as control returns to
|
|
291
|
+
* the event loop with no pending requests. Issue all `set`/`remove`/`get`
|
|
292
|
+
* calls back-to-back and `await` them together (e.g. `Promise.all([...])`)
|
|
293
|
+
* BEFORE awaiting anything unrelated. Awaiting a non-IndexedDB promise between
|
|
294
|
+
* operations lets the transaction close, after which further calls fail with
|
|
295
|
+
* `TransactionInactiveError`. For most multi-write needs prefer `setMany()`.
|
|
285
296
|
*/
|
|
286
297
|
async transaction() {
|
|
287
298
|
const db = await this.openDatabase();
|
|
@@ -328,7 +339,7 @@ class IndexedDBTransaction {
|
|
|
328
339
|
const request = this.store.get(key);
|
|
329
340
|
request.onsuccess = () => {
|
|
330
341
|
const result = request.result;
|
|
331
|
-
resolve(result ? result.value : null);
|
|
342
|
+
resolve(result ? (result.value?.value ?? result.value) : null);
|
|
332
343
|
};
|
|
333
344
|
request.onerror = () => reject(new StorageError(`Transaction get failed: ${request.error}`));
|
|
334
345
|
return promise;
|
|
@@ -340,7 +351,11 @@ class IndexedDBTransaction {
|
|
|
340
351
|
const now = Date.now();
|
|
341
352
|
const record = {
|
|
342
353
|
key,
|
|
343
|
-
value
|
|
354
|
+
value: {
|
|
355
|
+
value,
|
|
356
|
+
created: now,
|
|
357
|
+
updated: now,
|
|
358
|
+
},
|
|
344
359
|
created: now,
|
|
345
360
|
updated: now,
|
|
346
361
|
};
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* LocalStorage Adapter - Browser localStorage implementation
|
|
3
3
|
* Provides persistent storage with 5-10MB limit
|
|
4
4
|
*/
|
|
5
|
-
import { BaseAdapter } from
|
|
6
|
-
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo, SubscriptionCallback, UnsubscribeFunction } from
|
|
5
|
+
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
|
+
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo, SubscriptionCallback, UnsubscribeFunction } from "../../types/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* Browser localStorage adapter
|
|
9
9
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalStorageAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/web/LocalStorageAdapter.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,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAKjB;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,WAAW;IAClD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAkB;IAC5C,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,CAAa;gBAE9E,MAAM,SAAK;IAKvB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBrC;;OAEG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO7D;;;;;OAKG;IACH,SAAS,CAAC,UAAU,IAAI,OAAO;IAO/B;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAIpE;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAoBzD;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1E;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAqB/D;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"LocalStorageAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/web/LocalStorageAdapter.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,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAKjB;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,WAAW;IAClD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAkB;IAC5C,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,CAAa;gBAE9E,MAAM,SAAK;IAKvB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBrC;;OAEG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO7D;;;;;OAKG;IACH,SAAS,CAAC,UAAU,IAAI,OAAO;IAO/B;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAIpE;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAoBzD;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1E;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAqB/D;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAuB7B;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAiDvC;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIxD;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE;IAoB7C;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAK7B;;OAEG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAwCjD;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,oBAAoB,GAAG,mBAAmB;IAuC9D;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5B;;OAEG;IACH,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;CAUhD"}
|
|
@@ -132,7 +132,21 @@ export class LocalStorageAdapter extends BaseAdapter {
|
|
|
132
132
|
* Remove a value from localStorage (synchronous)
|
|
133
133
|
*/
|
|
134
134
|
removeSync(key) {
|
|
135
|
-
|
|
135
|
+
// Read the raw stored value directly — NOT via getSync(), which deletes an
|
|
136
|
+
// expired entry by calling removeSync(), recursing here forever (stack
|
|
137
|
+
// overflow). Only read when a listener actually needs the old value.
|
|
138
|
+
let oldValue = null;
|
|
139
|
+
if (this.hasChangeListeners()) {
|
|
140
|
+
const item = this.getStorage().getItem(this.prefix + key);
|
|
141
|
+
if (item) {
|
|
142
|
+
try {
|
|
143
|
+
oldValue = deserialize(item);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
oldValue = null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
136
150
|
this.getStorage().removeItem(this.prefix + key);
|
|
137
151
|
if (oldValue) {
|
|
138
152
|
this.emitChange(key, oldValue.value, undefined, 'local');
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Memory Adapter - In-memory storage implementation
|
|
3
3
|
* Provides fast, non-persistent storage using Map
|
|
4
4
|
*/
|
|
5
|
-
import { BaseAdapter } from
|
|
6
|
-
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, QueryCondition } from
|
|
5
|
+
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
|
+
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, QueryCondition } from "../../types/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* In-memory storage adapter using Map
|
|
9
9
|
*/
|
|
@@ -27,6 +27,13 @@ export declare class MemoryAdapter extends BaseAdapter {
|
|
|
27
27
|
* Get a value from memory
|
|
28
28
|
*/
|
|
29
29
|
get<T = unknown>(key: string): Promise<StorageValue<T> | null>;
|
|
30
|
+
/**
|
|
31
|
+
* Clone a stored value to isolate it from external mutation. Prefers
|
|
32
|
+
* structuredClone (preserves Map/Set/Date/TypedArray/ArrayBuffer — so the
|
|
33
|
+
* advertised `binary: true` capability holds), falling back to deepClone where
|
|
34
|
+
* structuredClone is unavailable or the value isn't structured-cloneable.
|
|
35
|
+
*/
|
|
36
|
+
private clone;
|
|
30
37
|
/**
|
|
31
38
|
* Get a value from memory (synchronous)
|
|
32
39
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MemoryAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/web/MemoryAdapter.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,cAAc,EACf,MAAM,SAAS,CAAC;AAIjB;;GAEG;AACH,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAY;IACtC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,WAAW,CAAK;IAExB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;OAEG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9D;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAIpE;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAezD;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1E;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAiC/D;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAW7B;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IA+CvC;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIxC;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAK7B;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIxD;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE;IAkB7C;;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;IAyB9F;;OAEG;IACH,cAAc,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAOlD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7B"}
|
|
1
|
+
{"version":3,"file":"MemoryAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/web/MemoryAdapter.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,cAAc,EACf,MAAM,SAAS,CAAC;AAIjB;;GAEG;AACH,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAY;IACtC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;IAEF,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,WAAW,CAAK;IAExB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;OAEG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9D;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAIpE;;;;;OAKG;IACH,OAAO,CAAC,KAAK;IAWb;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAezD;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1E;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAiC/D;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAW7B;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IA+CvC;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIxC;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAK7B;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIxD;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE;IAkB7C;;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;IAyB9F;;OAEG;IACH,cAAc,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAOlD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7B"}
|
|
@@ -43,6 +43,23 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
43
43
|
async get(key) {
|
|
44
44
|
return this.getSync(key);
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Clone a stored value to isolate it from external mutation. Prefers
|
|
48
|
+
* structuredClone (preserves Map/Set/Date/TypedArray/ArrayBuffer — so the
|
|
49
|
+
* advertised `binary: true` capability holds), falling back to deepClone where
|
|
50
|
+
* structuredClone is unavailable or the value isn't structured-cloneable.
|
|
51
|
+
*/
|
|
52
|
+
clone(value) {
|
|
53
|
+
if (typeof structuredClone === 'function') {
|
|
54
|
+
try {
|
|
55
|
+
return structuredClone(value);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Fall through to deepClone (e.g. value carries a non-cloneable field).
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return deepClone(value);
|
|
62
|
+
}
|
|
46
63
|
/**
|
|
47
64
|
* Get a value from memory (synchronous)
|
|
48
65
|
*/
|
|
@@ -55,8 +72,8 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
55
72
|
this.removeSync(key);
|
|
56
73
|
return null;
|
|
57
74
|
}
|
|
58
|
-
// Return a
|
|
59
|
-
return
|
|
75
|
+
// Return a clone to prevent external modifications
|
|
76
|
+
return this.clone(value);
|
|
60
77
|
}
|
|
61
78
|
/**
|
|
62
79
|
* Set a value in memory
|
|
@@ -83,8 +100,8 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
83
100
|
});
|
|
84
101
|
}
|
|
85
102
|
}
|
|
86
|
-
// Store a
|
|
87
|
-
const clonedValue =
|
|
103
|
+
// Store a clone to prevent external modifications
|
|
104
|
+
const clonedValue = this.clone(value);
|
|
88
105
|
this.storage.set(key, clonedValue);
|
|
89
106
|
// Update size tracking
|
|
90
107
|
if (oldValue) {
|
|
@@ -214,7 +231,7 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
214
231
|
if (matches) {
|
|
215
232
|
results.push({
|
|
216
233
|
key,
|
|
217
|
-
value:
|
|
234
|
+
value: this.clone(item.value),
|
|
218
235
|
});
|
|
219
236
|
}
|
|
220
237
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* SessionStorage Adapter - Browser sessionStorage implementation
|
|
3
3
|
* Provides session-scoped storage with 5-10MB limit
|
|
4
4
|
*/
|
|
5
|
-
import { LocalStorageAdapter } from
|
|
6
|
-
import type { StorageType, StorageCapabilities } from
|
|
5
|
+
import { LocalStorageAdapter } from "./LocalStorageAdapter.js";
|
|
6
|
+
import type { StorageType, StorageCapabilities } from "../../types/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* Browser sessionStorage adapter
|
|
9
9
|
* Extends LocalStorageAdapter as the API is identical
|
|
@@ -23,19 +23,19 @@ export declare class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
23
23
|
/**
|
|
24
24
|
* Get a value from sessionStorage
|
|
25
25
|
*/
|
|
26
|
-
get<T = unknown>(key: string): Promise<import(
|
|
26
|
+
get<T = unknown>(key: string): Promise<import("../../types/index.js").StorageValue<T> | null>;
|
|
27
27
|
/**
|
|
28
28
|
* Get a value from sessionStorage (synchronous)
|
|
29
29
|
*/
|
|
30
|
-
getSync<T = unknown>(key: string): import(
|
|
30
|
+
getSync<T = unknown>(key: string): import("../../types/index.js").StorageValue<T> | null;
|
|
31
31
|
/**
|
|
32
32
|
* Set a value in sessionStorage
|
|
33
33
|
*/
|
|
34
|
-
set<T = unknown>(key: string, value: import(
|
|
34
|
+
set<T = unknown>(key: string, value: import("../../types/index.js").StorageValue<T>): Promise<void>;
|
|
35
35
|
/**
|
|
36
36
|
* Set a value in sessionStorage (synchronous)
|
|
37
37
|
*/
|
|
38
|
-
setSync<T = unknown>(key: string, value: import(
|
|
38
|
+
setSync<T = unknown>(key: string, value: import("../../types/index.js").StorageValue<T>): void;
|
|
39
39
|
/**
|
|
40
40
|
* Remove a value from sessionStorage
|
|
41
41
|
*/
|
|
@@ -47,11 +47,11 @@ export declare class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
47
47
|
/**
|
|
48
48
|
* Clear sessionStorage
|
|
49
49
|
*/
|
|
50
|
-
clear(options?: import(
|
|
50
|
+
clear(options?: import("../../types/index.js").ClearOptions): Promise<void>;
|
|
51
51
|
/**
|
|
52
52
|
* Clear sessionStorage (synchronous)
|
|
53
53
|
*/
|
|
54
|
-
clearSync(options?: import(
|
|
54
|
+
clearSync(options?: import("../../types/index.js").ClearOptions): void;
|
|
55
55
|
/**
|
|
56
56
|
* Get all keys
|
|
57
57
|
*/
|
|
@@ -67,11 +67,11 @@ export declare class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
67
67
|
/**
|
|
68
68
|
* Get storage size
|
|
69
69
|
*/
|
|
70
|
-
size(detailed?: boolean): Promise<import(
|
|
70
|
+
size(detailed?: boolean): Promise<import("../../types/index.js").SizeInfo>;
|
|
71
71
|
/**
|
|
72
72
|
* Subscribe to storage changes
|
|
73
73
|
* Note: sessionStorage doesn't fire storage events in the same tab
|
|
74
74
|
*/
|
|
75
|
-
subscribe(callback: import(
|
|
75
|
+
subscribe(callback: import("../../types/index.js").SubscriptionCallback): import("../../types/index.js").UnsubscribeFunction;
|
|
76
76
|
}
|
|
77
77
|
//# sourceMappingURL=SessionStorageAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionStorageAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/web/SessionStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionStorageAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/web/SessionStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEhE;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,mBAAmB;IAC5D,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAoB;IAC9C,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAUxC;gBAEU,MAAM,SAAK;IAIvB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBrC;;OAEG;IACH,SAAS,CAAC,UAAU,IAAI,OAAO;IAO/B;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAItF;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAoB3E;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5F;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAkBjF;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAsB7B;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,EAAE,OAAO,SAAS,EAAE,YAAY,GAAG,IAAI;IAgDzD;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIxD;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE;IAmB7C;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAK7B;;OAEG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,SAAS,EAAE,QAAQ,CAAC;IAwCnE;;;OAGG;IACH,SAAS,CACP,QAAQ,EAAE,OAAO,SAAS,EAAE,oBAAoB,GAC/C,OAAO,SAAS,EAAE,mBAAmB;CAKzC"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Provides session-scoped storage with 5-10MB limit
|
|
4
4
|
*/
|
|
5
5
|
import { LocalStorageAdapter } from "./LocalStorageAdapter.js";
|
|
6
|
+
import { serialize, deserialize } from "../../utils/index.js";
|
|
6
7
|
import { QuotaExceededError, SerializationError, StorageError } from "../../utils/errors.js";
|
|
7
8
|
import { logger } from "../../utils/logger.js";
|
|
8
9
|
/**
|
|
@@ -66,7 +67,7 @@ export class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
66
67
|
const item = window.sessionStorage.getItem(this.prefix + key);
|
|
67
68
|
if (!item)
|
|
68
69
|
return null;
|
|
69
|
-
const value =
|
|
70
|
+
const value = deserialize(item);
|
|
70
71
|
// Check TTL
|
|
71
72
|
if (this.isExpired(value)) {
|
|
72
73
|
this.removeSync(key);
|
|
@@ -92,7 +93,7 @@ export class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
92
93
|
const fullKey = this.prefix + key;
|
|
93
94
|
const oldValue = this.getSync(key);
|
|
94
95
|
try {
|
|
95
|
-
const serialized =
|
|
96
|
+
const serialized = serialize(value);
|
|
96
97
|
window.sessionStorage.setItem(fullKey, serialized);
|
|
97
98
|
}
|
|
98
99
|
catch (error) {
|
|
@@ -114,7 +115,20 @@ export class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
114
115
|
* Remove a value from sessionStorage (synchronous)
|
|
115
116
|
*/
|
|
116
117
|
removeSync(key) {
|
|
117
|
-
|
|
118
|
+
// Read raw — NOT via getSync(), which deletes expired entries by calling
|
|
119
|
+
// removeSync() and would recurse here forever. Only read with a listener.
|
|
120
|
+
let oldValue = null;
|
|
121
|
+
if (this.hasChangeListeners()) {
|
|
122
|
+
const item = window.sessionStorage.getItem(this.prefix + key);
|
|
123
|
+
if (item) {
|
|
124
|
+
try {
|
|
125
|
+
oldValue = deserialize(item);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
oldValue = null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
118
132
|
window.sessionStorage.removeItem(this.prefix + key);
|
|
119
133
|
if (oldValue) {
|
|
120
134
|
this.emitChange(key, oldValue.value, undefined, 'local');
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* - Query mode is visible to the server on navigation; hash mode is client-only.
|
|
13
13
|
* - Not available outside a browser (SSR/Node) — `isAvailable()` returns false.
|
|
14
14
|
*/
|
|
15
|
-
import { BaseAdapter } from
|
|
16
|
-
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions } from
|
|
15
|
+
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
16
|
+
import type { StorageType, StorageCapabilities, StorageValue, ClearOptions } from "../../types/index.js";
|
|
17
17
|
/** Configuration for the URL adapter. */
|
|
18
18
|
export interface URLAdapterConfig {
|
|
19
19
|
/** Where to store params: query string (default) or hash fragment. */
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Web storage adapters
|
|
3
3
|
*/
|
|
4
|
-
export { MemoryAdapter } from
|
|
5
|
-
export { LocalStorageAdapter } from
|
|
6
|
-
export { SessionStorageAdapter } from
|
|
7
|
-
export { IndexedDBAdapter } from
|
|
8
|
-
export { CookieAdapter } from
|
|
9
|
-
export { CacheAdapter } from
|
|
10
|
-
export { URLAdapter, type URLAdapterConfig } from
|
|
4
|
+
export { MemoryAdapter } from "./MemoryAdapter.js";
|
|
5
|
+
export { LocalStorageAdapter } from "./LocalStorageAdapter.js";
|
|
6
|
+
export { SessionStorageAdapter } from "./SessionStorageAdapter.js";
|
|
7
|
+
export { IndexedDBAdapter } from "./IndexedDBAdapter.js";
|
|
8
|
+
export { CookieAdapter } from "./CookieAdapter.js";
|
|
9
|
+
export { CacheAdapter } from "./CacheAdapter.js";
|
|
10
|
+
export { URLAdapter, type URLAdapterConfig } from "./URLAdapter.js";
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/capacitor.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { Strata } from
|
|
2
|
-
export { PreferencesAdapter } from
|
|
3
|
-
export { SqliteAdapter } from
|
|
4
|
-
export { SecureAdapter } from
|
|
5
|
-
export { FilesystemAdapter } from
|
|
6
|
-
export { StrataStorage } from
|
|
1
|
+
import type { Strata } from "./core/Strata.js";
|
|
2
|
+
export { PreferencesAdapter } from "./adapters/capacitor/PreferencesAdapter.js";
|
|
3
|
+
export { SqliteAdapter } from "./adapters/capacitor/SqliteAdapter.js";
|
|
4
|
+
export { SecureAdapter } from "./adapters/capacitor/SecureAdapter.js";
|
|
5
|
+
export { FilesystemAdapter } from "./adapters/capacitor/FilesystemAdapter.js";
|
|
6
|
+
export { StrataStorage } from "./plugin/index.js";
|
|
7
7
|
/**
|
|
8
8
|
* Register Capacitor adapters with a Strata instance
|
|
9
9
|
* This is completely optional and only needed for Capacitor apps
|
package/dist/capacitor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capacitor.d.ts","sourceRoot":"","sources":["../src/capacitor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAQ5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAG3E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;GAGG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"capacitor.d.ts","sourceRoot":"","sources":["../src/capacitor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAQ5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAG3E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;GAGG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB9E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAShD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAEnD"}
|
package/dist/capacitor.js
CHANGED
|
@@ -28,10 +28,11 @@ export async function registerCapacitorAdapters(storage) {
|
|
|
28
28
|
storage.registerAdapter(new SqliteAdapter());
|
|
29
29
|
storage.registerAdapter(new SecureAdapter());
|
|
30
30
|
storage.registerAdapter(new FilesystemAdapter());
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
// Attach the newly registered adapters. initialize() is idempotent and would
|
|
32
|
+
// NOT pick up adapters registered after first init, so refreshAdapters()
|
|
33
|
+
// initializes + attaches them (and re-selects the default) whether or not the
|
|
34
|
+
// instance was already initialized.
|
|
35
|
+
await storage.refreshAdapters();
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
38
|
* Helper to check if running in Capacitor environment
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Base adapter implementation with common functionality
|
|
3
3
|
*/
|
|
4
|
-
import type { StorageAdapter, StorageValue, StorageType, StorageCapabilities, ClearOptions, SizeInfo, SubscriptionCallback, UnsubscribeFunction, QueryCondition } from
|
|
5
|
-
import { EventEmitter } from
|
|
6
|
-
import { QueryEngine } from
|
|
4
|
+
import type { StorageAdapter, StorageValue, StorageType, StorageCapabilities, ClearOptions, SizeInfo, SubscriptionCallback, UnsubscribeFunction, QueryCondition } from "../types/index.js";
|
|
5
|
+
import { EventEmitter } from "../utils/index.js";
|
|
6
|
+
import { QueryEngine } from "../features/query.js";
|
|
7
7
|
/**
|
|
8
8
|
* Abstract base adapter that implements common functionality
|
|
9
9
|
*/
|
|
@@ -23,9 +23,16 @@ export declare abstract class BaseAdapter implements StorageAdapter {
|
|
|
23
23
|
*/
|
|
24
24
|
protected stopTTLCleanup(): void;
|
|
25
25
|
/**
|
|
26
|
-
* Clean up expired items
|
|
26
|
+
* Clean up expired items, returning how many were removed.
|
|
27
|
+
*
|
|
28
|
+
* Default implementation is a per-key sweep (enumerate keys, drop the expired
|
|
29
|
+
* ones). Backends that can filter expired rows in the storage engine itself
|
|
30
|
+
* (e.g. SQLite) override this with a single bulk delete — and because such a
|
|
31
|
+
* backend's `keys()` no longer surfaces expired entries, this per-key sweep
|
|
32
|
+
* would not see them anyway. Called by the automatic TTL tick and by
|
|
33
|
+
* `Strata.cleanupExpired()`.
|
|
27
34
|
*/
|
|
28
|
-
|
|
35
|
+
cleanupExpired(): Promise<number>;
|
|
29
36
|
/**
|
|
30
37
|
* Check if value is expired
|
|
31
38
|
*/
|
|
@@ -62,6 +69,15 @@ export declare abstract class BaseAdapter implements StorageAdapter {
|
|
|
62
69
|
* Subscribe to changes (if supported)
|
|
63
70
|
*/
|
|
64
71
|
subscribe(callback: SubscriptionCallback): UnsubscribeFunction;
|
|
72
|
+
/**
|
|
73
|
+
* Whether any subscriber is currently attached to this adapter's change
|
|
74
|
+
* stream. Adapters that talk to a slow backend (native bridge, network) use
|
|
75
|
+
* this to avoid a wasted read-before-write: fetching the previous value just
|
|
76
|
+
* to populate a change event is pointless when nobody is listening. When a
|
|
77
|
+
* subscriber IS attached, callers must still capture the old value so the
|
|
78
|
+
* emitted change is complete. See `SqliteAdapter.set`/`remove`.
|
|
79
|
+
*/
|
|
80
|
+
protected hasChangeListeners(): boolean;
|
|
65
81
|
/**
|
|
66
82
|
* Emit change event
|
|
67
83
|
*/
|