strata-storage 2.4.3 → 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.
Files changed (108) hide show
  1. package/AI-INTEGRATION-GUIDE.md +115 -261
  2. package/README.md +426 -182
  3. package/android/AGENTS.md +34 -0
  4. package/android/CLAUDE.md +51 -0
  5. package/android/src/main/java/com/strata/storage/SQLiteStorage.java +35 -0
  6. package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +191 -27
  7. package/dist/README.md +426 -182
  8. package/dist/adapters/capacitor/FilesystemAdapter.d.ts.map +1 -1
  9. package/dist/adapters/capacitor/FilesystemAdapter.js +2 -1
  10. package/dist/adapters/capacitor/PreferencesAdapter.d.ts.map +1 -1
  11. package/dist/adapters/capacitor/PreferencesAdapter.js +2 -1
  12. package/dist/adapters/capacitor/SecureAdapter.d.ts.map +1 -1
  13. package/dist/adapters/capacitor/SecureAdapter.js +2 -1
  14. package/dist/adapters/capacitor/SqliteAdapter.d.ts.map +1 -1
  15. package/dist/adapters/capacitor/SqliteAdapter.js +2 -1
  16. package/dist/adapters/web/CacheAdapter.d.ts.map +1 -1
  17. package/dist/adapters/web/CacheAdapter.js +11 -3
  18. package/dist/adapters/web/CookieAdapter.d.ts +37 -1
  19. package/dist/adapters/web/CookieAdapter.d.ts.map +1 -1
  20. package/dist/adapters/web/CookieAdapter.js +89 -9
  21. package/dist/adapters/web/IndexedDBAdapter.d.ts.map +1 -1
  22. package/dist/adapters/web/IndexedDBAdapter.js +10 -2
  23. package/dist/adapters/web/LocalStorageAdapter.d.ts +31 -0
  24. package/dist/adapters/web/LocalStorageAdapter.d.ts.map +1 -1
  25. package/dist/adapters/web/LocalStorageAdapter.js +92 -19
  26. package/dist/adapters/web/MemoryAdapter.d.ts +24 -0
  27. package/dist/adapters/web/MemoryAdapter.d.ts.map +1 -1
  28. package/dist/adapters/web/MemoryAdapter.js +69 -18
  29. package/dist/adapters/web/SessionStorageAdapter.d.ts +24 -0
  30. package/dist/adapters/web/SessionStorageAdapter.d.ts.map +1 -1
  31. package/dist/adapters/web/SessionStorageAdapter.js +71 -9
  32. package/dist/adapters/web/URLAdapter.d.ts +59 -0
  33. package/dist/adapters/web/URLAdapter.d.ts.map +1 -0
  34. package/dist/adapters/web/URLAdapter.js +234 -0
  35. package/dist/adapters/web/index.d.ts +1 -0
  36. package/dist/adapters/web/index.d.ts.map +1 -1
  37. package/dist/adapters/web/index.js +1 -0
  38. package/dist/android/AGENTS.md +34 -0
  39. package/dist/android/CLAUDE.md +51 -0
  40. package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +35 -0
  41. package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +191 -27
  42. package/dist/capacitor.d.ts.map +1 -1
  43. package/dist/capacitor.js +2 -1
  44. package/dist/core/BaseAdapter.d.ts +8 -0
  45. package/dist/core/BaseAdapter.d.ts.map +1 -1
  46. package/dist/core/BaseAdapter.js +34 -14
  47. package/dist/core/Strata.d.ts +56 -2
  48. package/dist/core/Strata.d.ts.map +1 -1
  49. package/dist/core/Strata.js +501 -53
  50. package/dist/features/encryption.d.ts.map +1 -1
  51. package/dist/features/encryption.js +3 -2
  52. package/dist/features/integrity.d.ts +16 -0
  53. package/dist/features/integrity.d.ts.map +1 -0
  54. package/dist/features/integrity.js +28 -0
  55. package/dist/features/observer.d.ts.map +1 -1
  56. package/dist/features/observer.js +2 -1
  57. package/dist/features/query.d.ts +7 -1
  58. package/dist/features/query.d.ts.map +1 -1
  59. package/dist/features/query.js +9 -2
  60. package/dist/features/sync.d.ts.map +1 -1
  61. package/dist/features/sync.js +4 -3
  62. package/dist/index.d.ts +35 -2
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +55 -30
  65. package/dist/integrations/angular/index.d.ts +158 -0
  66. package/dist/integrations/angular/index.d.ts.map +1 -0
  67. package/dist/integrations/angular/index.js +395 -0
  68. package/dist/integrations/index.d.ts +15 -0
  69. package/dist/integrations/index.d.ts.map +1 -0
  70. package/dist/integrations/index.js +18 -0
  71. package/dist/integrations/react/index.d.ts +75 -0
  72. package/dist/integrations/react/index.d.ts.map +1 -0
  73. package/dist/integrations/react/index.js +191 -0
  74. package/dist/integrations/vue/index.d.ts +103 -0
  75. package/dist/integrations/vue/index.d.ts.map +1 -0
  76. package/dist/integrations/vue/index.js +274 -0
  77. package/dist/ios/AGENTS.md +33 -0
  78. package/dist/ios/CLAUDE.md +49 -0
  79. package/dist/ios/Plugin/KeychainStorage.swift +139 -50
  80. package/dist/ios/Plugin/SQLiteStorage.swift +40 -0
  81. package/dist/ios/Plugin/StrataStoragePlugin.m +23 -0
  82. package/dist/ios/Plugin/StrataStoragePlugin.swift +201 -52
  83. package/dist/package.json +21 -5
  84. package/dist/plugin/index.d.ts.map +1 -1
  85. package/dist/plugin/index.js +2 -1
  86. package/dist/types/index.d.ts +58 -9
  87. package/dist/types/index.d.ts.map +1 -1
  88. package/dist/types/index.js +0 -13
  89. package/dist/utils/errors.d.ts +7 -0
  90. package/dist/utils/errors.d.ts.map +1 -1
  91. package/dist/utils/errors.js +15 -3
  92. package/dist/utils/index.d.ts +63 -5
  93. package/dist/utils/index.d.ts.map +1 -1
  94. package/dist/utils/index.js +109 -16
  95. package/dist/utils/logger.d.ts +31 -0
  96. package/dist/utils/logger.d.ts.map +1 -0
  97. package/dist/utils/logger.js +63 -0
  98. package/ios/AGENTS.md +33 -0
  99. package/ios/CLAUDE.md +49 -0
  100. package/ios/Plugin/KeychainStorage.swift +139 -50
  101. package/ios/Plugin/SQLiteStorage.swift +40 -0
  102. package/ios/Plugin/StrataStoragePlugin.m +23 -0
  103. package/ios/Plugin/StrataStoragePlugin.swift +201 -52
  104. package/package.json +31 -20
  105. package/scripts/build.js +16 -5
  106. package/scripts/configure.js +2 -6
  107. package/scripts/postinstall.js +2 -2
  108. 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: false, // We use async for consistency
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 = window.localStorage.getItem(this.prefix + key);
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
- await this.remove(key);
87
+ this.removeSync(key);
69
88
  return null;
