hyperstorage-js 6.0.6 → 6.0.8

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/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## Description
8
8
 
9
- A lightweight wrapper for Storage interfaces (e.g., `localStorage` or `sessionStorage`) with **efficient caching** and **type-preserving serialization**.
9
+ A lightweight wrapper for Storage APIs (e.g., `localStorage` or `sessionStorage`) with **efficient caching** and **type-preserving serialization**.
10
10
 
11
11
  The biggest burdens of working with the **Storage API** is verifying values on every read, providing proper default values and only being able to store strings, having to `JSON.stringify()` and `JSON.parse()` manually everytime. This package eliminates this all by providing a safe, automatic and efficient wrapper that handles everything for you. You can read/store numbers and objects without any extra steps, lose no performance and improve code readability.
12
12
 
@@ -44,7 +44,7 @@ The biggest burdens of working with the **Storage API** is verifying values on e
44
44
 
45
45
  ```bash
46
46
  # npm
47
- npm install hyperstorage-js
47
+ npm i hyperstorage-js
48
48
 
49
49
  # pnpm
50
50
  pnpm add hyperstorage-js
@@ -101,10 +101,10 @@ The default method that works for all use cases is the `value` setter.
101
101
  store.value = 'anything'
102
102
  ```
103
103
 
104
- The [`set()` (click)](#setkeyorcallback-keyof-t--value-t--t-value-tkeyof-t-t) method is a handy wrapper for assigning and can be used as shown in the examples below, which are sorted from best to worst practice.
104
+ The [`set()`](#setkeyorcallback-keyof-t--value-t--t-value-tkeyof-t-t) method is a handy wrapper for assigning and can be used as shown in the examples below, which are sorted from best to worst practice.
105
105
 
106
106
  <details>
107
- <summary><strong>Object: Change Only One Property</strong></summary>
107
+ <summary><strong>Object: Change Single Property</strong></summary>
108
108
 
109
109
  ```js
110
110
  // Property setter
@@ -140,18 +140,18 @@ numberStore.value = numberStore.value + 2
140
140
  Use `sessionStorage` to only remember data for the duration of a session.
141
141
 
142
142
  ```js
143
- const sessionStore = new HyperStorage('sessionData', 'none', {
143
+ const sessionStore = new HyperStorage('session', 'none', {
144
144
  storage: window.sessionStorage,
145
145
  })
146
146
 
147
147
  sessionStore.value = 'temporary'
148
148
  console.log(sessionStore.value) // 'temporary'
149
- console.log(sessionStore.storage) // Storage {sessionData: '{"json":"temporary"}', length: 1}
149
+ console.log(sessionStore.storage) // Storage {session: '{"json":"temporary"}', length: 1}
150
150
  ```
151
151
 
152
- ### Using Encoding and Decoding Functions
152
+ ### Using the Encoding and Decoding Functions
153
153
 
154
- If you want to make stored data harder to reverse-engineer, use the `encodeFn` and `decodeFn` options.
154
+ If you want to make stored data harder to reverse-engineer or change the parser, use the `encodeFn` and `decodeFn` options.
155
155
 
156
156
  The default values for `encodeFn` and `decodeFn` are:
157
157
 
@@ -163,17 +163,17 @@ decodeFn = (value) => HyperStorage.superjson.parse(value)
163
163
  <details>
164
164
  <summary><strong>Base64 Example</strong></summary>
165
165
 
166
- Apply Base64 encoding using JavaScript's `btoa` (String to Base64) and `atob` (Base64 to String).
166
+ Apply Base64 encoding on top of superjson using JavaScript's `btoa` (String to Base64) and `atob` (Base64 to String) functions.
167
167
 
168
168
  ```js
169
- const sessionStore = new HyperStorage('sessionData', 'none', {
170
- encodeFn: (value) => btoa(value),
171
- decodeFn: (value) => atob(value),
169
+ const sessionStore = new HyperStorage('session', 'none', {
170
+ encodeFn: (value) => btoa(HyperStorage.superjson.stringify(value)),
171
+ decodeFn: (value) => HyperStorage.superjson.parse(atob(value)),
172
172
  })
173
173
 
174
174
  sessionStore.value = 'temporary'
175
175
  console.log(sessionStore.value) // 'temporary'
176
- console.log(sessionStore.storage) // Storage  {sessionData: 'dGVtcG9yYXJ5', length: 1}
176
+ console.log(sessionStore.storage) // Storage  {session: 'eyJqc29uIjoidGVtcG9yYXJ5In0=', length: 1}
177
177
  ```
178
178
 
179
179
  </details>
@@ -201,10 +201,10 @@ interface Settings {
201
201
  }
202
202
 
203
203
  const defaultValue: Settings = { theme: 'system', language: 'en' }
204
- const userStore = new HyperStorage<Settings>('userSettings', defaultValue)
204
+ const settingsStore = new HyperStorage<Settings>('userSettings', defaultValue)
205
205
 
206
206
  // Property 'language' is missing in type '{ theme: "dark"; }' but required in type 'Settings'. ts(2741)
207
- userStore.value = { theme: 'dark' }
207
+ settingsStore.value = { theme: 'dark' }
208
208
  ```
209
209
 
210
210
  ### Using `sync()`
@@ -214,14 +214,14 @@ Safe usage of `sync()` requires explicit runtime validation before accessing any
214
214
  ```ts
215
215
  // ... continues from the above example
216
216
 
217
- const result = userStore.sync() // (method): unknown
218
- // Right now, 'result' equals 'userStore.value' exactly
217
+ const result = settingsStore.sync() // (method): unknown
218
+ // Right now, 'result' equals 'settingsStore.value' exactly
219
219
 
220
220
  // 'result' is of type 'unknown'. ts(18046)
221
221
  console.log(result.theme) // 'dark'
222
222
 
223
223
  // No error, but unsafe
224
- console.log(userStore.value.theme) // 'dark'
224
+ console.log(settingsStore.value.theme) // 'dark'
225
225
 
226
226
  // Must narrow down to be safe
227
227
  if (result && typeof result === 'object' && 'theme' in result) {
@@ -234,22 +234,24 @@ if (result && typeof result === 'object' && 'theme' in result) {
234
234
 
235
235
  ## Supported Types in Storage
236
236
 
237
- | Type | Supported by Storage API | Supported by HyperStorage (trough superjson) |
238
- | --------- | ------------------------ | -------------------------------------------- |
239
- | string | | |
240
- | undefined | | |
241
- | null | | ✅ |
242
- | boolean | ❌ | ✅ |
243
- | number | ❌ | ✅ |
244
- | bigint | ❌ | ✅ |
245
- | Object | ❌ | ✅ |
246
- | Array | ❌ | ✅ |
247
- | Set | ❌ | ✅ |
248
- | Map | ❌ | ✅ |
249
- | URL | ❌ | ✅ |
250
- | Date | ❌ | ✅ |
251
- | RegExp | ❌ | ✅ |
252
- | Error | ❌ | ✅ |
237
+ Types supported by HyperStorage is based on what superjson supports.
238
+
239
+ | Type | Supported by Storage API | Supported by HyperStorage |
240
+ | --------- | ------------------------ | ------------------------- |
241
+ | string | | ✅ |
242
+ | undefined | ❌ | ✅ |
243
+ | null | ❌ | ✅ |
244
+ | boolean | ❌ | ✅ |
245
+ | number | ❌ | ✅ |
246
+ | bigint | ❌ | ✅ |
247
+ | Object | ❌ | ✅ |
248
+ | Array | ❌ | ✅ |
249
+ | Set | ❌ | ✅ |
250
+ | Map | ❌ | ✅ |
251
+ | URL | ❌ | ✅ |
252
+ | Date | ❌ | ✅ |
253
+ | RegExp | ❌ | ✅ |
254
+ | Error | ❌ | ✅ |
253
255
 
254
256
  <br>
255
257
 
@@ -288,7 +290,7 @@ if (result && typeof result === 'object' && 'theme' in result) {
288
290
  - Returns `true` if the current value matches the default, otherwise `false`.
289
291
 
290
292
  ```js
291
- if (userStore.isDefault()) {
293
+ if (settingsStore.isDefault()) {
292
294
  console.log('value equals the default value.')
293
295
  }
294
296
  ```
@@ -307,13 +309,13 @@ The return type is `unknown` because data read from `Storage` cannot be type-che
307
309
 
308
310
  ```js
309
311
  // External change to storage (to be avoided)
310
- localStorage.setItem('userSettings', '{"theme":"dark"}')
312
+ localStorage.setItem('settings', '{"theme":"dark"}')
311
313
 
312
314
  // Resynchronize the cache, optionally with a custom decoder
313
- userStore.sync((value) => JSON.parse(value))
315
+ settingsStore.sync((value) => JSON.parse(value))
314
316
 
315
- console.log(userStore.value) // { theme: 'dark' }
316
- console.log(userStore.storage) // Storage {userSettings: '{"json":{"theme":"dark"}}', length: 1}
317
+ console.log(settingsStore.value) // { theme: 'dark' }
318
+ console.log(settingsStore.storage) // Storage {settings: '{"json":{"theme":"dark"}}', length: 1}
317
319
  ```
318
320
 
319
321
  <br>
@@ -324,31 +326,31 @@ console.log(userStore.storage) // Storage {userSettings: '{"json":{"theme":"dark
324
326
  1. The item in `Storage` is undecodable by the `decodeFn` passed to `sync()`.
325
327
 
326
328
  ```js
327
- localStorage.setItem('userSettings', 'not an object')
329
+ localStorage.setItem('settings', 'not an object')
328
330
 
329
331
  // SyntaxError: Unexpected token 'o', "not an object" is not valid JSON
330
- const result = userStore.sync((value) => JSON.parse(value))
332
+ const result = settingsStore.sync((value) => JSON.parse(value))
331
333
  // Execution continues because sync() uses a try-catch
332
334
 
333
335
  console.log(result) // instance of SyntaxError
334
336
 
335
337
  // Reset to default value
336
- console.log(userStore.value) // {theme: 'system', language: 'en'}
338
+ console.log(settingsStore.value) // {theme: 'system', language: 'en'}
337
339
  ```
338
340
 
339
341
  2. The item in `Storage`, after being decoded, is not of type `T`.
340
342
 
341
343
  ```js
342
- localStorage.setItem('userSettings', '{"not":"valid"}')
344
+ localStorage.setItem('settings', '{"not":"valid"}')
343
345
 
344
- const result = userStore.sync((value) => JSON.parse(value))
346
+ const result = settingsStore.sync((value) => JSON.parse(value))
345
347
  console.log(result) // {not: 'valid'}
346
- console.log(userStore.value) // {not: 'valid'}
348
+ console.log(settingsStore.value) // {not: 'valid'}
347
349
  ```
348
350
 
349
- No errors, but `result` and `userStore.value` are both not of type `T`.
351
+ No errors, but `result` and `settingsStore.value` are both not of type `T`.
350
352
 
351
- This **must** be manually checked and `userStore.reset()` should be called if the check fails.
353
+ This **must** be manually checked and `settingsStore.reset()` should be called if the check fails.
352
354
 
353
355
  ```js
354
356
  // This example is specifically for type 'Settings'
@@ -363,11 +365,11 @@ if (
363
365
  // 'result' is of type 'T'
364
366
  } else {
365
367
  // 'result' is not of type 'T'
366
- userStore.reset()
367
- console.log(userStore.value) // {theme: 'system', language: 'en'}
368
+ settingsStore.reset()
369
+ console.log(settingsStore.value) // {theme: 'system', language: 'en'}
368
370
  }
369
371
 
370
- // 'userStore.value' is of type 'T'
372
+ // 'settingsStore.value' is of type 'T'
371
373
  ```
372
374
 
373
375
  </details>
package/dist/index.cjs CHANGED
@@ -867,7 +867,7 @@ SuperJSON.allowErrorProps;
867
867
  */
868
868
  class HyperStorage {
869
869
  /** Version of the library, injected via Rollup replace plugin. */
870
- static version = "6.0.6";
870
+ static version = "6.0.8";
871
871
  static superjson = SuperJSON;
872
872
  /** Key name under which the data is stored. */
873
873
  itemName;
@@ -935,10 +935,10 @@ class HyperStorage {
935
935
  });
936
936
  }
937
937
  /**
938
- * Synchronizes the internal cache (`#value`) with the actual value in storage.
938
+ * Synchronizes the cached value of this wrapper with the value in storage.
939
939
  *
940
- * This is only necessary if the stored value may have been modified externally.
941
- * Using this function should be avoided when possible and is not type safe.
940
+ * This is only necessary if the stored value may have been modified without using the setter of this class.
941
+ * Using this function is not type safe.
942
942
  */
943
943
  sync(decodeFn = this.#decodeFn) {
944
944
  const json = this.storage.getItem(this.itemName);
@@ -957,13 +957,15 @@ class HyperStorage {
957
957
  }
958
958
  /**
959
959
  * Resets the stored value to its configured default.
960
+ *
960
961
  * Updates both the underlying storage and the internal cache.
961
962
  */
962
963
  reset() {
963
964
  return (this.value = this.defaultValue);
964
965
  }
965
966
  /**
966
- * Checks whether the current cached value matches the configured default value.
967
+ * Checks whether the current value matches the configured default value.
968
+ *
967
969
  * Uses reference comparison for objects and strict equality for primitives.
968
970
  */
969
971
  isDefault() {
package/dist/index.d.ts CHANGED
@@ -51,19 +51,21 @@ declare class HyperStorage<T> {
51
51
  set<K extends keyof T>(key: K, value: T[K]): T;
52
52
  set(callback: (value: T) => T): T;
53
53
  /**
54
- * Synchronizes the internal cache (`#value`) with the actual value in storage.
54
+ * Synchronizes the cached value of this wrapper with the value in storage.
55
55
  *
56
- * This is only necessary if the stored value may have been modified externally.
57
- * Using this function should be avoided when possible and is not type safe.
56
+ * This is only necessary if the stored value may have been modified without using the setter of this class.
57
+ * Using this function is not type safe.
58
58
  */
59
59
  sync(decodeFn?: (value: string) => T): unknown;
60
60
  /**
61
61
  * Resets the stored value to its configured default.
62
+ *
62
63
  * Updates both the underlying storage and the internal cache.
63
64
  */
64
65
  reset(): T;
65
66
  /**
66
- * Checks whether the current cached value matches the configured default value.
67
+ * Checks whether the current value matches the configured default value.
68
+ *
67
69
  * Uses reference comparison for objects and strict equality for primitives.
68
70
  */
69
71
  isDefault(): boolean;
package/dist/index.mjs CHANGED
@@ -865,7 +865,7 @@ SuperJSON.allowErrorProps;
865
865
  */
866
866
  class HyperStorage {
867
867
  /** Version of the library, injected via Rollup replace plugin. */
868
- static version = "6.0.6";
868
+ static version = "6.0.8";
869
869
  static superjson = SuperJSON;
870
870
  /** Key name under which the data is stored. */
871
871
  itemName;
@@ -933,10 +933,10 @@ class HyperStorage {
933
933
  });
934
934
  }
935
935
  /**
936
- * Synchronizes the internal cache (`#value`) with the actual value in storage.
936
+ * Synchronizes the cached value of this wrapper with the value in storage.
937
937
  *
938
- * This is only necessary if the stored value may have been modified externally.
939
- * Using this function should be avoided when possible and is not type safe.
938
+ * This is only necessary if the stored value may have been modified without using the setter of this class.
939
+ * Using this function is not type safe.
940
940
  */
941
941
  sync(decodeFn = this.#decodeFn) {
942
942
  const json = this.storage.getItem(this.itemName);
@@ -955,13 +955,15 @@ class HyperStorage {
955
955
  }
956
956
  /**
957
957
  * Resets the stored value to its configured default.
958
+ *
958
959
  * Updates both the underlying storage and the internal cache.
959
960
  */
960
961
  reset() {
961
962
  return (this.value = this.defaultValue);
962
963
  }
963
964
  /**
964
- * Checks whether the current cached value matches the configured default value.
965
+ * Checks whether the current value matches the configured default value.
966
+ *
965
967
  * Uses reference comparison for objects and strict equality for primitives.
966
968
  */
967
969
  isDefault() {
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).HyperStorage=t()}(this,function(){"use strict";class DoubleIndexedKV{constructor(){this.keyToValue=new Map,this.valueToKey=new Map}set(e,t){this.keyToValue.set(e,t),this.valueToKey.set(t,e)}getByKey(e){return this.keyToValue.get(e)}getByValue(e){return this.valueToKey.get(e)}clear(){this.keyToValue.clear(),this.valueToKey.clear()}}class Registry{constructor(e){this.generateIdentifier=e,this.kv=new DoubleIndexedKV}register(e,t){this.kv.getByValue(e)||(t||(t=this.generateIdentifier(e)),this.kv.set(t,e))}clear(){this.kv.clear()}getIdentifier(e){return this.kv.getByValue(e)}getValue(e){return this.kv.getByKey(e)}}class ClassRegistry extends Registry{constructor(){super(e=>e.name),this.classToAllowedProps=new Map}register(e,t){"object"==typeof t?(t.allowProps&&this.classToAllowedProps.set(e,t.allowProps),super.register(e,t.identifier)):super.register(e,t)}getAllowedProps(e){return this.classToAllowedProps.get(e)}}function e(e,t){const r=function(e){if("values"in Object)return Object.values(e);const t=[];for(const r in e)e.hasOwnProperty(r)&&t.push(e[r]);return t}(e);if("find"in r)return r.find(t);const n=r;for(let e=0;e<n.length;e++){const r=n[e];if(t(r))return r}}function t(e,t){Object.entries(e).forEach(([e,r])=>t(r,e))}function r(e,t){return-1!==e.indexOf(t)}function n(e,t){for(let r=0;r<e.length;r++){const n=e[r];if(t(n))return n}}class CustomTransformerRegistry{constructor(){this.transfomers={}}register(e){this.transfomers[e.name]=e}findApplicable(t){return e(this.transfomers,e=>e.isApplicable(t))}findByName(e){return this.transfomers[e]}}const s=e=>void 0===e,o=e=>"object"==typeof e&&null!==e&&(e!==Object.prototype&&(null===Object.getPrototypeOf(e)||Object.getPrototypeOf(e)===Object.prototype)),i=e=>o(e)&&0===Object.keys(e).length,a=e=>Array.isArray(e),u=e=>e instanceof Map,l=e=>e instanceof Set,c=e=>"Symbol"===(e=>Object.prototype.toString.call(e).slice(8,-1))(e),f=e=>e instanceof Error,p=e=>"number"==typeof e&&isNaN(e),d=e=>(e=>"boolean"==typeof e)(e)||(e=>null===e)(e)||s(e)||(e=>"number"==typeof e&&!isNaN(e))(e)||(e=>"string"==typeof e)(e)||c(e),y=e=>e.replace(/\\/g,"\\\\").replace(/\./g,"\\."),g=e=>e.map(String).map(y).join("."),m=(e,t)=>{const r=[];let n="";for(let s=0;s<e.length;s++){let o=e.charAt(s);if(!t&&"\\"===o){const t=e.charAt(s+1);if("\\"===t){n+="\\",s++;continue}if("."!==t)throw Error("invalid path")}if("\\"===o&&"."===e.charAt(s+1)){n+=".",s++;continue}"."===o?(r.push(n),n=""):n+=o}const s=n;return r.push(s),r};function h(e,t,r,n){return{isApplicable:e,annotation:t,transform:r,untransform:n}}const S=[h(s,"undefined",()=>null,()=>{}),h(e=>"bigint"==typeof e,"bigint",e=>e.toString(),e=>"undefined"!=typeof BigInt?BigInt(e):(console.error("Please add a BigInt polyfill."),e)),h(e=>e instanceof Date&&!isNaN(e.valueOf()),"Date",e=>e.toISOString(),e=>new Date(e)),h(f,"Error",(e,t)=>{const r={name:e.name,message:e.message};return"cause"in e&&(r.cause=e.cause),t.allowedErrorProps.forEach(t=>{r[t]=e[t]}),r},(e,t)=>{const r=new Error(e.message,{cause:e.cause});return r.name=e.name,r.stack=e.stack,t.allowedErrorProps.forEach(t=>{r[t]=e[t]}),r}),h(e=>e instanceof RegExp,"regexp",e=>""+e,e=>{const t=e.slice(1,e.lastIndexOf("/")),r=e.slice(e.lastIndexOf("/")+1);return new RegExp(t,r)}),h(l,"set",e=>[...e.values()],e=>new Set(e)),h(u,"map",e=>[...e.entries()],e=>new Map(e)),h(e=>{return p(e)||((t=e)===1/0||t===-1/0);var t},"number",e=>p(e)?"NaN":e>0?"Infinity":"-Infinity",Number),h(e=>0===e&&1/e==-1/0,"number",()=>"-0",Number),h(e=>e instanceof URL,"URL",e=>e.toString(),e=>new URL(e))];function b(e,t,r,n){return{isApplicable:e,annotation:t,transform:r,untransform:n}}const w=b((e,t)=>{if(c(e)){return!!t.symbolRegistry.getIdentifier(e)}return!1},(e,t)=>["symbol",t.symbolRegistry.getIdentifier(e)],e=>e.description,(e,t,r)=>{const n=r.symbolRegistry.getValue(t[1]);if(!n)throw new Error("Trying to deserialize unknown symbol");return n}),O=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,Uint8ClampedArray].reduce((e,t)=>(e[t.name]=t,e),{}),N=b(e=>ArrayBuffer.isView(e)&&!(e instanceof DataView),e=>["typed-array",e.constructor.name],e=>[...e],(e,t)=>{const r=O[t[1]];if(!r)throw new Error("Trying to deserialize unknown typed array");return new r(e)});function v(e,t){if(e?.constructor){return!!t.classRegistry.getIdentifier(e.constructor)}return!1}const E=b(v,(e,t)=>["class",t.classRegistry.getIdentifier(e.constructor)],(e,t)=>{const r=t.classRegistry.getAllowedProps(e.constructor);if(!r)return{...e};const n={};return r.forEach(t=>{n[t]=e[t]}),n},(e,t,r)=>{const n=r.classRegistry.getValue(t[1]);if(!n)throw new Error(`Trying to deserialize unknown class '${t[1]}' - check https://github.com/blitz-js/superjson/issues/116#issuecomment-773996564`);return Object.assign(Object.create(n.prototype),e)}),I=b((e,t)=>!!t.customTransformerRegistry.findApplicable(e),(e,t)=>["custom",t.customTransformerRegistry.findApplicable(e).name],(e,t)=>t.customTransformerRegistry.findApplicable(e).serialize(e),(e,t,r)=>{const n=r.customTransformerRegistry.findByName(t[1]);if(!n)throw new Error("Trying to deserialize unknown custom value");return n.deserialize(e)}),J=[E,w,I,N],k=(e,t)=>{const r=n(J,r=>r.isApplicable(e,t));if(r)return{value:r.transform(e,t),type:r.annotation(e,t)};const s=n(S,r=>r.isApplicable(e,t));return s?{value:s.transform(e,t),type:s.annotation}:void 0},j={};S.forEach(e=>{j[e.annotation]=e});const A=(e,t)=>{if(t>e.size)throw new Error("index out of bounds");const r=e.keys();for(;t>0;)r.next(),t--;return r.next().value};function T(e){if(r(e,"__proto__"))throw new Error("__proto__ is not allowed as a property");if(r(e,"prototype"))throw new Error("prototype is not allowed as a property");if(r(e,"constructor"))throw new Error("constructor is not allowed as a property")}const R=(e,t,r)=>{if(T(t),0===t.length)return r(e);let n=e;for(let e=0;e<t.length-1;e++){const r=t[e];if(a(n)){n=n[+r]}else if(o(n))n=n[r];else if(l(n)){n=A(n,+r)}else if(u(n)){if(e===t.length-2)break;const s=+r,o=0===+t[++e]?"key":"value",i=A(n,s);switch(o){case"key":n=i;break;case"value":n=n.get(i)}}}const s=t[t.length-1];if(a(n)?n[+s]=r(n[+s]):o(n)&&(n[s]=r(n[s])),l(n)){const e=A(n,+s),t=r(e);e!==t&&(n.delete(e),n.add(t))}if(u(n)){const e=+t[t.length-2],o=A(n,e);switch(0===+s?"key":"value"){case"key":{const e=r(o);n.set(e,n.get(o)),e!==o&&n.delete(o);break}case"value":n.set(o,r(n.get(o)))}}return e},V=e=>e<1;function P(e,r,n,s=[]){if(!e)return;const o=V(n);if(!a(e))return void t(e,(e,t)=>P(e,r,n,[...s,...m(t,o)]));const[i,u]=e;u&&t(u,(e,t)=>{P(e,r,n,[...s,...m(t,o)])}),r(i,s)}function z(e,t,r,n){return P(t,(t,r)=>{e=R(e,r,e=>((e,t,r)=>{if(!a(t)){const n=j[t];if(!n)throw new Error("Unknown transformation: "+t);return n.untransform(e,r)}switch(t[0]){case"symbol":return w.untransform(e,t,r);case"class":return E.untransform(e,t,r);case"custom":return I.untransform(e,t,r);case"typed-array":return N.untransform(e,t,r);default:throw new Error("Unknown transformation: "+t)}})(e,t,n))},r),e}function _(e,r,n){const s=V(n);function o(t,r){const n=((e,t)=>{T(t);for(let r=0;r<t.length;r++){const n=t[r];if(l(e))e=A(e,+n);else if(u(e)){const s=+n,o=0===+t[++r]?"key":"value",i=A(e,s);switch(o){case"key":e=i;break;case"value":e=e.get(i)}}else e=e[n]}return e})(e,m(r,s));t.map(e=>m(e,s)).forEach(t=>{e=R(e,t,()=>n)})}if(a(r)){const[n,i]=r;n.forEach(t=>{e=R(e,m(t,s),()=>e)}),i&&t(i,o)}else t(r,o);return e}const x=(e,n,s,c,p=[],g=[],m=new Map)=>{const h=d(e);if(!h){!function(e,t,r){const n=r.get(e);n?n.push(t):r.set(e,[t])}(e,p,n);const t=m.get(e);if(t)return c?{transformedValue:null}:t}if(!((e,t)=>o(e)||a(e)||u(e)||l(e)||f(e)||v(e,t))(e,s)){const t=k(e,s),r=t?{transformedValue:t.value,annotations:[t.type]}:{transformedValue:e};return h||m.set(e,r),r}if(r(g,e))return{transformedValue:null};const S=k(e,s),b=S?.value??e,w=a(b)?[]:{},O={};t(b,(r,i)=>{if("__proto__"===i||"constructor"===i||"prototype"===i)throw new Error(`Detected property ${i}. This is a prototype pollution risk, please remove it from your object.`);const u=x(r,n,s,c,[...p,i],[...g,e],m);w[i]=u.transformedValue,a(u.annotations)?O[y(i)]=u.annotations:o(u.annotations)&&t(u.annotations,(e,t)=>{O[y(i)+"."+t]=e})});const N=i(O)?{transformedValue:w,annotations:S?[S.type]:void 0}:{transformedValue:w,annotations:S?[S.type,O]:O};return h||m.set(e,N),N};function C(e){return Object.prototype.toString.call(e).slice(8,-1)}function F(e){return"Array"===C(e)}function B(e,t={}){if(F(e))return e.map(e=>B(e,t));if(!function(e){if("Object"!==C(e))return!1;const t=Object.getPrototypeOf(e);return!!t&&t.constructor===Object&&t===Object.prototype}(e))return e;return[...Object.getOwnPropertyNames(e),...Object.getOwnPropertySymbols(e)].reduce((r,n)=>{if("__proto__"===n)return r;if(F(t.props)&&!t.props.includes(n))return r;return function(e,t,r,n,s){const o={}.propertyIsEnumerable.call(n,t)?"enumerable":"nonenumerable";"enumerable"===o&&(e[t]=r),s&&"nonenumerable"===o&&Object.defineProperty(e,t,{value:r,enumerable:!1,writable:!0,configurable:!0})}(r,n,B(e[n],t),e,t.nonenumerable),r},{})}class SuperJSON{constructor({dedupe:e=!1}={}){this.classRegistry=new ClassRegistry,this.symbolRegistry=new Registry(e=>e.description??""),this.customTransformerRegistry=new CustomTransformerRegistry,this.allowedErrorProps=[],this.dedupe=e}serialize(e){const t=new Map,r=x(e,t,this,this.dedupe),n={json:r.transformedValue};r.annotations&&(n.meta={...n.meta,values:r.annotations});const s=function(e,t){const r={};let n;return e.forEach(e=>{if(e.length<=1)return;t||(e=e.map(e=>e.map(String)).sort((e,t)=>e.length-t.length));const[s,...o]=e;0===s.length?n=o.map(g):r[g(s)]=o.map(g)}),n?i(r)?[n]:[n,r]:i(r)?void 0:r}(t,this.dedupe);return s&&(n.meta={...n.meta,referentialEqualities:s}),n.meta&&(n.meta.v=1),n}deserialize(e,t){const{json:r,meta:n}=e;let s=t?.inPlace?r:B(r);return n?.values&&(s=z(s,n.values,n.v??0,this)),n?.referentialEqualities&&(s=_(s,n.referentialEqualities,n.v??0)),s}stringify(e){return JSON.stringify(this.serialize(e))}parse(e){return this.deserialize(JSON.parse(e),{inPlace:!0})}registerClass(e,t){this.classRegistry.register(e,t)}registerSymbol(e,t){this.symbolRegistry.register(e,t)}registerCustom(e,t){this.customTransformerRegistry.register({name:t,...e})}allowErrorProps(...e){this.allowedErrorProps.push(...e)}}SuperJSON.defaultInstance=new SuperJSON,SuperJSON.serialize=SuperJSON.defaultInstance.serialize.bind(SuperJSON.defaultInstance),SuperJSON.deserialize=SuperJSON.defaultInstance.deserialize.bind(SuperJSON.defaultInstance),SuperJSON.stringify=SuperJSON.defaultInstance.stringify.bind(SuperJSON.defaultInstance),SuperJSON.parse=SuperJSON.defaultInstance.parse.bind(SuperJSON.defaultInstance),SuperJSON.registerClass=SuperJSON.defaultInstance.registerClass.bind(SuperJSON.defaultInstance),SuperJSON.registerSymbol=SuperJSON.defaultInstance.registerSymbol.bind(SuperJSON.defaultInstance),SuperJSON.registerCustom=SuperJSON.defaultInstance.registerCustom.bind(SuperJSON.defaultInstance),SuperJSON.allowErrorProps=SuperJSON.defaultInstance.allowErrorProps.bind(SuperJSON.defaultInstance),SuperJSON.serialize,SuperJSON.deserialize,SuperJSON.stringify,SuperJSON.parse,SuperJSON.registerClass,SuperJSON.registerCustom,SuperJSON.registerSymbol,SuperJSON.allowErrorProps;class HyperStorage{static version="6.0.6";static superjson=SuperJSON;itemName;defaultValue;#e;#t;storage;#r;constructor(e,t,r={}){const{encodeFn:n,decodeFn:s,storage:o=window.localStorage}=r;if("string"!=typeof e)throw new TypeError("itemName is not a string");if(this.itemName=e,this.defaultValue=t,n&&"function"!=typeof n)throw new TypeError("encodeFn is defined but is not a function");if(this.#e=n||(e=>HyperStorage.superjson.stringify(e)),s&&"function"!=typeof s)throw new TypeError("decodeFn is defined but is not a function");if(this.#t=s||(e=>HyperStorage.superjson.parse(e)),!(o instanceof Storage))throw new TypeError("storage must be an instance of Storage");this.storage=o,this.sync()}set value(e){this.#r=e,this.storage.setItem(this.itemName,this.#e(e))}get value(){return this.#r}set(e,t){return this.value="function"==typeof e?e(this.#r):{...this.#r,[e]:t}}sync(e=this.#t){const t=this.storage.getItem(this.itemName);if(null===t)return this.reset();try{return this.value=e(t)}catch(e){return console.error(e),this.reset(),e}}reset(){return this.value=this.defaultValue}isDefault(){return this.#r===this.defaultValue}}return HyperStorage});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).HyperStorage=t()}(this,function(){"use strict";class DoubleIndexedKV{constructor(){this.keyToValue=new Map,this.valueToKey=new Map}set(e,t){this.keyToValue.set(e,t),this.valueToKey.set(t,e)}getByKey(e){return this.keyToValue.get(e)}getByValue(e){return this.valueToKey.get(e)}clear(){this.keyToValue.clear(),this.valueToKey.clear()}}class Registry{constructor(e){this.generateIdentifier=e,this.kv=new DoubleIndexedKV}register(e,t){this.kv.getByValue(e)||(t||(t=this.generateIdentifier(e)),this.kv.set(t,e))}clear(){this.kv.clear()}getIdentifier(e){return this.kv.getByValue(e)}getValue(e){return this.kv.getByKey(e)}}class ClassRegistry extends Registry{constructor(){super(e=>e.name),this.classToAllowedProps=new Map}register(e,t){"object"==typeof t?(t.allowProps&&this.classToAllowedProps.set(e,t.allowProps),super.register(e,t.identifier)):super.register(e,t)}getAllowedProps(e){return this.classToAllowedProps.get(e)}}function e(e,t){const r=function(e){if("values"in Object)return Object.values(e);const t=[];for(const r in e)e.hasOwnProperty(r)&&t.push(e[r]);return t}(e);if("find"in r)return r.find(t);const n=r;for(let e=0;e<n.length;e++){const r=n[e];if(t(r))return r}}function t(e,t){Object.entries(e).forEach(([e,r])=>t(r,e))}function r(e,t){return-1!==e.indexOf(t)}function n(e,t){for(let r=0;r<e.length;r++){const n=e[r];if(t(n))return n}}class CustomTransformerRegistry{constructor(){this.transfomers={}}register(e){this.transfomers[e.name]=e}findApplicable(t){return e(this.transfomers,e=>e.isApplicable(t))}findByName(e){return this.transfomers[e]}}const s=e=>void 0===e,o=e=>"object"==typeof e&&null!==e&&(e!==Object.prototype&&(null===Object.getPrototypeOf(e)||Object.getPrototypeOf(e)===Object.prototype)),i=e=>o(e)&&0===Object.keys(e).length,a=e=>Array.isArray(e),u=e=>e instanceof Map,l=e=>e instanceof Set,c=e=>"Symbol"===(e=>Object.prototype.toString.call(e).slice(8,-1))(e),f=e=>e instanceof Error,p=e=>"number"==typeof e&&isNaN(e),d=e=>(e=>"boolean"==typeof e)(e)||(e=>null===e)(e)||s(e)||(e=>"number"==typeof e&&!isNaN(e))(e)||(e=>"string"==typeof e)(e)||c(e),y=e=>e.replace(/\\/g,"\\\\").replace(/\./g,"\\."),g=e=>e.map(String).map(y).join("."),m=(e,t)=>{const r=[];let n="";for(let s=0;s<e.length;s++){let o=e.charAt(s);if(!t&&"\\"===o){const t=e.charAt(s+1);if("\\"===t){n+="\\",s++;continue}if("."!==t)throw Error("invalid path")}if("\\"===o&&"."===e.charAt(s+1)){n+=".",s++;continue}"."===o?(r.push(n),n=""):n+=o}const s=n;return r.push(s),r};function h(e,t,r,n){return{isApplicable:e,annotation:t,transform:r,untransform:n}}const S=[h(s,"undefined",()=>null,()=>{}),h(e=>"bigint"==typeof e,"bigint",e=>e.toString(),e=>"undefined"!=typeof BigInt?BigInt(e):(console.error("Please add a BigInt polyfill."),e)),h(e=>e instanceof Date&&!isNaN(e.valueOf()),"Date",e=>e.toISOString(),e=>new Date(e)),h(f,"Error",(e,t)=>{const r={name:e.name,message:e.message};return"cause"in e&&(r.cause=e.cause),t.allowedErrorProps.forEach(t=>{r[t]=e[t]}),r},(e,t)=>{const r=new Error(e.message,{cause:e.cause});return r.name=e.name,r.stack=e.stack,t.allowedErrorProps.forEach(t=>{r[t]=e[t]}),r}),h(e=>e instanceof RegExp,"regexp",e=>""+e,e=>{const t=e.slice(1,e.lastIndexOf("/")),r=e.slice(e.lastIndexOf("/")+1);return new RegExp(t,r)}),h(l,"set",e=>[...e.values()],e=>new Set(e)),h(u,"map",e=>[...e.entries()],e=>new Map(e)),h(e=>{return p(e)||((t=e)===1/0||t===-1/0);var t},"number",e=>p(e)?"NaN":e>0?"Infinity":"-Infinity",Number),h(e=>0===e&&1/e==-1/0,"number",()=>"-0",Number),h(e=>e instanceof URL,"URL",e=>e.toString(),e=>new URL(e))];function b(e,t,r,n){return{isApplicable:e,annotation:t,transform:r,untransform:n}}const w=b((e,t)=>{if(c(e)){return!!t.symbolRegistry.getIdentifier(e)}return!1},(e,t)=>["symbol",t.symbolRegistry.getIdentifier(e)],e=>e.description,(e,t,r)=>{const n=r.symbolRegistry.getValue(t[1]);if(!n)throw new Error("Trying to deserialize unknown symbol");return n}),O=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,Uint8ClampedArray].reduce((e,t)=>(e[t.name]=t,e),{}),N=b(e=>ArrayBuffer.isView(e)&&!(e instanceof DataView),e=>["typed-array",e.constructor.name],e=>[...e],(e,t)=>{const r=O[t[1]];if(!r)throw new Error("Trying to deserialize unknown typed array");return new r(e)});function v(e,t){if(e?.constructor){return!!t.classRegistry.getIdentifier(e.constructor)}return!1}const E=b(v,(e,t)=>["class",t.classRegistry.getIdentifier(e.constructor)],(e,t)=>{const r=t.classRegistry.getAllowedProps(e.constructor);if(!r)return{...e};const n={};return r.forEach(t=>{n[t]=e[t]}),n},(e,t,r)=>{const n=r.classRegistry.getValue(t[1]);if(!n)throw new Error(`Trying to deserialize unknown class '${t[1]}' - check https://github.com/blitz-js/superjson/issues/116#issuecomment-773996564`);return Object.assign(Object.create(n.prototype),e)}),I=b((e,t)=>!!t.customTransformerRegistry.findApplicable(e),(e,t)=>["custom",t.customTransformerRegistry.findApplicable(e).name],(e,t)=>t.customTransformerRegistry.findApplicable(e).serialize(e),(e,t,r)=>{const n=r.customTransformerRegistry.findByName(t[1]);if(!n)throw new Error("Trying to deserialize unknown custom value");return n.deserialize(e)}),J=[E,w,I,N],k=(e,t)=>{const r=n(J,r=>r.isApplicable(e,t));if(r)return{value:r.transform(e,t),type:r.annotation(e,t)};const s=n(S,r=>r.isApplicable(e,t));return s?{value:s.transform(e,t),type:s.annotation}:void 0},j={};S.forEach(e=>{j[e.annotation]=e});const A=(e,t)=>{if(t>e.size)throw new Error("index out of bounds");const r=e.keys();for(;t>0;)r.next(),t--;return r.next().value};function T(e){if(r(e,"__proto__"))throw new Error("__proto__ is not allowed as a property");if(r(e,"prototype"))throw new Error("prototype is not allowed as a property");if(r(e,"constructor"))throw new Error("constructor is not allowed as a property")}const R=(e,t,r)=>{if(T(t),0===t.length)return r(e);let n=e;for(let e=0;e<t.length-1;e++){const r=t[e];if(a(n)){n=n[+r]}else if(o(n))n=n[r];else if(l(n)){n=A(n,+r)}else if(u(n)){if(e===t.length-2)break;const s=+r,o=0===+t[++e]?"key":"value",i=A(n,s);switch(o){case"key":n=i;break;case"value":n=n.get(i)}}}const s=t[t.length-1];if(a(n)?n[+s]=r(n[+s]):o(n)&&(n[s]=r(n[s])),l(n)){const e=A(n,+s),t=r(e);e!==t&&(n.delete(e),n.add(t))}if(u(n)){const e=+t[t.length-2],o=A(n,e);switch(0===+s?"key":"value"){case"key":{const e=r(o);n.set(e,n.get(o)),e!==o&&n.delete(o);break}case"value":n.set(o,r(n.get(o)))}}return e},V=e=>e<1;function P(e,r,n,s=[]){if(!e)return;const o=V(n);if(!a(e))return void t(e,(e,t)=>P(e,r,n,[...s,...m(t,o)]));const[i,u]=e;u&&t(u,(e,t)=>{P(e,r,n,[...s,...m(t,o)])}),r(i,s)}function z(e,t,r,n){return P(t,(t,r)=>{e=R(e,r,e=>((e,t,r)=>{if(!a(t)){const n=j[t];if(!n)throw new Error("Unknown transformation: "+t);return n.untransform(e,r)}switch(t[0]){case"symbol":return w.untransform(e,t,r);case"class":return E.untransform(e,t,r);case"custom":return I.untransform(e,t,r);case"typed-array":return N.untransform(e,t,r);default:throw new Error("Unknown transformation: "+t)}})(e,t,n))},r),e}function _(e,r,n){const s=V(n);function o(t,r){const n=((e,t)=>{T(t);for(let r=0;r<t.length;r++){const n=t[r];if(l(e))e=A(e,+n);else if(u(e)){const s=+n,o=0===+t[++r]?"key":"value",i=A(e,s);switch(o){case"key":e=i;break;case"value":e=e.get(i)}}else e=e[n]}return e})(e,m(r,s));t.map(e=>m(e,s)).forEach(t=>{e=R(e,t,()=>n)})}if(a(r)){const[n,i]=r;n.forEach(t=>{e=R(e,m(t,s),()=>e)}),i&&t(i,o)}else t(r,o);return e}const x=(e,n,s,c,p=[],g=[],m=new Map)=>{const h=d(e);if(!h){!function(e,t,r){const n=r.get(e);n?n.push(t):r.set(e,[t])}(e,p,n);const t=m.get(e);if(t)return c?{transformedValue:null}:t}if(!((e,t)=>o(e)||a(e)||u(e)||l(e)||f(e)||v(e,t))(e,s)){const t=k(e,s),r=t?{transformedValue:t.value,annotations:[t.type]}:{transformedValue:e};return h||m.set(e,r),r}if(r(g,e))return{transformedValue:null};const S=k(e,s),b=S?.value??e,w=a(b)?[]:{},O={};t(b,(r,i)=>{if("__proto__"===i||"constructor"===i||"prototype"===i)throw new Error(`Detected property ${i}. This is a prototype pollution risk, please remove it from your object.`);const u=x(r,n,s,c,[...p,i],[...g,e],m);w[i]=u.transformedValue,a(u.annotations)?O[y(i)]=u.annotations:o(u.annotations)&&t(u.annotations,(e,t)=>{O[y(i)+"."+t]=e})});const N=i(O)?{transformedValue:w,annotations:S?[S.type]:void 0}:{transformedValue:w,annotations:S?[S.type,O]:O};return h||m.set(e,N),N};function C(e){return Object.prototype.toString.call(e).slice(8,-1)}function F(e){return"Array"===C(e)}function B(e,t={}){if(F(e))return e.map(e=>B(e,t));if(!function(e){if("Object"!==C(e))return!1;const t=Object.getPrototypeOf(e);return!!t&&t.constructor===Object&&t===Object.prototype}(e))return e;return[...Object.getOwnPropertyNames(e),...Object.getOwnPropertySymbols(e)].reduce((r,n)=>{if("__proto__"===n)return r;if(F(t.props)&&!t.props.includes(n))return r;return function(e,t,r,n,s){const o={}.propertyIsEnumerable.call(n,t)?"enumerable":"nonenumerable";"enumerable"===o&&(e[t]=r),s&&"nonenumerable"===o&&Object.defineProperty(e,t,{value:r,enumerable:!1,writable:!0,configurable:!0})}(r,n,B(e[n],t),e,t.nonenumerable),r},{})}class SuperJSON{constructor({dedupe:e=!1}={}){this.classRegistry=new ClassRegistry,this.symbolRegistry=new Registry(e=>e.description??""),this.customTransformerRegistry=new CustomTransformerRegistry,this.allowedErrorProps=[],this.dedupe=e}serialize(e){const t=new Map,r=x(e,t,this,this.dedupe),n={json:r.transformedValue};r.annotations&&(n.meta={...n.meta,values:r.annotations});const s=function(e,t){const r={};let n;return e.forEach(e=>{if(e.length<=1)return;t||(e=e.map(e=>e.map(String)).sort((e,t)=>e.length-t.length));const[s,...o]=e;0===s.length?n=o.map(g):r[g(s)]=o.map(g)}),n?i(r)?[n]:[n,r]:i(r)?void 0:r}(t,this.dedupe);return s&&(n.meta={...n.meta,referentialEqualities:s}),n.meta&&(n.meta.v=1),n}deserialize(e,t){const{json:r,meta:n}=e;let s=t?.inPlace?r:B(r);return n?.values&&(s=z(s,n.values,n.v??0,this)),n?.referentialEqualities&&(s=_(s,n.referentialEqualities,n.v??0)),s}stringify(e){return JSON.stringify(this.serialize(e))}parse(e){return this.deserialize(JSON.parse(e),{inPlace:!0})}registerClass(e,t){this.classRegistry.register(e,t)}registerSymbol(e,t){this.symbolRegistry.register(e,t)}registerCustom(e,t){this.customTransformerRegistry.register({name:t,...e})}allowErrorProps(...e){this.allowedErrorProps.push(...e)}}SuperJSON.defaultInstance=new SuperJSON,SuperJSON.serialize=SuperJSON.defaultInstance.serialize.bind(SuperJSON.defaultInstance),SuperJSON.deserialize=SuperJSON.defaultInstance.deserialize.bind(SuperJSON.defaultInstance),SuperJSON.stringify=SuperJSON.defaultInstance.stringify.bind(SuperJSON.defaultInstance),SuperJSON.parse=SuperJSON.defaultInstance.parse.bind(SuperJSON.defaultInstance),SuperJSON.registerClass=SuperJSON.defaultInstance.registerClass.bind(SuperJSON.defaultInstance),SuperJSON.registerSymbol=SuperJSON.defaultInstance.registerSymbol.bind(SuperJSON.defaultInstance),SuperJSON.registerCustom=SuperJSON.defaultInstance.registerCustom.bind(SuperJSON.defaultInstance),SuperJSON.allowErrorProps=SuperJSON.defaultInstance.allowErrorProps.bind(SuperJSON.defaultInstance),SuperJSON.serialize,SuperJSON.deserialize,SuperJSON.stringify,SuperJSON.parse,SuperJSON.registerClass,SuperJSON.registerCustom,SuperJSON.registerSymbol,SuperJSON.allowErrorProps;class HyperStorage{static version="6.0.8";static superjson=SuperJSON;itemName;defaultValue;#e;#t;storage;#r;constructor(e,t,r={}){const{encodeFn:n,decodeFn:s,storage:o=window.localStorage}=r;if("string"!=typeof e)throw new TypeError("itemName is not a string");if(this.itemName=e,this.defaultValue=t,n&&"function"!=typeof n)throw new TypeError("encodeFn is defined but is not a function");if(this.#e=n||(e=>HyperStorage.superjson.stringify(e)),s&&"function"!=typeof s)throw new TypeError("decodeFn is defined but is not a function");if(this.#t=s||(e=>HyperStorage.superjson.parse(e)),!(o instanceof Storage))throw new TypeError("storage must be an instance of Storage");this.storage=o,this.sync()}set value(e){this.#r=e,this.storage.setItem(this.itemName,this.#e(e))}get value(){return this.#r}set(e,t){return this.value="function"==typeof e?e(this.#r):{...this.#r,[e]:t}}sync(e=this.#t){const t=this.storage.getItem(this.itemName);if(null===t)return this.reset();try{return this.value=e(t)}catch(e){return console.error(e),this.reset(),e}}reset(){return this.value=this.defaultValue}isDefault(){return this.#r===this.defaultValue}}return HyperStorage});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperstorage-js",
3
- "version": "6.0.6",
3
+ "version": "6.0.8",
4
4
  "description": "A lightweight wrapper for localStorage/sessionStorage with efficient caching and type-preserving serialization.",
5
5
  "license": "MIT",
6
6
  "author": "Khoeckman",
@@ -34,14 +34,9 @@
34
34
  "@rollup/plugin-replace": "^6.0.3",
35
35
  "@rollup/plugin-terser": "^1.0.0",
36
36
  "@rollup/plugin-typescript": "^12.3.0",
37
- "@types/node": "^25.3.5",
38
- "pnpm": "^10.30.3",
39
37
  "prettier": "^3.8.1",
40
38
  "rollup": "^4.59.0",
41
- "rollup-plugin-delete": "^3.0.2",
42
- "rollup-plugin-prettier": "^4.1.2",
43
- "tslib": "^2.8.1",
44
- "typescript": "^5.9.3"
39
+ "rollup-plugin-delete": "^3.0.2"
45
40
  },
46
41
  "publishConfig": {
47
42
  "access": "public"
package/src/index.ts CHANGED
@@ -12,15 +12,15 @@ declare const __VERSION__: string
12
12
  */
13
13
  class HyperStorage<T> {
14
14
  /** Version of the library, injected via Rollup replace plugin. */
15
- public static readonly version: string = __VERSION__
15
+ static readonly version = __VERSION__
16
16
 
17
- public static readonly superjson = superjson
17
+ static readonly superjson = superjson
18
18
 
19
19
  /** Key name under which the data is stored. */
20
- public readonly itemName: string
20
+ readonly itemName: string
21
21
 
22
22
  /** Default value used when the key does not exist in storage. */
23
- public readonly defaultValue: T
23
+ readonly defaultValue: T
24
24
 
25
25
  /** Function to encode values before storing. */
26
26
  readonly #encodeFn: (value: T) => string
@@ -29,7 +29,7 @@ class HyperStorage<T> {
29
29
  readonly #decodeFn: (value: string) => T
30
30
 
31
31
  /** The underlying storage backend (defaults to `window.localStorage`). */
32
- public readonly storage: Storage
32
+ readonly storage: Storage
33
33
 
34
34
  /** Internal cached value to improve access speed. */
35
35
  #value!: T
@@ -107,10 +107,10 @@ class HyperStorage<T> {
107
107
  }
108
108
 
109
109
  /**
110
- * Synchronizes the internal cache (`#value`) with the actual value in storage.
110
+ * Synchronizes the cached value of this wrapper with the value in storage.
111
111
  *
112
- * This is only necessary if the stored value may have been modified externally.
113
- * Using this function should be avoided when possible and is not type safe.
112
+ * This is only necessary if the stored value may have been modified without using the setter of this class.
113
+ * Using this function is not type safe.
114
114
  */
115
115
  sync(decodeFn = this.#decodeFn): unknown {
116
116
  const json = this.storage.getItem(this.itemName)
@@ -130,6 +130,7 @@ class HyperStorage<T> {
130
130
 
131
131
  /**
132
132
  * Resets the stored value to its configured default.
133
+ *
133
134
  * Updates both the underlying storage and the internal cache.
134
135
  */
135
136
  reset(): T {
@@ -137,7 +138,8 @@ class HyperStorage<T> {
137
138
  }
138
139
 
139
140
  /**
140
- * Checks whether the current cached value matches the configured default value.
141
+ * Checks whether the current value matches the configured default value.
142
+ *
141
143
  * Uses reference comparison for objects and strict equality for primitives.
142
144
  */
143
145
  isDefault(): boolean {