strata-storage 2.4.2 → 2.5.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 +208 -0
- package/README.md +427 -181
- package/android/AGENTS.md +34 -0
- package/android/CLAUDE.md +51 -0
- package/android/src/main/java/com/strata/storage/SQLiteStorage.java +35 -0
- package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +191 -27
- package/dist/README.md +427 -181
- package/dist/adapters/capacitor/FilesystemAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/FilesystemAdapter.js +2 -1
- package/dist/adapters/capacitor/PreferencesAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/PreferencesAdapter.js +2 -1
- package/dist/adapters/capacitor/SecureAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/SecureAdapter.js +2 -1
- package/dist/adapters/capacitor/SqliteAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitor/SqliteAdapter.js +2 -1
- package/dist/adapters/web/CacheAdapter.d.ts.map +1 -1
- package/dist/adapters/web/CacheAdapter.js +11 -3
- package/dist/adapters/web/CookieAdapter.d.ts +37 -1
- package/dist/adapters/web/CookieAdapter.d.ts.map +1 -1
- package/dist/adapters/web/CookieAdapter.js +89 -9
- package/dist/adapters/web/IndexedDBAdapter.d.ts.map +1 -1
- package/dist/adapters/web/IndexedDBAdapter.js +10 -2
- package/dist/adapters/web/LocalStorageAdapter.d.ts +31 -0
- package/dist/adapters/web/LocalStorageAdapter.d.ts.map +1 -1
- package/dist/adapters/web/LocalStorageAdapter.js +92 -19
- package/dist/adapters/web/MemoryAdapter.d.ts +24 -0
- package/dist/adapters/web/MemoryAdapter.d.ts.map +1 -1
- package/dist/adapters/web/MemoryAdapter.js +69 -18
- package/dist/adapters/web/SessionStorageAdapter.d.ts +24 -0
- package/dist/adapters/web/SessionStorageAdapter.d.ts.map +1 -1
- package/dist/adapters/web/SessionStorageAdapter.js +71 -9
- package/dist/adapters/web/URLAdapter.d.ts +59 -0
- package/dist/adapters/web/URLAdapter.d.ts.map +1 -0
- package/dist/adapters/web/URLAdapter.js +234 -0
- package/dist/adapters/web/index.d.ts +1 -0
- package/dist/adapters/web/index.d.ts.map +1 -1
- package/dist/adapters/web/index.js +1 -0
- package/dist/android/AGENTS.md +34 -0
- package/dist/android/CLAUDE.md +51 -0
- package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +35 -0
- package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +191 -27
- package/dist/capacitor.d.ts.map +1 -1
- package/dist/capacitor.js +2 -1
- package/dist/config/support.d.ts +10 -0
- package/dist/config/support.d.ts.map +1 -0
- package/dist/config/support.js +9 -0
- package/dist/core/BaseAdapter.d.ts +8 -0
- package/dist/core/BaseAdapter.d.ts.map +1 -1
- package/dist/core/BaseAdapter.js +34 -14
- package/dist/core/Strata.d.ts +56 -2
- package/dist/core/Strata.d.ts.map +1 -1
- package/dist/core/Strata.js +501 -53
- package/dist/features/encryption.d.ts.map +1 -1
- package/dist/features/encryption.js +3 -2
- package/dist/features/integrity.d.ts +16 -0
- package/dist/features/integrity.d.ts.map +1 -0
- package/dist/features/integrity.js +28 -0
- package/dist/features/observer.d.ts.map +1 -1
- package/dist/features/observer.js +2 -1
- package/dist/features/query.d.ts +7 -1
- package/dist/features/query.d.ts.map +1 -1
- package/dist/features/query.js +9 -2
- package/dist/features/sync.d.ts.map +1 -1
- package/dist/features/sync.js +4 -3
- package/dist/index.d.ts +35 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +55 -30
- package/dist/integrations/angular/index.d.ts +158 -0
- package/dist/integrations/angular/index.d.ts.map +1 -0
- package/dist/integrations/angular/index.js +395 -0
- package/dist/integrations/index.d.ts +15 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +18 -0
- package/dist/integrations/react/index.d.ts +75 -0
- package/dist/integrations/react/index.d.ts.map +1 -0
- package/dist/integrations/react/index.js +191 -0
- package/dist/integrations/vue/index.d.ts +103 -0
- package/dist/integrations/vue/index.d.ts.map +1 -0
- package/dist/integrations/vue/index.js +274 -0
- package/dist/ios/AGENTS.md +33 -0
- package/dist/ios/CLAUDE.md +49 -0
- package/dist/ios/Plugin/KeychainStorage.swift +139 -50
- package/dist/ios/Plugin/SQLiteStorage.swift +40 -0
- package/dist/ios/Plugin/StrataStoragePlugin.m +23 -0
- package/dist/ios/Plugin/StrataStoragePlugin.swift +201 -52
- package/dist/package.json +21 -5
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +2 -1
- package/dist/types/index.d.ts +58 -9
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -13
- package/dist/utils/errors.d.ts +7 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +15 -3
- package/dist/utils/index.d.ts +63 -5
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +109 -16
- package/dist/utils/logger.d.ts +31 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +63 -0
- package/ios/AGENTS.md +33 -0
- package/ios/CLAUDE.md +49 -0
- package/ios/Plugin/KeychainStorage.swift +139 -50
- package/ios/Plugin/SQLiteStorage.swift +40 -0
- package/ios/Plugin/StrataStoragePlugin.m +23 -0
- package/ios/Plugin/StrataStoragePlugin.swift +201 -52
- package/package.json +35 -23
- package/scripts/build.js +16 -5
- package/scripts/configure.js +2 -6
- package/scripts/postinstall.js +2 -2
- package/Readme.md +0 -271
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { BaseAdapter } from "../../core/BaseAdapter.js";
|
|
6
6
|
import { serialize, deserialize, getObjectSize } from "../../utils/index.js";
|
|
7
|
-
import { QuotaExceededError, SerializationError } from "../../utils/errors.js";
|
|
7
|
+
import { QuotaExceededError, SerializationError, StorageError } from "../../utils/errors.js";
|
|
8
|
+
import { logger } from "../../utils/logger.js";
|
|
8
9
|
/**
|
|
9
10
|
* Browser localStorage adapter
|
|
10
11
|
*/
|
|
@@ -12,7 +13,7 @@ export class LocalStorageAdapter extends BaseAdapter {
|
|
|
12
13
|
name = 'localStorage';
|
|
13
14
|
capabilities = {
|
|
14
15
|
persistent: true,
|
|
15
|
-
synchronous:
|
|
16
|
+
synchronous: true, // window.localStorage backend is synchronous
|
|
16
17
|
observable: true, // Via storage events
|
|
17
18
|
transactional: false,
|
|
18
19
|
queryable: true,
|
|
@@ -54,24 +55,42 @@ export class LocalStorageAdapter extends BaseAdapter {
|
|
|
54
55
|
}
|
|
55
56
|
this.startTTLCleanup();
|
|
56
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Get the backing Storage object.
|
|
60
|
+
* Subclasses (e.g. SessionStorageAdapter) override this to target a
|
|
61
|
+
* different Storage. All sync/async methods route through it so the
|
|
62
|
+
* subclass inherits correct behavior.
|
|
63
|
+
*/
|
|
64
|
+
getStorage() {
|
|
65
|
+
if (typeof window === 'undefined' || !window.localStorage) {
|
|
66
|
+
throw new StorageError(`${this.name} is not available in this environment (no window).`);
|
|
67
|
+
}
|
|
68
|
+
return window.localStorage;
|
|
69
|
+
}
|
|
57
70
|
/**
|
|
58
71
|
* Get a value from localStorage
|
|
59
72
|
*/
|
|
60
73
|
async get(key) {
|
|
74
|
+
return this.getSync(key);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get a value from localStorage (synchronous)
|
|
78
|
+
*/
|
|
79
|
+
getSync(key) {
|
|
61
80
|
try {
|
|
62
|
-
const item =
|
|
81
|
+
const item = this.getStorage().getItem(this.prefix + key);
|
|
63
82
|
if (!item)
|
|
64
83
|
return null;
|
|
65
84
|
const value = deserialize(item);
|
|
66
85
|
// Check TTL
|
|
67
86
|
if (this.isExpired(value)) {
|
|
68
|
-
|
|
87
|
+
this.removeSync(key);
|
|
69
88
|
return null;
|
|
70
89
|
}
|
|
71
90
|
return value;
|
|
72
91
|
}
|
|
73
92
|
catch (error) {
|
|
74
|
-
|
|
93
|
+
logger.error(`Failed to get key ${key} from ${this.name}:`, error);
|
|
75
94
|
return null;
|
|
76
95
|
}
|
|
77
96
|
}
|
|
@@ -79,20 +98,26 @@ export class LocalStorageAdapter extends BaseAdapter {
|
|
|
79
98
|
* Set a value in localStorage
|
|
80
99
|
*/
|
|
81
100
|
async set(key, value) {
|
|
101
|
+
this.setSync(key, value);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Set a value in localStorage (synchronous)
|
|
105
|
+
*/
|
|
106
|
+
setSync(key, value) {
|
|
82
107
|
const fullKey = this.prefix + key;
|
|
83
|
-
const oldValue =
|
|
108
|
+
const oldValue = this.getSync(key);
|
|
84
109
|
try {
|
|
85
110
|
const serialized = serialize(value);
|
|
86
|
-
|
|
111
|
+
this.getStorage().setItem(fullKey, serialized);
|
|
87
112
|
}
|
|
88
113
|
catch (error) {
|
|
89
114
|
if (this.isQuotaError(error)) {
|
|
90
|
-
throw new QuotaExceededError(
|
|
115
|
+
throw new QuotaExceededError(`${this.name} quota exceeded`, {
|
|
91
116
|
key,
|
|
92
117
|
size: getObjectSize(value),
|
|
93
118
|
});
|
|
94
119
|
}
|
|
95
|
-
throw new SerializationError(`Failed to store key ${key} in
|
|
120
|
+
throw new SerializationError(`Failed to store key ${key} in ${this.name}`, error);
|
|
96
121
|
}
|
|
97
122
|
// Emit change event (storage events don't fire in same window)
|
|
98
123
|
this.emitChange(key, oldValue?.value, value.value, 'local');
|
|
@@ -101,8 +126,14 @@ export class LocalStorageAdapter extends BaseAdapter {
|
|
|
101
126
|
* Remove a value from localStorage
|
|
102
127
|
*/
|
|
103
128
|
async remove(key) {
|
|
104
|
-
|
|
105
|
-
|
|
129
|
+
this.removeSync(key);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Remove a value from localStorage (synchronous)
|
|
133
|
+
*/
|
|
134
|
+
removeSync(key) {
|
|
135
|
+
const oldValue = this.getSync(key);
|
|
136
|
+
this.getStorage().removeItem(this.prefix + key);
|
|
106
137
|
if (oldValue) {
|
|
107
138
|
this.emitChange(key, oldValue.value, undefined, 'local');
|
|
108
139
|
}
|
|
@@ -111,34 +142,69 @@ export class LocalStorageAdapter extends BaseAdapter {
|
|
|
111
142
|
* Clear localStorage
|
|
112
143
|
*/
|
|
113
144
|
async clear(options) {
|
|
145
|
+
this.clearSync(options);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Clear localStorage (synchronous)
|
|
149
|
+
*/
|
|
150
|
+
clearSync(options) {
|
|
114
151
|
if (!options ||
|
|
115
152
|
(!options.pattern && !options.prefix && !options.tags && !options.expiredOnly)) {
|
|
116
153
|
// Clear all with our prefix
|
|
154
|
+
const storage = this.getStorage();
|
|
117
155
|
const keysToRemove = [];
|
|
118
|
-
for (let i = 0; i <
|
|
119
|
-
const key =
|
|
156
|
+
for (let i = 0; i < storage.length; i++) {
|
|
157
|
+
const key = storage.key(i);
|
|
120
158
|
if (key?.startsWith(this.prefix)) {
|
|
121
159
|
keysToRemove.push(key);
|
|
122
160
|
}
|
|
123
161
|
}
|
|
124
|
-
keysToRemove.forEach((key) =>
|
|
162
|
+
keysToRemove.forEach((key) => storage.removeItem(key));
|
|
125
163
|
this.emitChange('*', undefined, undefined, 'local');
|
|
126
164
|
return;
|
|
127
165
|
}
|
|
128
|
-
//
|
|
129
|
-
|
|
166
|
+
// Synchronous filtered clear (mirrors BaseAdapter.clear logic)
|
|
167
|
+
for (const key of this.keysSync()) {
|
|
168
|
+
let shouldDelete = true;
|
|
169
|
+
const pattern = options.pattern || options.prefix;
|
|
170
|
+
if (pattern) {
|
|
171
|
+
shouldDelete = this.filterKeys([key], pattern).length > 0;
|
|
172
|
+
}
|
|
173
|
+
if (shouldDelete && options.tags) {
|
|
174
|
+
const value = this.getSync(key);
|
|
175
|
+
if (!value?.tags || !options.tags.some((tag) => value.tags?.includes(tag))) {
|
|
176
|
+
shouldDelete = false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (shouldDelete && options.expiredOnly) {
|
|
180
|
+
const value = this.getSync(key);
|
|
181
|
+
if (!value || !this.isExpired(value)) {
|
|
182
|
+
shouldDelete = false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (shouldDelete) {
|
|
186
|
+
this.removeSync(key);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
130
189
|
}
|
|
131
190
|
/**
|
|
132
191
|
* Get all keys
|
|
133
192
|
*/
|
|
134
193
|
async keys(pattern) {
|
|
194
|
+
return this.keysSync(pattern);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get all keys (synchronous)
|
|
198
|
+
*/
|
|
199
|
+
keysSync(pattern) {
|
|
200
|
+
const storage = this.getStorage();
|
|
135
201
|
const keys = [];
|
|
136
|
-
for (let i = 0; i <
|
|
137
|
-
const fullKey =
|
|
202
|
+
for (let i = 0; i < storage.length; i++) {
|
|
203
|
+
const fullKey = storage.key(i);
|
|
138
204
|
if (fullKey?.startsWith(this.prefix)) {
|
|
139
205
|
const key = fullKey.substring(this.prefix.length);
|
|
140
206
|
// Check if not expired
|
|
141
|
-
const value =
|
|
207
|
+
const value = this.getSync(key);
|
|
142
208
|
if (value) {
|
|
143
209
|
keys.push(key);
|
|
144
210
|
}
|
|
@@ -146,6 +212,13 @@ export class LocalStorageAdapter extends BaseAdapter {
|
|
|
146
212
|
}
|
|
147
213
|
return this.filterKeys(keys, pattern);
|
|
148
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Check if key exists (synchronous)
|
|
217
|
+
*/
|
|
218
|
+
hasSync(key) {
|
|
219
|
+
const value = this.getSync(key);
|
|
220
|
+
return value !== null && !this.isExpired(value);
|
|
221
|
+
}
|
|
149
222
|
/**
|
|
150
223
|
* Get storage size
|
|
151
224
|
*/
|
|
@@ -27,26 +27,50 @@ 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
|
+
* Get a value from memory (synchronous)
|
|
32
|
+
*/
|
|
33
|
+
getSync<T = unknown>(key: string): StorageValue<T> | null;
|
|
30
34
|
/**
|
|
31
35
|
* Set a value in memory
|
|
32
36
|
*/
|
|
33
37
|
set<T = unknown>(key: string, value: StorageValue<T>): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Set a value in memory (synchronous)
|
|
40
|
+
*/
|
|
41
|
+
setSync<T = unknown>(key: string, value: StorageValue<T>): void;
|
|
34
42
|
/**
|
|
35
43
|
* Remove a value from memory
|
|
36
44
|
*/
|
|
37
45
|
remove(key: string): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Remove a value from memory (synchronous)
|
|
48
|
+
*/
|
|
49
|
+
removeSync(key: string): void;
|
|
38
50
|
/**
|
|
39
51
|
* Clear memory storage
|
|
40
52
|
*/
|
|
41
53
|
clear(options?: ClearOptions): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Clear memory storage (synchronous)
|
|
56
|
+
*/
|
|
57
|
+
clearSync(options?: ClearOptions): void;
|
|
42
58
|
/**
|
|
43
59
|
* Check if key exists
|
|
44
60
|
*/
|
|
45
61
|
has(key: string): Promise<boolean>;
|
|
62
|
+
/**
|
|
63
|
+
* Check if key exists (synchronous)
|
|
64
|
+
*/
|
|
65
|
+
hasSync(key: string): boolean;
|
|
46
66
|
/**
|
|
47
67
|
* Get all keys
|
|
48
68
|
*/
|
|
49
69
|
keys(pattern?: string | RegExp): Promise<string[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Get all keys (synchronous)
|
|
72
|
+
*/
|
|
73
|
+
keysSync(pattern?: string | RegExp): string[];
|
|
50
74
|
/**
|
|
51
75
|
* Query implementation for memory adapter
|
|
52
76
|
*/
|
|
@@ -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;
|
|
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"}
|
|
@@ -12,7 +12,7 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
12
12
|
name = 'memory';
|
|
13
13
|
capabilities = {
|
|
14
14
|
persistent: false,
|
|
15
|
-
synchronous:
|
|
15
|
+
synchronous: true, // Map backend is synchronous
|
|
16
16
|
observable: true,
|
|
17
17
|
transactional: false,
|
|
18
18
|
queryable: true,
|
|
@@ -41,12 +41,18 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
41
41
|
* Get a value from memory
|
|
42
42
|
*/
|
|
43
43
|
async get(key) {
|
|
44
|
+
return this.getSync(key);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get a value from memory (synchronous)
|
|
48
|
+
*/
|
|
49
|
+
getSync(key) {
|
|
44
50
|
const value = this.storage.get(key);
|
|
45
51
|
if (!value)
|
|
46
52
|
return null;
|
|
47
53
|
// Check TTL
|
|
48
54
|
if (this.isExpired(value)) {
|
|
49
|
-
|
|
55
|
+
this.removeSync(key);
|
|
50
56
|
return null;
|
|
51
57
|
}
|
|
52
58
|
// Return a deep clone to prevent external modifications
|
|
@@ -56,6 +62,12 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
56
62
|
* Set a value in memory
|
|
57
63
|
*/
|
|
58
64
|
async set(key, value) {
|
|
65
|
+
this.setSync(key, value);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Set a value in memory (synchronous)
|
|
69
|
+
*/
|
|
70
|
+
setSync(key, value) {
|
|
59
71
|
const oldValue = this.storage.get(key);
|
|
60
72
|
const newSize = this.calculateSize(value);
|
|
61
73
|
// Check size limit if configured
|
|
@@ -86,6 +98,12 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
86
98
|
* Remove a value from memory
|
|
87
99
|
*/
|
|
88
100
|
async remove(key) {
|
|
101
|
+
this.removeSync(key);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Remove a value from memory (synchronous)
|
|
105
|
+
*/
|
|
106
|
+
removeSync(key) {
|
|
89
107
|
const value = this.storage.get(key);
|
|
90
108
|
if (!value)
|
|
91
109
|
return;
|
|
@@ -98,6 +116,12 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
98
116
|
* Clear memory storage
|
|
99
117
|
*/
|
|
100
118
|
async clear(options) {
|
|
119
|
+
this.clearSync(options);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Clear memory storage (synchronous)
|
|
123
|
+
*/
|
|
124
|
+
clearSync(options) {
|
|
101
125
|
if (!options ||
|
|
102
126
|
(!options.pattern && !options.prefix && !options.tags && !options.expiredOnly)) {
|
|
103
127
|
// Clear everything
|
|
@@ -106,8 +130,29 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
106
130
|
this.emitChange('*', undefined, undefined, 'local');
|
|
107
131
|
return;
|
|
108
132
|
}
|
|
109
|
-
//
|
|
110
|
-
|
|
133
|
+
// Synchronous filtered clear (mirrors BaseAdapter.clear logic)
|
|
134
|
+
for (const key of this.keysSync()) {
|
|
135
|
+
let shouldDelete = true;
|
|
136
|
+
const pattern = options.pattern || options.prefix;
|
|
137
|
+
if (pattern) {
|
|
138
|
+
shouldDelete = this.filterKeys([key], pattern).length > 0;
|
|
139
|
+
}
|
|
140
|
+
if (shouldDelete && options.tags) {
|
|
141
|
+
const value = this.getSync(key);
|
|
142
|
+
if (!value?.tags || !options.tags.some((tag) => value.tags?.includes(tag))) {
|
|
143
|
+
shouldDelete = false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (shouldDelete && options.expiredOnly) {
|
|
147
|
+
const value = this.storage.get(key);
|
|
148
|
+
if (!value || !this.isExpired(value)) {
|
|
149
|
+
shouldDelete = false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (shouldDelete) {
|
|
153
|
+
this.removeSync(key);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
111
156
|
// Recalculate size after filtered clear
|
|
112
157
|
this.currentSize = 0;
|
|
113
158
|
for (const value of this.storage.values()) {
|
|
@@ -118,6 +163,12 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
118
163
|
* Check if key exists
|
|
119
164
|
*/
|
|
120
165
|
async has(key) {
|
|
166
|
+
return this.hasSync(key);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Check if key exists (synchronous)
|
|
170
|
+
*/
|
|
171
|
+
hasSync(key) {
|
|
121
172
|
const value = this.storage.get(key);
|
|
122
173
|
return value !== undefined && !this.isExpired(value);
|
|
123
174
|
}
|
|
@@ -125,6 +176,12 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
125
176
|
* Get all keys
|
|
126
177
|
*/
|
|
127
178
|
async keys(pattern) {
|
|
179
|
+
return this.keysSync(pattern);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Get all keys (synchronous)
|
|
183
|
+
*/
|
|
184
|
+
keysSync(pattern) {
|
|
128
185
|
const allKeys = Array.from(this.storage.keys());
|
|
129
186
|
// Remove expired entries
|
|
130
187
|
const validKeys = [];
|
|
@@ -135,7 +192,7 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
135
192
|
}
|
|
136
193
|
else if (value) {
|
|
137
194
|
// Clean up expired entry
|
|
138
|
-
|
|
195
|
+
this.removeSync(key);
|
|
139
196
|
}
|
|
140
197
|
}
|
|
141
198
|
return this.filterKeys(validKeys, pattern);
|
|
@@ -147,19 +204,13 @@ export class MemoryAdapter extends BaseAdapter {
|
|
|
147
204
|
const results = [];
|
|
148
205
|
for (const [key, item] of this.storage.entries()) {
|
|
149
206
|
if (!this.isExpired(item)) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
matches = this.queryEngine.matches(item, condition);
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
// Query against the stored value
|
|
161
|
-
matches = this.queryEngine.matches(item.value, condition);
|
|
162
|
-
}
|
|
207
|
+
const isStorageQuery = this.isStorageMetadataQuery(condition);
|
|
208
|
+
const normalizedCondition = isStorageQuery
|
|
209
|
+
? condition
|
|
210
|
+
: this.normalizeValueQueryCondition(condition);
|
|
211
|
+
const matches = isStorageQuery
|
|
212
|
+
? this.queryEngine.matches(item, normalizedCondition)
|
|
213
|
+
: this.queryEngine.matches(item.value, normalizedCondition);
|
|
163
214
|
if (matches) {
|
|
164
215
|
results.push({
|
|
165
216
|
key,
|
|
@@ -24,22 +24,46 @@ export declare class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
24
24
|
* Get a value from sessionStorage
|
|
25
25
|
*/
|
|
26
26
|
get<T = unknown>(key: string): Promise<import('@/types').StorageValue<T> | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Get a value from sessionStorage (synchronous)
|
|
29
|
+
*/
|
|
30
|
+
getSync<T = unknown>(key: string): import('@/types').StorageValue<T> | null;
|
|
27
31
|
/**
|
|
28
32
|
* Set a value in sessionStorage
|
|
29
33
|
*/
|
|
30
34
|
set<T = unknown>(key: string, value: import('@/types').StorageValue<T>): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Set a value in sessionStorage (synchronous)
|
|
37
|
+
*/
|
|
38
|
+
setSync<T = unknown>(key: string, value: import('@/types').StorageValue<T>): void;
|
|
31
39
|
/**
|
|
32
40
|
* Remove a value from sessionStorage
|
|
33
41
|
*/
|
|
34
42
|
remove(key: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Remove a value from sessionStorage (synchronous)
|
|
45
|
+
*/
|
|
46
|
+
removeSync(key: string): void;
|
|
35
47
|
/**
|
|
36
48
|
* Clear sessionStorage
|
|
37
49
|
*/
|
|
38
50
|
clear(options?: import('@/types').ClearOptions): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Clear sessionStorage (synchronous)
|
|
53
|
+
*/
|
|
54
|
+
clearSync(options?: import('@/types').ClearOptions): void;
|
|
39
55
|
/**
|
|
40
56
|
* Get all keys
|
|
41
57
|
*/
|
|
42
58
|
keys(pattern?: string | RegExp): Promise<string[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Get all keys (synchronous)
|
|
61
|
+
*/
|
|
62
|
+
keysSync(pattern?: string | RegExp): string[];
|
|
63
|
+
/**
|
|
64
|
+
* Check if key exists (synchronous)
|
|
65
|
+
*/
|
|
66
|
+
hasSync(key: string): boolean;
|
|
43
67
|
/**
|
|
44
68
|
* Get storage size
|
|
45
69
|
*/
|
|
@@ -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;AAG5D,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;IAS7B;;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,7 +3,8 @@
|
|
|
3
3
|
* Provides session-scoped storage with 5-10MB limit
|
|
4
4
|
*/
|
|
5
5
|
import { LocalStorageAdapter } from "./LocalStorageAdapter.js";
|
|
6
|
-
import { QuotaExceededError, SerializationError } from "../../utils/errors.js";
|
|
6
|
+
import { QuotaExceededError, SerializationError, StorageError } from "../../utils/errors.js";
|
|
7
|
+
import { logger } from "../../utils/logger.js";
|
|
7
8
|
/**
|
|
8
9
|
* Browser sessionStorage adapter
|
|
9
10
|
* Extends LocalStorageAdapter as the API is identical
|
|
@@ -12,7 +13,7 @@ export class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
12
13
|
name = 'sessionStorage';
|
|
13
14
|
capabilities = {
|
|
14
15
|
persistent: false, // Only for session
|
|
15
|
-
synchronous:
|
|
16
|
+
synchronous: true, // window.sessionStorage backend is synchronous
|
|
16
17
|
observable: true,
|
|
17
18
|
transactional: false,
|
|
18
19
|
queryable: true,
|
|
@@ -46,12 +47,21 @@ export class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
46
47
|
* Override all methods to use sessionStorage instead of localStorage
|
|
47
48
|
*/
|
|
48
49
|
getStorage() {
|
|
50
|
+
if (typeof window === 'undefined' || !window.sessionStorage) {
|
|
51
|
+
throw new StorageError(`${this.name} is not available in this environment (no window).`);
|
|
52
|
+
}
|
|
49
53
|
return window.sessionStorage;
|
|
50
54
|
}
|
|
51
55
|
/**
|
|
52
56
|
* Get a value from sessionStorage
|
|
53
57
|
*/
|
|
54
58
|
async get(key) {
|
|
59
|
+
return this.getSync(key);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get a value from sessionStorage (synchronous)
|
|
63
|
+
*/
|
|
64
|
+
getSync(key) {
|
|
55
65
|
try {
|
|
56
66
|
const item = window.sessionStorage.getItem(this.prefix + key);
|
|
57
67
|
if (!item)
|
|
@@ -59,13 +69,13 @@ export class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
59
69
|
const value = JSON.parse(item);
|
|
60
70
|
// Check TTL
|
|
61
71
|
if (this.isExpired(value)) {
|
|
62
|
-
|
|
72
|
+
this.removeSync(key);
|
|
63
73
|
return null;
|
|
64
74
|
}
|
|
65
75
|
return value;
|
|
66
76
|
}
|
|
67
77
|
catch (error) {
|
|
68
|
-
|
|
78
|
+
logger.error(`Failed to get key ${key} from sessionStorage:`, error);
|
|
69
79
|
return null;
|
|
70
80
|
}
|
|
71
81
|
}
|
|
@@ -73,8 +83,14 @@ export class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
73
83
|
* Set a value in sessionStorage
|
|
74
84
|
*/
|
|
75
85
|
async set(key, value) {
|
|
86
|
+
this.setSync(key, value);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Set a value in sessionStorage (synchronous)
|
|
90
|
+
*/
|
|
91
|
+
setSync(key, value) {
|
|
76
92
|
const fullKey = this.prefix + key;
|
|
77
|
-
const oldValue =
|
|
93
|
+
const oldValue = this.getSync(key);
|
|
78
94
|
try {
|
|
79
95
|
const serialized = JSON.stringify(value);
|
|
80
96
|
window.sessionStorage.setItem(fullKey, serialized);
|
|
@@ -92,7 +108,13 @@ export class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
92
108
|
* Remove a value from sessionStorage
|
|
93
109
|
*/
|
|
94
110
|
async remove(key) {
|
|
95
|
-
|
|
111
|
+
this.removeSync(key);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Remove a value from sessionStorage (synchronous)
|
|
115
|
+
*/
|
|
116
|
+
removeSync(key) {
|
|
117
|
+
const oldValue = this.getSync(key);
|
|
96
118
|
window.sessionStorage.removeItem(this.prefix + key);
|
|
97
119
|
if (oldValue) {
|
|
98
120
|
this.emitChange(key, oldValue.value, undefined, 'local');
|
|
@@ -102,6 +124,12 @@ export class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
102
124
|
* Clear sessionStorage
|
|
103
125
|
*/
|
|
104
126
|
async clear(options) {
|
|
127
|
+
this.clearSync(options);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Clear sessionStorage (synchronous)
|
|
131
|
+
*/
|
|
132
|
+
clearSync(options) {
|
|
105
133
|
if (!options ||
|
|
106
134
|
(!options.pattern && !options.prefix && !options.tags && !options.expiredOnly)) {
|
|
107
135
|
// Clear all with our prefix
|
|
@@ -116,20 +144,47 @@ export class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
116
144
|
this.emitChange('*', undefined, undefined, 'local');
|
|
117
145
|
return;
|
|
118
146
|
}
|
|
119
|
-
//
|
|
120
|
-
|
|
147
|
+
// Synchronous filtered clear (mirrors BaseAdapter.clear logic)
|
|
148
|
+
for (const key of this.keysSync()) {
|
|
149
|
+
let shouldDelete = true;
|
|
150
|
+
const pattern = options.pattern || options.prefix;
|
|
151
|
+
if (pattern) {
|
|
152
|
+
shouldDelete = this.filterKeys([key], pattern).length > 0;
|
|
153
|
+
}
|
|
154
|
+
if (shouldDelete && options.tags) {
|
|
155
|
+
const value = this.getSync(key);
|
|
156
|
+
if (!value?.tags || !options.tags.some((tag) => value.tags?.includes(tag))) {
|
|
157
|
+
shouldDelete = false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (shouldDelete && options.expiredOnly) {
|
|
161
|
+
const value = this.getSync(key);
|
|
162
|
+
if (!value || !this.isExpired(value)) {
|
|
163
|
+
shouldDelete = false;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (shouldDelete) {
|
|
167
|
+
this.removeSync(key);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
121
170
|
}
|
|
122
171
|
/**
|
|
123
172
|
* Get all keys
|
|
124
173
|
*/
|
|
125
174
|
async keys(pattern) {
|
|
175
|
+
return this.keysSync(pattern);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get all keys (synchronous)
|
|
179
|
+
*/
|
|
180
|
+
keysSync(pattern) {
|
|
126
181
|
const keys = [];
|
|
127
182
|
for (let i = 0; i < window.sessionStorage.length; i++) {
|
|
128
183
|
const fullKey = window.sessionStorage.key(i);
|
|
129
184
|
if (fullKey?.startsWith(this.prefix)) {
|
|
130
185
|
const key = fullKey.substring(this.prefix.length);
|
|
131
186
|
// Check if not expired
|
|
132
|
-
const value =
|
|
187
|
+
const value = this.getSync(key);
|
|
133
188
|
if (value) {
|
|
134
189
|
keys.push(key);
|
|
135
190
|
}
|
|
@@ -137,6 +192,13 @@ export class SessionStorageAdapter extends LocalStorageAdapter {
|
|
|
137
192
|
}
|
|
138
193
|
return this.filterKeys(keys, pattern);
|
|
139
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Check if key exists (synchronous)
|
|
197
|
+
*/
|
|
198
|
+
hasSync(key) {
|
|
199
|
+
const value = this.getSync(key);
|
|
200
|
+
return value !== null && !this.isExpired(value);
|
|
201
|
+
}
|
|
140
202
|
/**
|
|
141
203
|
* Get storage size
|
|
142
204
|
*/
|