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.
Files changed (143) hide show
  1. package/AI-INTEGRATION-GUIDE.md +129 -11
  2. package/README.md +42 -64
  3. package/android/AGENTS.md +18 -3
  4. package/android/CLAUDE.md +36 -3
  5. package/android/build.gradle +5 -1
  6. package/android/src/main/java/com/strata/storage/EncryptedStorage.java +31 -18
  7. package/android/src/main/java/com/strata/storage/FilesystemStorage.java +62 -10
  8. package/android/src/main/java/com/strata/storage/SQLiteStorage.java +65 -13
  9. package/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +63 -51
  10. package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +80 -11
  11. package/dist/README.md +42 -64
  12. package/dist/adapters/capacitor/FilesystemAdapter.d.ts +2 -2
  13. package/dist/adapters/capacitor/FilesystemAdapter.d.ts.map +1 -1
  14. package/dist/adapters/capacitor/FilesystemAdapter.js +6 -2
  15. package/dist/adapters/capacitor/PreferencesAdapter.d.ts +2 -2
  16. package/dist/adapters/capacitor/PreferencesAdapter.d.ts.map +1 -1
  17. package/dist/adapters/capacitor/PreferencesAdapter.js +6 -2
  18. package/dist/adapters/capacitor/SecureAdapter.d.ts +3 -3
  19. package/dist/adapters/capacitor/SecureAdapter.d.ts.map +1 -1
  20. package/dist/adapters/capacitor/SecureAdapter.js +6 -2
  21. package/dist/adapters/capacitor/SqliteAdapter.d.ts +24 -3
  22. package/dist/adapters/capacitor/SqliteAdapter.d.ts.map +1 -1
  23. package/dist/adapters/capacitor/SqliteAdapter.js +105 -23
  24. package/dist/adapters/capacitor/index.d.ts +4 -4
  25. package/dist/adapters/web/CacheAdapter.d.ts +2 -2
  26. package/dist/adapters/web/CacheAdapter.d.ts.map +1 -1
  27. package/dist/adapters/web/CacheAdapter.js +20 -5
  28. package/dist/adapters/web/CookieAdapter.d.ts +2 -2
  29. package/dist/adapters/web/CookieAdapter.d.ts.map +1 -1
  30. package/dist/adapters/web/CookieAdapter.js +27 -3
  31. package/dist/adapters/web/IndexedDBAdapter.d.ts +10 -3
  32. package/dist/adapters/web/IndexedDBAdapter.d.ts.map +1 -1
  33. package/dist/adapters/web/IndexedDBAdapter.js +19 -4
  34. package/dist/adapters/web/LocalStorageAdapter.d.ts +2 -2
  35. package/dist/adapters/web/LocalStorageAdapter.d.ts.map +1 -1
  36. package/dist/adapters/web/LocalStorageAdapter.js +15 -1
  37. package/dist/adapters/web/MemoryAdapter.d.ts +9 -2
  38. package/dist/adapters/web/MemoryAdapter.d.ts.map +1 -1
  39. package/dist/adapters/web/MemoryAdapter.js +22 -5
  40. package/dist/adapters/web/SessionStorageAdapter.d.ts +10 -10
  41. package/dist/adapters/web/SessionStorageAdapter.d.ts.map +1 -1
  42. package/dist/adapters/web/SessionStorageAdapter.js +17 -3
  43. package/dist/adapters/web/URLAdapter.d.ts +2 -2
  44. package/dist/adapters/web/index.d.ts +7 -7
  45. package/dist/capacitor.d.ts +6 -6
  46. package/dist/capacitor.d.ts.map +1 -1
  47. package/dist/capacitor.js +5 -4
  48. package/dist/core/AdapterRegistry.d.ts +1 -1
  49. package/dist/core/BaseAdapter.d.ts +21 -5
  50. package/dist/core/BaseAdapter.d.ts.map +1 -1
  51. package/dist/core/BaseAdapter.js +29 -1
  52. package/dist/core/Strata.d.ts +53 -7
  53. package/dist/core/Strata.d.ts.map +1 -1
  54. package/dist/core/Strata.js +581 -125
  55. package/dist/features/compression/index.d.ts +1 -1
  56. package/dist/features/compression.d.ts +28 -9
  57. package/dist/features/compression.d.ts.map +1 -1
  58. package/dist/features/compression.js +164 -77
  59. package/dist/features/encryption/index.d.ts +1 -1
  60. package/dist/features/encryption.d.ts +55 -2
  61. package/dist/features/encryption.d.ts.map +1 -1
  62. package/dist/features/encryption.js +139 -26
  63. package/dist/features/migration.d.ts +1 -1
  64. package/dist/features/migration.d.ts.map +1 -1
  65. package/dist/features/migration.js +7 -2
  66. package/dist/features/observer/index.d.ts +1 -1
  67. package/dist/features/observer.d.ts +1 -1
  68. package/dist/features/query/index.d.ts +1 -1
  69. package/dist/features/query.d.ts +2 -1
  70. package/dist/features/query.d.ts.map +1 -1
  71. package/dist/features/query.js +32 -7
  72. package/dist/features/sync/index.d.ts +1 -1
  73. package/dist/features/sync.d.ts +19 -3
  74. package/dist/features/sync.d.ts.map +1 -1
  75. package/dist/features/sync.js +75 -12
  76. package/dist/features/ttl/index.d.ts +1 -1
  77. package/dist/features/ttl.d.ts +2 -2
  78. package/dist/features/ttl.d.ts.map +1 -1
  79. package/dist/features/ttl.js +4 -2
  80. package/dist/firebase.d.ts +1 -1
  81. package/dist/firebase.d.ts.map +1 -1
  82. package/dist/firebase.js +72 -10
  83. package/dist/index.d.ts +24 -22
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +6 -1
  86. package/dist/integrations/angular/index.d.ts +2 -2
  87. package/dist/integrations/angular/index.d.ts.map +1 -1
  88. package/dist/integrations/angular/index.js +7 -8
  89. package/dist/integrations/react/index.d.ts +3 -3
  90. package/dist/integrations/react/index.d.ts.map +1 -1
  91. package/dist/integrations/react/index.js +16 -4
  92. package/dist/integrations/vue/index.d.ts +2 -2
  93. package/dist/integrations/vue/index.d.ts.map +1 -1
  94. package/dist/integrations/vue/index.js +5 -2
  95. package/dist/package.json +11 -2
  96. package/dist/plugin/definitions.d.ts +29 -3
  97. package/dist/plugin/definitions.d.ts.map +1 -1
  98. package/dist/plugin/index.d.ts +2 -2
  99. package/dist/plugin/index.d.ts.map +1 -1
  100. package/dist/plugin/index.js +3 -0
  101. package/dist/plugin/web.d.ts +11 -2
  102. package/dist/plugin/web.d.ts.map +1 -1
  103. package/dist/plugin/web.js +23 -4
  104. package/dist/types/index.d.ts +50 -20
  105. package/dist/types/index.d.ts.map +1 -1
  106. package/dist/types/index.js +1 -10
  107. package/dist/utils/index.d.ts +5 -0
  108. package/dist/utils/index.d.ts.map +1 -1
  109. package/dist/utils/index.js +7 -0
  110. package/ios/AGENTS.md +14 -3
  111. package/ios/CLAUDE.md +25 -3
  112. package/ios/Plugin/FilesystemStorage.swift +19 -0
  113. package/ios/Plugin/SQLiteStorage.swift +59 -9
  114. package/ios/Plugin/StrataStoragePlugin.m +1 -0
  115. package/ios/Plugin/StrataStoragePlugin.swift +87 -34
  116. package/ios/Plugin/UserDefaultsStorage.swift +47 -46
  117. package/package.json +27 -24
  118. package/scripts/build.js +46 -27
  119. package/scripts/cli.js +1 -1
  120. package/scripts/configure.js +2 -2
  121. package/scripts/postinstall.js +3 -2
  122. package/dist/android/AGENTS.md +0 -51
  123. package/dist/android/CLAUDE.md +0 -89
  124. package/dist/android/build.gradle +0 -58
  125. package/dist/android/proguard-rules.pro +0 -11
  126. package/dist/android/settings.gradle +0 -2
  127. package/dist/android/src/main/AndroidManifest.xml +0 -2
  128. package/dist/android/src/main/java/com/strata/storage/EncryptedStorage.java +0 -218
  129. package/dist/android/src/main/java/com/strata/storage/FilesystemStorage.java +0 -287
  130. package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +0 -371
  131. package/dist/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +0 -209
  132. package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +0 -616
  133. package/dist/core/StorageStrategy.d.ts +0 -55
  134. package/dist/core/StorageStrategy.d.ts.map +0 -1
  135. package/dist/core/StorageStrategy.js +0 -200
  136. package/dist/ios/AGENTS.md +0 -48
  137. package/dist/ios/CLAUDE.md +0 -84
  138. package/dist/ios/Plugin/FilesystemStorage.swift +0 -218
  139. package/dist/ios/Plugin/KeychainStorage.swift +0 -233
  140. package/dist/ios/Plugin/SQLiteStorage.swift +0 -426
  141. package/dist/ios/Plugin/StrataStoragePlugin.m +0 -23
  142. package/dist/ios/Plugin/StrataStoragePlugin.swift +0 -411
  143. 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.json());
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
- const response = new Response(JSON.stringify(value), {
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
- const oldValue = await this.get(key);
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 '@/core/BaseAdapter';
6
- import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo } from '@/types';
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;AAIjB;;;;;;;;;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;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;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;IAiCjB;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACH,OAAO,CAAC,aAAa;CAmBtB"}
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 = JSON.parse(decoded);
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 = JSON.stringify(value);
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 '@/core/BaseAdapter';
6
- import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo, QueryCondition, Transaction } from '@/types';
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;IAsBxC;;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;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC;IAQzC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B;;OAEG;IACH,OAAO,CAAC,YAAY;CAMrB"}
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
- const oldValue = await this.get(key);
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 '@/core/BaseAdapter';
6
- import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, SizeInfo, SubscriptionCallback, UnsubscribeFunction } from '@/types';
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;IAS7B;;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"}
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
- const oldValue = this.getSync(key);
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 '@/core/BaseAdapter';
6
- import type { StorageType, StorageCapabilities, StorageValue, ClearOptions, QueryCondition } from '@/types';
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 deep clone to prevent external modifications
59
- return deepClone(value);
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 deep clone to prevent external modifications
87
- const clonedValue = deepClone(value);
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: deepClone(item.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 './LocalStorageAdapter';
6
- import type { StorageType, StorageCapabilities } from '@/types';
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('@/types').StorageValue<T> | null>;
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('@/types').StorageValue<T> | null;
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('@/types').StorageValue<T>): Promise<void>;
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('@/types').StorageValue<T>): void;
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('@/types').ClearOptions): Promise<void>;
50
+ clear(options?: import("../../types/index.js").ClearOptions): Promise<void>;
51
51
  /**
52
52
  * Clear sessionStorage (synchronous)
53
53
  */
