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 +52 -50
- package/dist/index.cjs +7 -5
- package/dist/index.d.ts +6 -4
- package/dist/index.mjs +7 -5
- package/dist/index.umd.js +1 -1
- package/package.json +2 -7
- package/src/index.ts +11 -9
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## Description
|
|
8
8
|
|
|
9
|
-
A lightweight wrapper for Storage
|
|
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
|
|
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()`
|
|
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
|
|
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('
|
|
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 {
|
|
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('
|
|
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 {
|
|
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
|
|
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
|
-
|
|
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 =
|
|
218
|
-
// Right now, 'result' equals '
|
|
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(
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
|
240
|
-
|
|
|
241
|
-
|
|
|
242
|
-
|
|
|
243
|
-
|
|
|
244
|
-
|
|
|
245
|
-
|
|
|
246
|
-
|
|
|
247
|
-
|
|
|
248
|
-
|
|
|
249
|
-
|
|
|
250
|
-
|
|
|
251
|
-
|
|
|
252
|
-
|
|
|
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 (
|
|
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('
|
|
312
|
+
localStorage.setItem('settings', '{"theme":"dark"}')
|
|
311
313
|
|
|
312
314
|
// Resynchronize the cache, optionally with a custom decoder
|
|
313
|
-
|
|
315
|
+
settingsStore.sync((value) => JSON.parse(value))
|
|
314
316
|
|
|
315
|
-
console.log(
|
|
316
|
-
console.log(
|
|
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('
|
|
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 =
|
|
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(
|
|
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('
|
|
344
|
+
localStorage.setItem('settings', '{"not":"valid"}')
|
|
343
345
|
|
|
344
|
-
const result =
|
|
346
|
+
const result = settingsStore.sync((value) => JSON.parse(value))
|
|
345
347
|
console.log(result) // {not: 'valid'}
|
|
346
|
-
console.log(
|
|
348
|
+
console.log(settingsStore.value) // {not: 'valid'}
|
|
347
349
|
```
|
|
348
350
|
|
|
349
|
-
No errors, but `result` and `
|
|
351
|
+
No errors, but `result` and `settingsStore.value` are both not of type `T`.
|
|
350
352
|
|
|
351
|
-
This **must** be manually checked and `
|
|
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
|
-
|
|
367
|
-
console.log(
|
|
368
|
+
settingsStore.reset()
|
|
369
|
+
console.log(settingsStore.value) // {theme: 'system', language: 'en'}
|
|
368
370
|
}
|
|
369
371
|
|
|
370
|
-
// '
|
|
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.
|
|
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
|
|
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
|
|
941
|
-
* Using this function
|
|
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
|
|
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
|
|
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
|
|
57
|
-
* Using this function
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
939
|
-
* Using this function
|
|
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
|
|
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.
|
|
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
|
-
|
|
15
|
+
static readonly version = __VERSION__
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
static readonly superjson = superjson
|
|
18
18
|
|
|
19
19
|
/** Key name under which the data is stored. */
|
|
20
|
-
|
|
20
|
+
readonly itemName: string
|
|
21
21
|
|
|
22
22
|
/** Default value used when the key does not exist in storage. */
|
|
23
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
113
|
-
* Using this function
|
|
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
|
|
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 {
|