hyperstorage-js 6.0.3 → 6.0.5
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 +21 -19
- package/dist/index.cjs +10 -10
- package/dist/index.d.ts +1 -5
- package/dist/index.mjs +10 -10
- package/dist/index.umd.js +1 -1
- package/package.json +1 -1
- package/src/index.ts +14 -14
package/README.md
CHANGED
|
@@ -20,25 +20,6 @@ The biggest burdens of working with the **Storage API** is verifying values on e
|
|
|
20
20
|
- 🛠️ **Utility helpers**: use `.set()` and `.isDefault()` to simplify storage operations.
|
|
21
21
|
- 🌐 **Custom storage**: works with any object implementing the standard Storage API. (`localStorage`, `sessionStorage`, ...)
|
|
22
22
|
|
|
23
|
-
### Supported Types
|
|
24
|
-
|
|
25
|
-
| Type | Supported by Storage API | Supported by HyperStorage (trough superjson) |
|
|
26
|
-
| --------- | ------------------------ | -------------------------------------------- |
|
|
27
|
-
| string | ✅ | ✅ |
|
|
28
|
-
| number | ❌ | ✅ |
|
|
29
|
-
| boolean | ❌ | ✅ |
|
|
30
|
-
| null | ❌ | ✅ |
|
|
31
|
-
| Array | ❌ | ✅ |
|
|
32
|
-
| Object | ❌ | ✅ |
|
|
33
|
-
| undefined | ❌ | ✅ |
|
|
34
|
-
| bigint | ❌ | ✅ |
|
|
35
|
-
| Date | ❌ | ✅ |
|
|
36
|
-
| RegExp | ❌ | ✅ |
|
|
37
|
-
| Set | ❌ | ✅ |
|
|
38
|
-
| Map | ❌ | ✅ |
|
|
39
|
-
| Error | ❌ | ✅ |
|
|
40
|
-
| URL | ❌ | ✅ |
|
|
41
|
-
|
|
42
23
|
<br>
|
|
43
24
|
|
|
44
25
|
## Installation
|
|
@@ -205,6 +186,27 @@ if (result && typeof result === 'object' && 'theme' in result) {
|
|
|
205
186
|
|
|
206
187
|
<br>
|
|
207
188
|
|
|
189
|
+
## Supported Types in Storage
|
|
190
|
+
|
|
191
|
+
| Type | Supported by Storage API | Supported by HyperStorage (trough superjson) |
|
|
192
|
+
| --------- | ------------------------ | -------------------------------------------- |
|
|
193
|
+
| string | ✅ | ✅ |
|
|
194
|
+
| undefined | ❌ | ✅ |
|
|
195
|
+
| null | ❌ | ✅ |
|
|
196
|
+
| boolean | ❌ | ✅ |
|
|
197
|
+
| number | ❌ | ✅ |
|
|
198
|
+
| bigint | ❌ | ✅ |
|
|
199
|
+
| Object | ❌ | ✅ |
|
|
200
|
+
| Array | ❌ | ✅ |
|
|
201
|
+
| Set | ❌ | ✅ |
|
|
202
|
+
| Map | ❌ | ✅ |
|
|
203
|
+
| URL | ❌ | ✅ |
|
|
204
|
+
| Date | ❌ | ✅ |
|
|
205
|
+
| RegExp | ❌ | ✅ |
|
|
206
|
+
| Error | ❌ | ✅ |
|
|
207
|
+
|
|
208
|
+
<br>
|
|
209
|
+
|
|
208
210
|
## API
|
|
209
211
|
|
|
210
212
|
### `constructor<T>(itemName: string, defaultValue: T, options = {})`
|
package/dist/index.cjs
CHANGED
|
@@ -867,16 +867,16 @@ 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.5";
|
|
871
871
|
static superjson = SuperJSON;
|
|
872
872
|
/** Key name under which the data is stored. */
|
|
873
873
|
itemName;
|
|
874
874
|
/** Default value used when the key does not exist in storage. */
|
|
875
875
|
defaultValue;
|
|
876
876
|
/** Function to encode values before storing. */
|
|
877
|
-
encodeFn;
|
|
877
|
+
#encodeFn;
|
|
878
878
|
/** Function to decode values when reading. */
|
|
879
|
-
decodeFn;
|
|
879
|
+
#decodeFn;
|
|
880
880
|
/** The underlying storage backend (defaults to `window.localStorage`). */
|
|
881
881
|
storage;
|
|
882
882
|
/** Internal cached value to improve access speed. */
|
|
@@ -903,10 +903,10 @@ class HyperStorage {
|
|
|
903
903
|
this.defaultValue = defaultValue;
|
|
904
904
|
if (encodeFn && typeof encodeFn !== 'function')
|
|
905
905
|
throw new TypeError('encodeFn is defined but is not a function');
|
|
906
|
-
this
|
|
906
|
+
this.#encodeFn = encodeFn || ((v) => HyperStorage.superjson.stringify(v));
|
|
907
907
|
if (decodeFn && typeof decodeFn !== 'function')
|
|
908
908
|
throw new TypeError('decodeFn is defined but is not a function');
|
|
909
|
-
this
|
|
909
|
+
this.#decodeFn = decodeFn || ((v) => HyperStorage.superjson.parse(v));
|
|
910
910
|
if (!(storage instanceof Storage))
|
|
911
911
|
throw new TypeError('storage must be an instance of Storage');
|
|
912
912
|
this.storage = storage;
|
|
@@ -918,7 +918,7 @@ class HyperStorage {
|
|
|
918
918
|
*/
|
|
919
919
|
set value(value) {
|
|
920
920
|
this.#value = value; // Cache real value
|
|
921
|
-
this.storage.setItem(this.itemName, this
|
|
921
|
+
this.storage.setItem(this.itemName, this.#encodeFn(value));
|
|
922
922
|
}
|
|
923
923
|
/**
|
|
924
924
|
* Gets the current cached value.
|
|
@@ -940,16 +940,16 @@ class HyperStorage {
|
|
|
940
940
|
* This is only necessary if the stored value may have been modified externally.
|
|
941
941
|
* Using this function should be avoided when possible and is not type safe.
|
|
942
942
|
*/
|
|
943
|
-
sync(decodeFn = this
|
|
944
|
-
|
|
943
|
+
sync(decodeFn = this.#decodeFn) {
|
|
944
|
+
const json = this.storage.getItem(this.itemName);
|
|
945
945
|
// Reset value to defaultValue if it does not exist in storage
|
|
946
|
-
if (
|
|
946
|
+
if (json === null)
|
|
947
947
|
return this.reset();
|
|
948
|
-
// Reset value to defaultValue if the incoming value is not properly encoded
|
|
949
948
|
try {
|
|
950
949
|
return (this.value = decodeFn(json));
|
|
951
950
|
}
|
|
952
951
|
catch (err) {
|
|
952
|
+
// Reset value to defaultValue if the incoming value is not properly encoded
|
|
953
953
|
console.error(err);
|
|
954
954
|
this.reset();
|
|
955
955
|
return err;
|
package/dist/index.d.ts
CHANGED
|
@@ -14,11 +14,7 @@ declare class HyperStorage<T> {
|
|
|
14
14
|
/** Key name under which the data is stored. */
|
|
15
15
|
readonly itemName: string;
|
|
16
16
|
/** Default value used when the key does not exist in storage. */
|
|
17
|
-
|
|
18
|
-
/** Function to encode values before storing. */
|
|
19
|
-
private readonly encodeFn;
|
|
20
|
-
/** Function to decode values when reading. */
|
|
21
|
-
private readonly decodeFn;
|
|
17
|
+
readonly defaultValue: T;
|
|
22
18
|
/** The underlying storage backend (defaults to `window.localStorage`). */
|
|
23
19
|
readonly storage: Storage;
|
|
24
20
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -865,16 +865,16 @@ 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.5";
|
|
869
869
|
static superjson = SuperJSON;
|
|
870
870
|
/** Key name under which the data is stored. */
|
|
871
871
|
itemName;
|
|
872
872
|
/** Default value used when the key does not exist in storage. */
|
|
873
873
|
defaultValue;
|
|
874
874
|
/** Function to encode values before storing. */
|
|
875
|
-
encodeFn;
|
|
875
|
+
#encodeFn;
|
|
876
876
|
/** Function to decode values when reading. */
|
|
877
|
-
decodeFn;
|
|
877
|
+
#decodeFn;
|
|
878
878
|
/** The underlying storage backend (defaults to `window.localStorage`). */
|
|
879
879
|
storage;
|
|
880
880
|
/** Internal cached value to improve access speed. */
|
|
@@ -901,10 +901,10 @@ class HyperStorage {
|
|
|
901
901
|
this.defaultValue = defaultValue;
|
|
902
902
|
if (encodeFn && typeof encodeFn !== 'function')
|
|
903
903
|
throw new TypeError('encodeFn is defined but is not a function');
|
|
904
|
-
this
|
|
904
|
+
this.#encodeFn = encodeFn || ((v) => HyperStorage.superjson.stringify(v));
|
|
905
905
|
if (decodeFn && typeof decodeFn !== 'function')
|
|
906
906
|
throw new TypeError('decodeFn is defined but is not a function');
|
|
907
|
-
this
|
|
907
|
+
this.#decodeFn = decodeFn || ((v) => HyperStorage.superjson.parse(v));
|
|
908
908
|
if (!(storage instanceof Storage))
|
|
909
909
|
throw new TypeError('storage must be an instance of Storage');
|
|
910
910
|
this.storage = storage;
|
|
@@ -916,7 +916,7 @@ class HyperStorage {
|
|
|
916
916
|
*/
|
|
917
917
|
set value(value) {
|
|
918
918
|
this.#value = value; // Cache real value
|
|
919
|
-
this.storage.setItem(this.itemName, this
|
|
919
|
+
this.storage.setItem(this.itemName, this.#encodeFn(value));
|
|
920
920
|
}
|
|
921
921
|
/**
|
|
922
922
|
* Gets the current cached value.
|
|
@@ -938,16 +938,16 @@ class HyperStorage {
|
|
|
938
938
|
* This is only necessary if the stored value may have been modified externally.
|
|
939
939
|
* Using this function should be avoided when possible and is not type safe.
|
|
940
940
|
*/
|
|
941
|
-
sync(decodeFn = this
|
|
942
|
-
|
|
941
|
+
sync(decodeFn = this.#decodeFn) {
|
|
942
|
+
const json = this.storage.getItem(this.itemName);
|
|
943
943
|
// Reset value to defaultValue if it does not exist in storage
|
|
944
|
-
if (
|
|
944
|
+
if (json === null)
|
|
945
945
|
return this.reset();
|
|
946
|
-
// Reset value to defaultValue if the incoming value is not properly encoded
|
|
947
946
|
try {
|
|
948
947
|
return (this.value = decodeFn(json));
|
|
949
948
|
}
|
|
950
949
|
catch (err) {
|
|
950
|
+
// Reset value to defaultValue if the incoming value is not properly encoded
|
|
951
951
|
console.error(err);
|
|
952
952
|
this.reset();
|
|
953
953
|
return err;
|
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 e{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 t{constructor(t){this.generateIdentifier=t,this.kv=new e}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 r extends t{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 n(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 s(e,t){Object.entries(e).forEach(([e,r])=>t(r,e))}function o(e,t){return-1!==e.indexOf(t)}function i(e,t){for(let r=0;r<e.length;r++){const n=e[r];if(t(n))return n}}class a{constructor(){this.transfomers={}}register(e){this.transfomers[e.name]=e}findApplicable(e){return n(this.transfomers,t=>t.isApplicable(e))}findByName(e){return this.transfomers[e]}}const l=e=>void 0===e,u=e=>"object"==typeof e&&null!==e&&(e!==Object.prototype&&(null===Object.getPrototypeOf(e)||Object.getPrototypeOf(e)===Object.prototype)),c=e=>u(e)&&0===Object.keys(e).length,f=e=>Array.isArray(e),p=e=>e instanceof Map,d=e=>e instanceof Set,y=e=>"Symbol"===(e=>Object.prototype.toString.call(e).slice(8,-1))(e),g=e=>e instanceof Error,m=e=>"number"==typeof e&&isNaN(e),h=e=>(e=>"boolean"==typeof e)(e)||(e=>null===e)(e)||l(e)||(e=>"number"==typeof e&&!isNaN(e))(e)||(e=>"string"==typeof e)(e)||y(e),b=e=>e.replace(/\\/g,"\\\\").replace(/\./g,"\\."),w=e=>e.map(String).map(b).join("."),v=(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 E(e,t,r,n){return{isApplicable:e,annotation:t,transform:r,untransform:n}}const I=[E(l,"undefined",()=>null,()=>{}),E(e=>"bigint"==typeof e,"bigint",e=>e.toString(),e=>"undefined"!=typeof BigInt?BigInt(e):(console.error("Please add a BigInt polyfill."),e)),E(e=>e instanceof Date&&!isNaN(e.valueOf()),"Date",e=>e.toISOString(),e=>new Date(e)),E(g,"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}),E(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)}),E(d,"set",e=>[...e.values()],e=>new Set(e)),E(p,"map",e=>[...e.entries()],e=>new Map(e)),E(e=>{return m(e)||((t=e)===1/0||t===-1/0);var t},"number",e=>m(e)?"NaN":e>0?"Infinity":"-Infinity",Number),E(e=>0===e&&1/e==-1/0,"number",()=>"-0",Number),E(e=>e instanceof URL,"URL",e=>e.toString(),e=>new URL(e))];function k(e,t,r,n){return{isApplicable:e,annotation:t,transform:r,untransform:n}}const O=k((e,t)=>{if(y(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}),j=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,Uint8ClampedArray].reduce((e,t)=>(e[t.name]=t,e),{}),A=k(e=>ArrayBuffer.isView(e)&&!(e instanceof DataView),e=>["typed-array",e.constructor.name],e=>[...e],(e,t)=>{const r=j[t[1]];if(!r)throw new Error("Trying to deserialize unknown typed array");return new r(e)});function T(e,t){if(e?.constructor){return!!t.classRegistry.getIdentifier(e.constructor)}return!1}const P=k(T,(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)}),V=k((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)}),R=[P,O,V,A],S=(e,t)=>{const r=i(R,r=>r.isApplicable(e,t));if(r)return{value:r.transform(e,t),type:r.annotation(e,t)};const n=i(I,r=>r.isApplicable(e,t));return n?{value:n.transform(e,t),type:n.annotation}:void 0},N={};I.forEach(e=>{N[e.annotation]=e});const z=(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 _(e){if(o(e,"__proto__"))throw new Error("__proto__ is not allowed as a property");if(o(e,"prototype"))throw new Error("prototype is not allowed as a property");if(o(e,"constructor"))throw new Error("constructor is not allowed as a property")}const x=(e,t,r)=>{if(_(t),0===t.length)return r(e);let n=e;for(let e=0;e<t.length-1;e++){const r=t[e];if(f(n)){n=n[+r]}else if(u(n))n=n[r];else if(d(n)){n=z(n,+r)}else if(p(n)){if(e===t.length-2)break;const s=+r,o=0===+t[++e]?"key":"value",i=z(n,s);switch(o){case"key":n=i;break;case"value":n=n.get(i)}}}const s=t[t.length-1];if(f(n)?n[+s]=r(n[+s]):u(n)&&(n[s]=r(n[s])),d(n)){const e=z(n,+s),t=r(e);e!==t&&(n.delete(e),n.add(t))}if(p(n)){const e=+t[t.length-2],o=z(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},F=e=>e<1;function B(e,t,r,n=[]){if(!e)return;const o=F(r);if(!f(e))return void s(e,(e,s)=>B(e,t,r,[...n,...v(s,o)]));const[i,a]=e;a&&s(a,(e,s)=>{B(e,t,r,[...n,...v(s,o)])}),t(i,n)}function C(e,t,r,n){return B(t,(t,r)=>{e=x(e,r,e=>((e,t,r)=>{if(!f(t)){const n=N[t];if(!n)throw new Error("Unknown transformation: "+t);return n.untransform(e,r)}switch(t[0]){case"symbol":return O.untransform(e,t,r);case"class":return P.untransform(e,t,r);case"custom":return V.untransform(e,t,r);case"typed-array":return A.untransform(e,t,r);default:throw new Error("Unknown transformation: "+t)}})(e,t,n))},r),e}function U(e,t,r){const n=F(r);function o(t,r){const s=((e,t)=>{_(t);for(let r=0;r<t.length;r++){const n=t[r];if(d(e))e=z(e,+n);else if(p(e)){const s=+n,o=0===+t[++r]?"key":"value",i=z(e,s);switch(o){case"key":e=i;break;case"value":e=e.get(i)}}else e=e[n]}return e})(e,v(r,n));t.map(e=>v(e,n)).forEach(t=>{e=x(e,t,()=>s)})}if(f(t)){const[r,i]=t;r.forEach(t=>{e=x(e,v(t,n),()=>e)}),i&&s(i,o)}else s(t,o);return e}const M=(e,t,r,n,i=[],a=[],l=new Map)=>{const y=h(e);if(!y){!function(e,t,r){const n=r.get(e);n?n.push(t):r.set(e,[t])}(e,i,t);const r=l.get(e);if(r)return n?{transformedValue:null}:r}if(!((e,t)=>u(e)||f(e)||p(e)||d(e)||g(e)||T(e,t))(e,r)){const t=S(e,r),n=t?{transformedValue:t.value,annotations:[t.type]}:{transformedValue:e};return y||l.set(e,n),n}if(o(a,e))return{transformedValue:null};const m=S(e,r),w=m?.value??e,v=f(w)?[]:{},E={};s(w,(o,c)=>{if("__proto__"===c||"constructor"===c||"prototype"===c)throw new Error(`Detected property ${c}. This is a prototype pollution risk, please remove it from your object.`);const p=M(o,t,r,n,[...i,c],[...a,e],l);v[c]=p.transformedValue,f(p.annotations)?E[b(c)]=p.annotations:u(p.annotations)&&s(p.annotations,(e,t)=>{E[b(c)+"."+t]=e})});const I=c(E)?{transformedValue:v,annotations:m?[m.type]:void 0}:{transformedValue:v,annotations:m?[m.type,E]:E};return y||l.set(e,I),I};function D(e){return Object.prototype.toString.call(e).slice(8,-1)}function K(e){return"Array"===D(e)}function q(e,t={}){if(K(e))return e.map(e=>q(e,t));if(!function(e){if("Object"!==D(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(K(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,q(e[n],t),e,t.nonenumerable),r},{})}class L{constructor({dedupe:e=!1}={}){this.classRegistry=new r,this.symbolRegistry=new t(e=>e.description??""),this.customTransformerRegistry=new a,this.allowedErrorProps=[],this.dedupe=e}serialize(e){const t=new Map,r=M(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(w):r[w(s)]=o.map(w)}),n?c(r)?[n]:[n,r]:c(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:q(r);return n?.values&&(s=C(s,n.values,n.v??0,this)),n?.referentialEqualities&&(s=U(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)}}L.defaultInstance=new L,L.serialize=L.defaultInstance.serialize.bind(L.defaultInstance),L.deserialize=L.defaultInstance.deserialize.bind(L.defaultInstance),L.stringify=L.defaultInstance.stringify.bind(L.defaultInstance),L.parse=L.defaultInstance.parse.bind(L.defaultInstance),L.registerClass=L.defaultInstance.registerClass.bind(L.defaultInstance),L.registerSymbol=L.defaultInstance.registerSymbol.bind(L.defaultInstance),L.registerCustom=L.defaultInstance.registerCustom.bind(L.defaultInstance),L.allowErrorProps=L.defaultInstance.allowErrorProps.bind(L.defaultInstance),L.serialize,L.deserialize,L.stringify,L.parse,L.registerClass,L.registerCustom,L.registerSymbol,L.allowErrorProps;class J{static version="6.0.3";static superjson=L;itemName;defaultValue;encodeFn;decodeFn;storage;#e;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.encodeFn=n||(e=>J.superjson.stringify(e)),s&&"function"!=typeof s)throw new TypeError("decodeFn is defined but is not a function");if(this.decodeFn=s||(e=>J.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.#e=e,this.storage.setItem(this.itemName,this.encodeFn(e))}get value(){return this.#e}set(e,t){return this.value="function"==typeof e?e(this.#e):{...this.#e,[e]:t}}sync(e=this.decodeFn){let t=this.storage.getItem(this.itemName);if("string"!=typeof 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.#e===this.defaultValue}}return J});
|
|
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 e{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 t{constructor(t){this.generateIdentifier=t,this.kv=new e}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 r extends t{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 n(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 s(e,t){Object.entries(e).forEach(([e,r])=>t(r,e))}function o(e,t){return-1!==e.indexOf(t)}function i(e,t){for(let r=0;r<e.length;r++){const n=e[r];if(t(n))return n}}class a{constructor(){this.transfomers={}}register(e){this.transfomers[e.name]=e}findApplicable(e){return n(this.transfomers,t=>t.isApplicable(e))}findByName(e){return this.transfomers[e]}}const l=e=>void 0===e,u=e=>"object"==typeof e&&null!==e&&(e!==Object.prototype&&(null===Object.getPrototypeOf(e)||Object.getPrototypeOf(e)===Object.prototype)),c=e=>u(e)&&0===Object.keys(e).length,f=e=>Array.isArray(e),p=e=>e instanceof Map,d=e=>e instanceof Set,y=e=>"Symbol"===(e=>Object.prototype.toString.call(e).slice(8,-1))(e),g=e=>e instanceof Error,m=e=>"number"==typeof e&&isNaN(e),h=e=>(e=>"boolean"==typeof e)(e)||(e=>null===e)(e)||l(e)||(e=>"number"==typeof e&&!isNaN(e))(e)||(e=>"string"==typeof e)(e)||y(e),b=e=>e.replace(/\\/g,"\\\\").replace(/\./g,"\\."),w=e=>e.map(String).map(b).join("."),v=(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 E(e,t,r,n){return{isApplicable:e,annotation:t,transform:r,untransform:n}}const I=[E(l,"undefined",()=>null,()=>{}),E(e=>"bigint"==typeof e,"bigint",e=>e.toString(),e=>"undefined"!=typeof BigInt?BigInt(e):(console.error("Please add a BigInt polyfill."),e)),E(e=>e instanceof Date&&!isNaN(e.valueOf()),"Date",e=>e.toISOString(),e=>new Date(e)),E(g,"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}),E(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)}),E(d,"set",e=>[...e.values()],e=>new Set(e)),E(p,"map",e=>[...e.entries()],e=>new Map(e)),E(e=>{return m(e)||((t=e)===1/0||t===-1/0);var t},"number",e=>m(e)?"NaN":e>0?"Infinity":"-Infinity",Number),E(e=>0===e&&1/e==-1/0,"number",()=>"-0",Number),E(e=>e instanceof URL,"URL",e=>e.toString(),e=>new URL(e))];function k(e,t,r,n){return{isApplicable:e,annotation:t,transform:r,untransform:n}}const O=k((e,t)=>{if(y(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}),j=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,Uint8ClampedArray].reduce((e,t)=>(e[t.name]=t,e),{}),A=k(e=>ArrayBuffer.isView(e)&&!(e instanceof DataView),e=>["typed-array",e.constructor.name],e=>[...e],(e,t)=>{const r=j[t[1]];if(!r)throw new Error("Trying to deserialize unknown typed array");return new r(e)});function T(e,t){if(e?.constructor){return!!t.classRegistry.getIdentifier(e.constructor)}return!1}const P=k(T,(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)}),V=k((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)}),R=[P,O,V,A],S=(e,t)=>{const r=i(R,r=>r.isApplicable(e,t));if(r)return{value:r.transform(e,t),type:r.annotation(e,t)};const n=i(I,r=>r.isApplicable(e,t));return n?{value:n.transform(e,t),type:n.annotation}:void 0},N={};I.forEach(e=>{N[e.annotation]=e});const z=(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 _(e){if(o(e,"__proto__"))throw new Error("__proto__ is not allowed as a property");if(o(e,"prototype"))throw new Error("prototype is not allowed as a property");if(o(e,"constructor"))throw new Error("constructor is not allowed as a property")}const x=(e,t,r)=>{if(_(t),0===t.length)return r(e);let n=e;for(let e=0;e<t.length-1;e++){const r=t[e];if(f(n)){n=n[+r]}else if(u(n))n=n[r];else if(d(n)){n=z(n,+r)}else if(p(n)){if(e===t.length-2)break;const s=+r,o=0===+t[++e]?"key":"value",i=z(n,s);switch(o){case"key":n=i;break;case"value":n=n.get(i)}}}const s=t[t.length-1];if(f(n)?n[+s]=r(n[+s]):u(n)&&(n[s]=r(n[s])),d(n)){const e=z(n,+s),t=r(e);e!==t&&(n.delete(e),n.add(t))}if(p(n)){const e=+t[t.length-2],o=z(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},F=e=>e<1;function B(e,t,r,n=[]){if(!e)return;const o=F(r);if(!f(e))return void s(e,(e,s)=>B(e,t,r,[...n,...v(s,o)]));const[i,a]=e;a&&s(a,(e,s)=>{B(e,t,r,[...n,...v(s,o)])}),t(i,n)}function C(e,t,r,n){return B(t,(t,r)=>{e=x(e,r,e=>((e,t,r)=>{if(!f(t)){const n=N[t];if(!n)throw new Error("Unknown transformation: "+t);return n.untransform(e,r)}switch(t[0]){case"symbol":return O.untransform(e,t,r);case"class":return P.untransform(e,t,r);case"custom":return V.untransform(e,t,r);case"typed-array":return A.untransform(e,t,r);default:throw new Error("Unknown transformation: "+t)}})(e,t,n))},r),e}function U(e,t,r){const n=F(r);function o(t,r){const s=((e,t)=>{_(t);for(let r=0;r<t.length;r++){const n=t[r];if(d(e))e=z(e,+n);else if(p(e)){const s=+n,o=0===+t[++r]?"key":"value",i=z(e,s);switch(o){case"key":e=i;break;case"value":e=e.get(i)}}else e=e[n]}return e})(e,v(r,n));t.map(e=>v(e,n)).forEach(t=>{e=x(e,t,()=>s)})}if(f(t)){const[r,i]=t;r.forEach(t=>{e=x(e,v(t,n),()=>e)}),i&&s(i,o)}else s(t,o);return e}const M=(e,t,r,n,i=[],a=[],l=new Map)=>{const y=h(e);if(!y){!function(e,t,r){const n=r.get(e);n?n.push(t):r.set(e,[t])}(e,i,t);const r=l.get(e);if(r)return n?{transformedValue:null}:r}if(!((e,t)=>u(e)||f(e)||p(e)||d(e)||g(e)||T(e,t))(e,r)){const t=S(e,r),n=t?{transformedValue:t.value,annotations:[t.type]}:{transformedValue:e};return y||l.set(e,n),n}if(o(a,e))return{transformedValue:null};const m=S(e,r),w=m?.value??e,v=f(w)?[]:{},E={};s(w,(o,c)=>{if("__proto__"===c||"constructor"===c||"prototype"===c)throw new Error(`Detected property ${c}. This is a prototype pollution risk, please remove it from your object.`);const p=M(o,t,r,n,[...i,c],[...a,e],l);v[c]=p.transformedValue,f(p.annotations)?E[b(c)]=p.annotations:u(p.annotations)&&s(p.annotations,(e,t)=>{E[b(c)+"."+t]=e})});const I=c(E)?{transformedValue:v,annotations:m?[m.type]:void 0}:{transformedValue:v,annotations:m?[m.type,E]:E};return y||l.set(e,I),I};function D(e){return Object.prototype.toString.call(e).slice(8,-1)}function K(e){return"Array"===D(e)}function q(e,t={}){if(K(e))return e.map(e=>q(e,t));if(!function(e){if("Object"!==D(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(K(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,q(e[n],t),e,t.nonenumerable),r},{})}class L{constructor({dedupe:e=!1}={}){this.classRegistry=new r,this.symbolRegistry=new t(e=>e.description??""),this.customTransformerRegistry=new a,this.allowedErrorProps=[],this.dedupe=e}serialize(e){const t=new Map,r=M(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(w):r[w(s)]=o.map(w)}),n?c(r)?[n]:[n,r]:c(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:q(r);return n?.values&&(s=C(s,n.values,n.v??0,this)),n?.referentialEqualities&&(s=U(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)}}L.defaultInstance=new L,L.serialize=L.defaultInstance.serialize.bind(L.defaultInstance),L.deserialize=L.defaultInstance.deserialize.bind(L.defaultInstance),L.stringify=L.defaultInstance.stringify.bind(L.defaultInstance),L.parse=L.defaultInstance.parse.bind(L.defaultInstance),L.registerClass=L.defaultInstance.registerClass.bind(L.defaultInstance),L.registerSymbol=L.defaultInstance.registerSymbol.bind(L.defaultInstance),L.registerCustom=L.defaultInstance.registerCustom.bind(L.defaultInstance),L.allowErrorProps=L.defaultInstance.allowErrorProps.bind(L.defaultInstance),L.serialize,L.deserialize,L.stringify,L.parse,L.registerClass,L.registerCustom,L.registerSymbol,L.allowErrorProps;class J{static version="6.0.5";static superjson=L;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=>J.superjson.stringify(e)),s&&"function"!=typeof s)throw new TypeError("decodeFn is defined but is not a function");if(this.#t=s||(e=>J.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 J});
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -12,24 +12,24 @@ declare const __VERSION__: string
|
|
|
12
12
|
*/
|
|
13
13
|
class HyperStorage<T> {
|
|
14
14
|
/** Version of the library, injected via Rollup replace plugin. */
|
|
15
|
-
static readonly version: string = __VERSION__
|
|
15
|
+
public static readonly version: string = __VERSION__
|
|
16
16
|
|
|
17
|
-
static readonly superjson = superjson
|
|
17
|
+
public static readonly superjson = superjson
|
|
18
18
|
|
|
19
19
|
/** Key name under which the data is stored. */
|
|
20
|
-
readonly itemName: string
|
|
20
|
+
public readonly itemName: string
|
|
21
21
|
|
|
22
22
|
/** Default value used when the key does not exist in storage. */
|
|
23
|
-
|
|
23
|
+
public readonly defaultValue: T
|
|
24
24
|
|
|
25
25
|
/** Function to encode values before storing. */
|
|
26
|
-
|
|
26
|
+
readonly #encodeFn: (value: T) => string
|
|
27
27
|
|
|
28
28
|
/** Function to decode values when reading. */
|
|
29
|
-
|
|
29
|
+
readonly #decodeFn: (value: string) => T
|
|
30
30
|
|
|
31
31
|
/** The underlying storage backend (defaults to `window.localStorage`). */
|
|
32
|
-
readonly storage: Storage
|
|
32
|
+
public readonly storage: Storage
|
|
33
33
|
|
|
34
34
|
/** Internal cached value to improve access speed. */
|
|
35
35
|
#value!: T
|
|
@@ -65,10 +65,10 @@ class HyperStorage<T> {
|
|
|
65
65
|
this.defaultValue = defaultValue
|
|
66
66
|
|
|
67
67
|
if (encodeFn && typeof encodeFn !== 'function') throw new TypeError('encodeFn is defined but is not a function')
|
|
68
|
-
this
|
|
68
|
+
this.#encodeFn = encodeFn || ((v) => HyperStorage.superjson.stringify(v))
|
|
69
69
|
|
|
70
70
|
if (decodeFn && typeof decodeFn !== 'function') throw new TypeError('decodeFn is defined but is not a function')
|
|
71
|
-
this
|
|
71
|
+
this.#decodeFn = decodeFn || ((v) => HyperStorage.superjson.parse(v))
|
|
72
72
|
|
|
73
73
|
if (!(storage instanceof Storage)) throw new TypeError('storage must be an instance of Storage')
|
|
74
74
|
this.storage = storage
|
|
@@ -82,7 +82,7 @@ class HyperStorage<T> {
|
|
|
82
82
|
*/
|
|
83
83
|
set value(value: T) {
|
|
84
84
|
this.#value = value // Cache real value
|
|
85
|
-
this.storage.setItem(this.itemName, this
|
|
85
|
+
this.storage.setItem(this.itemName, this.#encodeFn(value))
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
/**
|
|
@@ -112,16 +112,16 @@ class HyperStorage<T> {
|
|
|
112
112
|
* This is only necessary if the stored value may have been modified externally.
|
|
113
113
|
* Using this function should be avoided when possible and is not type safe.
|
|
114
114
|
*/
|
|
115
|
-
sync(decodeFn = this
|
|
116
|
-
|
|
115
|
+
sync(decodeFn = this.#decodeFn): unknown {
|
|
116
|
+
const json = this.storage.getItem(this.itemName)
|
|
117
117
|
|
|
118
118
|
// Reset value to defaultValue if it does not exist in storage
|
|
119
|
-
if (
|
|
119
|
+
if (json === null) return this.reset()
|
|
120
120
|
|
|
121
|
-
// Reset value to defaultValue if the incoming value is not properly encoded
|
|
122
121
|
try {
|
|
123
122
|
return (this.value = decodeFn(json))
|
|
124
123
|
} catch (err) {
|
|
124
|
+
// Reset value to defaultValue if the incoming value is not properly encoded
|
|
125
125
|
console.error(err)
|
|
126
126
|
this.reset()
|
|
127
127
|
return err
|