70
89
  }
71
90
  return value;
72
91
  }
73
92
  catch (error) {
74
- console.error(`Failed to get key ${key} from localStorage:`, error);
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 = await this.get(key);
108
+ const oldValue = this.getSync(key);
84
109
  try {
85
110
  const serialized = serialize(value);
86
- window.localStorage.setItem(fullKey, serialized);
111
+ this.getStorage().setItem(fullKey, serialized);
87
112
  }
88
113
  catch (error) {
89
114
  if (this.isQuotaError(error)) {
90
- throw new QuotaExceededError('LocalStorage quota exceeded', {
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 localStorage`, error);
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
- const oldValue = await this.get(key);
105
- window.localStorage.removeItem(this.prefix + key);
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 < window.localStorage.length; i++) {
119
- const key = window.localStorage.key(i);
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) => window.localStorage.removeItem(key));
162
+ keysToRemove.forEach((key) => storage.removeItem(key));
125
163
  this.emitChange('*', undefined, undefined, 'local');
126
164
  return;
127
165
  }
128
- // Use base implementation for filtered clear
129
- await super.clear(options);
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 < window.localStorage.length; i++) {
137
- const fullKey = window.localStorage.key(i);
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 = await this.get(key);
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;IAepE;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC1E;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxC;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBlD;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKxC;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAkBxD;;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;IAgC9F;;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;;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: false, // We use async for consistency
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
- await this.remove(key);
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
- // Use base implementation for filtered clear
110
- await super.clear(options);
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
- await this.remove(key);
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
- // Check if querying storage metadata (tags, metadata, etc) or the actual value
151
- let matches = false;
152
- // Check for storage-level properties
153
- const storageProps = ['tags', 'metadata', 'created', 'updated', 'expires'];
154
- const isStorageQuery = Object.keys(condition).some((k) => storageProps.includes(k));
155
- if (isStorageQuery) {
156
- // Query against the storage wrapper
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;AAE5D,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;IAI/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;IAoBtF;;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;IAkB5F;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASxC;;OAEG;IACG,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBpE;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAmBxD;;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"}
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: false,
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
- await this.remove(key);
72
+ this.removeSync(key);
63
73
  return null;
64
74
  }
65
75
  return value;
66
76
  }
67
77
  catch (error) {
68
- console.error(`Failed to get key ${key} from sessionStorage:`, error);
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 = await this.get(key);
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
- const oldValue = await this.get(key);
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
- // Use base implementation for filtered clear
120
- await super.clear(options);
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 = await this.get(key);
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
  */