54
- clearSync(options?: import('@/types').ClearOptions): void;
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('@/types').SizeInfo>;
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('@/types').SubscriptionCallback): import('@/types').UnsubscribeFunction;
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;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"}
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 = JSON.parse(item);
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 = JSON.stringify(value);
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
- const oldValue = this.getSync(key);
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 '@/core/BaseAdapter';
16
- import type { StorageType, StorageCapabilities, StorageValue, ClearOptions } from '@/types';
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 './MemoryAdapter';
5
- export { LocalStorageAdapter } from './LocalStorageAdapter';
6
- export { SessionStorageAdapter } from './SessionStorageAdapter';
7
- export { IndexedDBAdapter } from './IndexedDBAdapter';
8
- export { CookieAdapter } from './CookieAdapter';
9
- export { CacheAdapter } from './CacheAdapter';
10
- export { URLAdapter, type URLAdapterConfig } from './URLAdapter';
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
@@ -1,9 +1,9 @@
1
- import type { Strata } from './core/Strata';
2
- export { PreferencesAdapter } from './adapters/capacitor/PreferencesAdapter';
3
- export { SqliteAdapter } from './adapters/capacitor/SqliteAdapter';
4
- export { SecureAdapter } from './adapters/capacitor/SecureAdapter';
5
- export { FilesystemAdapter } from './adapters/capacitor/FilesystemAdapter';
6
- export { StrataStorage } from './plugin';
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
@@ -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,CAwB9E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAShD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAEnD"}
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
- // Re-initialize to make new adapters available
32
- if (storage.isInitialized) {
33
- await storage.initialize();
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,7 +1,7 @@
1
1
  /**
2
2
  * Registry for managing storage adapters
3
3
  */
4
- import type { StorageAdapter, StorageType } from '@/types';
4
+ import type { StorageAdapter, StorageType } from "../types/index.js";
5
5
  /**
6
6
  * Adapter registry for managing storage adapters
7
7
  */
@@ -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 '@/types';
5
- import { EventEmitter } from '@/utils';
6
- import { QueryEngine } from '@/features/query';
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
- protected cleanupExpired(): Promise<void>;
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
  */