@storix-js/persist 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +544 -0
- package/package.json +24 -0
- package/src/index.ts +210 -0
- package/tsconfig.build.json +8 -0
- package/tsconfig.json +4 -0
- package/vite.config.ts +15 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var at=Symbol.for("preact-signals");function G(){if(E>1)E--;else{for(var e,t=!1;A!==void 0;){var o=A;for(A=void 0,Q++;o!==void 0;){var d=o.o;if(o.o=void 0,o.f&=-3,!(8&o.f)&&it(o))try{o.c()}catch(O){t||(e=O,t=!0)}o=d}}if(Q=0,E--,t)throw e}}function L(e){if(E>0)return e();E++;try{return e()}finally{G()}}var l=void 0;function et(e){var t=l;l=void 0;try{return e()}finally{l=t}}var A=void 0,E=0,Q=0,F=0;function nt(e){if(l!==void 0){var t=e.n;if(t===void 0||t.t!==l)return t={i:0,S:e,p:l.s,n:void 0,t:l,e:void 0,x:void 0,r:t},l.s!==void 0&&(l.s.n=t),l.s=t,e.n=t,32&l.f&&e.S(t),t;if(t.i===-1)return t.i=0,t.n!==void 0&&(t.n.p=t.p,t.p!==void 0&&(t.p.n=t.n),t.p=l.s,t.n=void 0,l.s.n=t,l.s=t),t}}function b(e,t){this.v=e,this.i=0,this.n=void 0,this.t=void 0,this.W=t==null?void 0:t.watched,this.Z=t==null?void 0:t.unwatched,this.name=t==null?void 0:t.name}b.prototype.brand=at;b.prototype.h=function(){return!0};b.prototype.S=function(e){var t=this,o=this.t;o!==e&&e.e===void 0&&(e.x=o,this.t=e,o!==void 0?o.e=e:et(function(){var d;(d=t.W)==null||d.call(t)}))};b.prototype.U=function(e){var t=this;if(this.t!==void 0){var o=e.e,d=e.x;o!==void 0&&(o.x=d,e.e=void 0),d!==void 0&&(d.e=o,e.x=void 0),e===this.t&&(this.t=d,d===void 0&&et(function(){var O;(O=t.Z)==null||O.call(t)}))}};b.prototype.subscribe=function(e){var t=this;return ut(function(){var o=t.value,d=l;l=void 0;try{e(o)}finally{l=d}},{name:"sub"})};b.prototype.valueOf=function(){return this.value};b.prototype.toString=function(){return this.value+""};b.prototype.toJSON=function(){return this.value};b.prototype.peek=function(){var e=l;l=void 0;try{return this.value}finally{l=e}};Object.defineProperty(b.prototype,"value",{get:function(){var e=nt(this);return e!==void 0&&(e.i=this.i),this.v},set:function(e){if(e!==this.v){if(Q>100)throw new Error("Cycle detected");this.v=e,this.i++,F++,E++;try{for(var t=this.t;t!==void 0;t=t.x)t.t.N()}finally{G()}}}});function ct(e,t){return new b(e,t)}function it(e){for(var t=e.s;t!==void 0;t=t.n)if(t.S.i!==t.i||!t.S.h()||t.S.i!==t.i)return!0;return!1}function ot(e){for(var t=e.s;t!==void 0;t=t.n){var o=t.S.n;if(o!==void 0&&(t.r=o),t.S.n=t,t.i=-1,t.n===void 0){e.s=t;break}}}function rt(e){for(var t=e.s,o=void 0;t!==void 0;){var d=t.p;t.i===-1?(t.S.U(t),d!==void 0&&(d.n=t.n),t.n!==void 0&&(t.n.p=d)):o=t,t.S.n=t.r,t.r!==void 0&&(t.r=void 0),t=d}e.s=o}function U(e,t){b.call(this,void 0),this.x=e,this.s=void 0,this.g=F-1,this.f=4,this.W=t==null?void 0:t.watched,this.Z=t==null?void 0:t.unwatched,this.name=t==null?void 0:t.name}U.prototype=new b;U.prototype.h=function(){if(this.f&=-3,1&this.f)return!1;if((36&this.f)==32||(this.f&=-5,this.g===F))return!0;if(this.g=F,this.f|=1,this.i>0&&!it(this))return this.f&=-2,!0;var e=l;try{ot(this),l=this;var t=this.x();(16&this.f||this.v!==t||this.i===0)&&(this.v=t,this.f&=-17,this.i++)}catch(o){this.v=o,this.f|=16,this.i++}return l=e,rt(this),this.f&=-2,!0};U.prototype.S=function(e){if(this.t===void 0){this.f|=36;for(var t=this.s;t!==void 0;t=t.n)t.S.S(t)}b.prototype.S.call(this,e)};U.prototype.U=function(e){if(this.t!==void 0&&(b.prototype.U.call(this,e),this.t===void 0)){this.f&=-33;for(var t=this.s;t!==void 0;t=t.n)t.S.U(t)}};U.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var e=this.t;e!==void 0;e=e.x)e.t.N()}};Object.defineProperty(U.prototype,"value",{get:function(){if(1&this.f)throw new Error("Cycle detected");var e=nt(this);if(this.h(),e!==void 0&&(e.i=this.i),16&this.f)throw this.v;return this.v}});function tt(e,t){return new U(e,t)}function st(e){var t=e.u;if(e.u=void 0,typeof t=="function"){E++;var o=l;l=void 0;try{t()}catch(d){throw e.f&=-2,e.f|=8,X(e),d}finally{l=o,G()}}}function X(e){for(var t=e.s;t!==void 0;t=t.n)t.S.U(t);e.x=void 0,e.s=void 0,st(e)}function ft(e){if(l!==this)throw new Error("Out-of-order effect");rt(this),l=e,this.f&=-2,8&this.f&&X(this),G()}function K(e,t){this.x=e,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32,this.name=t==null?void 0:t.name}K.prototype.c=function(){var e=this.S();try{if(8&this.f||this.x===void 0)return;var t=this.x();typeof t=="function"&&(this.u=t)}finally{e()}};K.prototype.S=function(){if(1&this.f)throw new Error("Cycle detected");this.f|=1,this.f&=-9,st(this),ot(this),E++;var e=l;return l=this,ft.bind(this,e)};K.prototype.N=function(){2&this.f||(this.f|=2,this.o=A,A=this)};K.prototype.d=function(){this.f|=8,1&this.f||X(this)};K.prototype.dispose=function(){this.d()};function ut(e,t){var o=new K(e,t);try{o.c()}catch(O){throw o.d(),O}var d=o.d.bind(o);return d[Symbol.dispose]=d,d}function dt(e={}){const t=(e.namespace??"default").trim()||"default",o=e.plugins??[],d=new Map;function O(S,D){return function(){var Z;const j=`${t}:${S}`,R=d.get(S);if(R)return R;const N=D.state(),x=D.modules??{},z={...N};for(const[i,n]of Object.entries(x))z[i]=n.state();const y=ct(z),I=new Map,H=new Map,q=new Map,P=new Map,$=new Map,T=new Set,M=new Set(Object.keys(N)),W=new Set(Object.keys(D.getters??{})),C=new Set(Object.keys(D.actions??{})),r=i=>y.value[i]??{},a=(i,n)=>{y.value={...y.value,[i]:n}},h=new Proxy({},{get(i,n){var c,f;if(I.has(n))return(c=I.get(n))==null?void 0:c.value;if($.has(n))return(f=$.get(n))==null?void 0:f.value;if(M.has(n))return y.value[n];const p=P.get(n);return p?r(p.moduleName)[p.key]:y.value[n]}});for(const[i,n]of Object.entries(D.getters??{}))I.set(i,tt(()=>n(y.value,h)));const w=(i,n)=>{var c;for(const f of T)f(i);for(const f of o)(c=f.onMutation)==null||c.call(f,n,i)},J=(i,n,c,f)=>{const p=y.value[i];Object.is(p,n)||(y.value={...y.value,[i]:n},w({namespace:t,scopeId:j,storeId:S,key:i,oldValue:p,newValue:n,origin:c},f))},B=(i,n,c,f,p)=>{const m=r(i),s=m[n];Object.is(s,c)||(a(i,{...m,[n]:c}),w({namespace:t,scopeId:j,storeId:S,key:`${i}.${n}`,oldValue:s,newValue:c,origin:f},p))},g={$id:S,$namespace:t,$scopeId:j,$subscribe(i){return T.add(i),()=>T.delete(i)},$dispose(){var i;T.clear();for(const n of o)(i=n.onDispose)==null||i.call(n,v);d.delete(S)},$patch(i,n="local"){L(()=>{for(const[c,f]of Object.entries(i)){const p=P.get(c);if(p){B(p.moduleName,p.key,f,n,v);continue}if(c.includes(".")){const[m,s]=c.split(".",2);if(x[m]){B(m,s,f,n,v);continue}}if(x[c]&&f&&typeof f=="object"&&!Array.isArray(f)){for(const[m,s]of Object.entries(f))B(c,m,s,n,v);continue}J(c,f,n,v)}})},$snapshot(){return{...y.value}}};for(const[i,n]of Object.entries(x)){const c=new Map,f=new Map,p=new Proxy({},{get(s,u){var k,V,Y;if(c.has(u))return(k=c.get(u))==null?void 0:k.value;if(I.has(u))return(V=I.get(u))==null?void 0:V.value;if($.has(u))return(Y=$.get(u))==null?void 0:Y.value;const _=r(i);if(u in _)return _[u];if(M.has(u))return y.value[u]}});for(const[s,u]of Object.entries(n.getters??{}))c.set(s,tt(()=>u(r(i),y.value,p)));let m;for(const[s,u]of Object.entries(n.actions??{}))f.set(s,(...k)=>L(()=>u.apply(m,k)));m=new Proxy({},{get(s,u){var k;if(f.has(u))return f.get(u);if(c.has(u))return(k=c.get(u))==null?void 0:k.value;const V=r(i);return u in V?V[u]:v[u]},set(s,u,k){if(f.has(u)||c.has(u))return!1;const V=r(i);return u in V?B(i,u,k,"local",v):v[u]=k,!0}}),q.set(i,m),H.set(i,c);for(const s of Object.keys(r(i)))!(M.has(s)||W.has(s)||C.has(s)||Reflect.has(g,s)||x[s]!==void 0)&&!P.has(s)&&P.set(s,{moduleName:i,key:s});for(const[s,u]of c.entries())!(M.has(s)||W.has(s)||C.has(s)||Reflect.has(g,s)||x[s]!==void 0)&&!$.has(s)&&$.set(s,u);for(const[s,u]of f.entries())!(M.has(s)||W.has(s)||C.has(s)||Reflect.has(g,s)||x[s]!==void 0)&&!Reflect.has(g,s)&&(g[s]=u)}const v=new Proxy(g,{get(i,n,c){var f,p;if(Reflect.has(i,n))return Reflect.get(i,n,c);if(q.has(n))return q.get(n);if(I.has(n))return(f=I.get(n))==null?void 0:f.value;if($.has(n))return(p=$.get(n))==null?void 0:p.value;if(M.has(n))return y.value[n];const m=P.get(n);return m?r(m.moduleName)[m.key]:y.value[n]},set(i,n,c,f){if(Reflect.has(i,n))return Reflect.set(i,n,c,f);const p=P.get(n);return p?(B(p.moduleName,p.key,c,"local",f),!0):(J(n,c,"local",f),!0)}});for(const[i,n]of Object.entries(D.actions??{}))g[i]=(...c)=>L(()=>n.apply(v,c));for(const i of o)(Z=i.onInit)==null||Z.call(i,v);return d.set(S,v),v}}return{defineStore:O,use(S){o.push(S)}}}dt();function lt(e={}){var W,C;const t=e.keyPrefix??"storix",o=new Set(e.include??[]),d=e.storage??"localStorage",O=e.serialize??JSON.stringify,S=e.deserialize??(r=>JSON.parse(r)),D=e.debounce??100,Z=((W=e.indexedDB)==null?void 0:W.dbName)??`${t}-persist`,j=((C=e.indexedDB)==null?void 0:C.storeName)??"stores",R=new Map,N=new Map;let x=null;const z=r=>{const a=[r.$id,r.$scopeId];return!(o.size>0&&!a.some(h=>o.has(h)))},y=r=>`${t}:${r.$namespace}:${r.$id}`,I=()=>x||(x=new Promise((r,a)=>{const h=window.indexedDB.open(Z,1);h.onupgradeneeded=()=>{const w=h.result;w.objectStoreNames.contains(j)||w.createObjectStore(j)},h.onsuccess=()=>r(h.result),h.onerror=()=>a(h.error??new Error("IndexedDB open failed"))}),x),H=async r=>{const a=await I(),h=y(r);return new Promise((w,J)=>{const g=a.transaction(j,"readonly").objectStore(j).get(h);g.onsuccess=()=>{const v=g.result;if(typeof v!="string"){w(null);return}try{w(S(v))}catch{w(null)}},g.onerror=()=>J(g.error??new Error("IndexedDB read failed"))})},q=async(r,a)=>{const h=await I(),w=y(r),J=O(a);return new Promise((B,g)=>{const v=h.transaction(j,"readwrite");v.objectStore(j).put(J,w),v.oncomplete=()=>B(),v.onerror=()=>g(v.error??new Error("IndexedDB write failed")),v.onabort=()=>g(v.error??new Error("IndexedDB write aborted"))})},P=async r=>{if(typeof window>"u")return null;if(d==="indexedDB"&&"indexedDB"in window)try{return await H(r)}catch{return null}try{const a=window.localStorage.getItem(y(r));return a?S(a):null}catch{return null}},$=r=>{if(typeof window>"u")return;const a=R.get(r.$scopeId);if(a){if(d==="indexedDB"&&"indexedDB"in window){q(r,a).catch(()=>{});return}try{window.localStorage.setItem(y(r),O(a))}catch{}}},T=r=>{const a=r.$scopeId,h=N.get(a);if(h&&(clearTimeout(h),N.delete(a)),D<=0){$(r);return}const w=setTimeout(()=>{N.delete(a),$(r)},D);N.set(a,w)},M=r=>{const a=r.$scopeId,h=N.get(a);h&&(clearTimeout(h),N.delete(a)),$(r)};return{name:"persist",onInit(r){const a=r;typeof window>"u"||z(a)&&(async()=>{const h=await P(a);h&&(R.set(a.$scopeId,h),a.$patch(h,"remote"))})()},onMutation(r,a){const h=r;if(typeof window>"u"||!z(h))return;const w=R.get(h.$scopeId)??{};w[a.key]=a.newValue,R.set(h.$scopeId,w),T(h)},onDispose(r){const a=r;z(a)&&M(a)}}}exports.persistPlugin=lt;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type PersistStorage = 'localStorage' | 'indexedDB';
|
|
2
|
+
export interface IndexedDBPersistOptions {
|
|
3
|
+
dbName?: string;
|
|
4
|
+
storeName?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface PersistPluginOptions {
|
|
7
|
+
keyPrefix?: string;
|
|
8
|
+
include?: string[];
|
|
9
|
+
storage?: PersistStorage;
|
|
10
|
+
serialize?: (value: Record<string, unknown>) => string;
|
|
11
|
+
deserialize?: (raw: string) => Record<string, unknown>;
|
|
12
|
+
debounce?: number;
|
|
13
|
+
indexedDB?: IndexedDBPersistOptions;
|
|
14
|
+
}
|
|
15
|
+
export declare function persistPlugin(options?: PersistPluginOptions): import("@storix-js/core").StorePlugin;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,KAAK,cAAc,GAAG,cAAc,GAAG,WAAW,CAAC;AAEnD,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;IACvD,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,uBAAuB,CAAC;CACrC;AASD,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,yCAuL/D"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
var at = Symbol.for("preact-signals");
|
|
2
|
+
function G() {
|
|
3
|
+
if (E > 1)
|
|
4
|
+
E--;
|
|
5
|
+
else {
|
|
6
|
+
for (var e, t = !1; A !== void 0; ) {
|
|
7
|
+
var o = A;
|
|
8
|
+
for (A = void 0, Q++; o !== void 0; ) {
|
|
9
|
+
var d = o.o;
|
|
10
|
+
if (o.o = void 0, o.f &= -3, !(8 & o.f) && it(o)) try {
|
|
11
|
+
o.c();
|
|
12
|
+
} catch (O) {
|
|
13
|
+
t || (e = O, t = !0);
|
|
14
|
+
}
|
|
15
|
+
o = d;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (Q = 0, E--, t) throw e;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function L(e) {
|
|
22
|
+
if (E > 0) return e();
|
|
23
|
+
E++;
|
|
24
|
+
try {
|
|
25
|
+
return e();
|
|
26
|
+
} finally {
|
|
27
|
+
G();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
var l = void 0;
|
|
31
|
+
function et(e) {
|
|
32
|
+
var t = l;
|
|
33
|
+
l = void 0;
|
|
34
|
+
try {
|
|
35
|
+
return e();
|
|
36
|
+
} finally {
|
|
37
|
+
l = t;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
var A = void 0, E = 0, Q = 0, F = 0;
|
|
41
|
+
function nt(e) {
|
|
42
|
+
if (l !== void 0) {
|
|
43
|
+
var t = e.n;
|
|
44
|
+
if (t === void 0 || t.t !== l)
|
|
45
|
+
return t = { i: 0, S: e, p: l.s, n: void 0, t: l, e: void 0, x: void 0, r: t }, l.s !== void 0 && (l.s.n = t), l.s = t, e.n = t, 32 & l.f && e.S(t), t;
|
|
46
|
+
if (t.i === -1)
|
|
47
|
+
return t.i = 0, t.n !== void 0 && (t.n.p = t.p, t.p !== void 0 && (t.p.n = t.n), t.p = l.s, t.n = void 0, l.s.n = t, l.s = t), t;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function b(e, t) {
|
|
51
|
+
this.v = e, this.i = 0, this.n = void 0, this.t = void 0, this.W = t == null ? void 0 : t.watched, this.Z = t == null ? void 0 : t.unwatched, this.name = t == null ? void 0 : t.name;
|
|
52
|
+
}
|
|
53
|
+
b.prototype.brand = at;
|
|
54
|
+
b.prototype.h = function() {
|
|
55
|
+
return !0;
|
|
56
|
+
};
|
|
57
|
+
b.prototype.S = function(e) {
|
|
58
|
+
var t = this, o = this.t;
|
|
59
|
+
o !== e && e.e === void 0 && (e.x = o, this.t = e, o !== void 0 ? o.e = e : et(function() {
|
|
60
|
+
var d;
|
|
61
|
+
(d = t.W) == null || d.call(t);
|
|
62
|
+
}));
|
|
63
|
+
};
|
|
64
|
+
b.prototype.U = function(e) {
|
|
65
|
+
var t = this;
|
|
66
|
+
if (this.t !== void 0) {
|
|
67
|
+
var o = e.e, d = e.x;
|
|
68
|
+
o !== void 0 && (o.x = d, e.e = void 0), d !== void 0 && (d.e = o, e.x = void 0), e === this.t && (this.t = d, d === void 0 && et(function() {
|
|
69
|
+
var O;
|
|
70
|
+
(O = t.Z) == null || O.call(t);
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
b.prototype.subscribe = function(e) {
|
|
75
|
+
var t = this;
|
|
76
|
+
return ut(function() {
|
|
77
|
+
var o = t.value, d = l;
|
|
78
|
+
l = void 0;
|
|
79
|
+
try {
|
|
80
|
+
e(o);
|
|
81
|
+
} finally {
|
|
82
|
+
l = d;
|
|
83
|
+
}
|
|
84
|
+
}, { name: "sub" });
|
|
85
|
+
};
|
|
86
|
+
b.prototype.valueOf = function() {
|
|
87
|
+
return this.value;
|
|
88
|
+
};
|
|
89
|
+
b.prototype.toString = function() {
|
|
90
|
+
return this.value + "";
|
|
91
|
+
};
|
|
92
|
+
b.prototype.toJSON = function() {
|
|
93
|
+
return this.value;
|
|
94
|
+
};
|
|
95
|
+
b.prototype.peek = function() {
|
|
96
|
+
var e = l;
|
|
97
|
+
l = void 0;
|
|
98
|
+
try {
|
|
99
|
+
return this.value;
|
|
100
|
+
} finally {
|
|
101
|
+
l = e;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
Object.defineProperty(b.prototype, "value", { get: function() {
|
|
105
|
+
var e = nt(this);
|
|
106
|
+
return e !== void 0 && (e.i = this.i), this.v;
|
|
107
|
+
}, set: function(e) {
|
|
108
|
+
if (e !== this.v) {
|
|
109
|
+
if (Q > 100) throw new Error("Cycle detected");
|
|
110
|
+
this.v = e, this.i++, F++, E++;
|
|
111
|
+
try {
|
|
112
|
+
for (var t = this.t; t !== void 0; t = t.x) t.t.N();
|
|
113
|
+
} finally {
|
|
114
|
+
G();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
} });
|
|
118
|
+
function ct(e, t) {
|
|
119
|
+
return new b(e, t);
|
|
120
|
+
}
|
|
121
|
+
function it(e) {
|
|
122
|
+
for (var t = e.s; t !== void 0; t = t.n) if (t.S.i !== t.i || !t.S.h() || t.S.i !== t.i) return !0;
|
|
123
|
+
return !1;
|
|
124
|
+
}
|
|
125
|
+
function ot(e) {
|
|
126
|
+
for (var t = e.s; t !== void 0; t = t.n) {
|
|
127
|
+
var o = t.S.n;
|
|
128
|
+
if (o !== void 0 && (t.r = o), t.S.n = t, t.i = -1, t.n === void 0) {
|
|
129
|
+
e.s = t;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function rt(e) {
|
|
135
|
+
for (var t = e.s, o = void 0; t !== void 0; ) {
|
|
136
|
+
var d = t.p;
|
|
137
|
+
t.i === -1 ? (t.S.U(t), d !== void 0 && (d.n = t.n), t.n !== void 0 && (t.n.p = d)) : o = t, t.S.n = t.r, t.r !== void 0 && (t.r = void 0), t = d;
|
|
138
|
+
}
|
|
139
|
+
e.s = o;
|
|
140
|
+
}
|
|
141
|
+
function U(e, t) {
|
|
142
|
+
b.call(this, void 0), this.x = e, this.s = void 0, this.g = F - 1, this.f = 4, this.W = t == null ? void 0 : t.watched, this.Z = t == null ? void 0 : t.unwatched, this.name = t == null ? void 0 : t.name;
|
|
143
|
+
}
|
|
144
|
+
U.prototype = new b();
|
|
145
|
+
U.prototype.h = function() {
|
|
146
|
+
if (this.f &= -3, 1 & this.f) return !1;
|
|
147
|
+
if ((36 & this.f) == 32 || (this.f &= -5, this.g === F)) return !0;
|
|
148
|
+
if (this.g = F, this.f |= 1, this.i > 0 && !it(this))
|
|
149
|
+
return this.f &= -2, !0;
|
|
150
|
+
var e = l;
|
|
151
|
+
try {
|
|
152
|
+
ot(this), l = this;
|
|
153
|
+
var t = this.x();
|
|
154
|
+
(16 & this.f || this.v !== t || this.i === 0) && (this.v = t, this.f &= -17, this.i++);
|
|
155
|
+
} catch (o) {
|
|
156
|
+
this.v = o, this.f |= 16, this.i++;
|
|
157
|
+
}
|
|
158
|
+
return l = e, rt(this), this.f &= -2, !0;
|
|
159
|
+
};
|
|
160
|
+
U.prototype.S = function(e) {
|
|
161
|
+
if (this.t === void 0) {
|
|
162
|
+
this.f |= 36;
|
|
163
|
+
for (var t = this.s; t !== void 0; t = t.n) t.S.S(t);
|
|
164
|
+
}
|
|
165
|
+
b.prototype.S.call(this, e);
|
|
166
|
+
};
|
|
167
|
+
U.prototype.U = function(e) {
|
|
168
|
+
if (this.t !== void 0 && (b.prototype.U.call(this, e), this.t === void 0)) {
|
|
169
|
+
this.f &= -33;
|
|
170
|
+
for (var t = this.s; t !== void 0; t = t.n) t.S.U(t);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
U.prototype.N = function() {
|
|
174
|
+
if (!(2 & this.f)) {
|
|
175
|
+
this.f |= 6;
|
|
176
|
+
for (var e = this.t; e !== void 0; e = e.x) e.t.N();
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
Object.defineProperty(U.prototype, "value", { get: function() {
|
|
180
|
+
if (1 & this.f) throw new Error("Cycle detected");
|
|
181
|
+
var e = nt(this);
|
|
182
|
+
if (this.h(), e !== void 0 && (e.i = this.i), 16 & this.f) throw this.v;
|
|
183
|
+
return this.v;
|
|
184
|
+
} });
|
|
185
|
+
function tt(e, t) {
|
|
186
|
+
return new U(e, t);
|
|
187
|
+
}
|
|
188
|
+
function st(e) {
|
|
189
|
+
var t = e.u;
|
|
190
|
+
if (e.u = void 0, typeof t == "function") {
|
|
191
|
+
E++;
|
|
192
|
+
var o = l;
|
|
193
|
+
l = void 0;
|
|
194
|
+
try {
|
|
195
|
+
t();
|
|
196
|
+
} catch (d) {
|
|
197
|
+
throw e.f &= -2, e.f |= 8, X(e), d;
|
|
198
|
+
} finally {
|
|
199
|
+
l = o, G();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function X(e) {
|
|
204
|
+
for (var t = e.s; t !== void 0; t = t.n) t.S.U(t);
|
|
205
|
+
e.x = void 0, e.s = void 0, st(e);
|
|
206
|
+
}
|
|
207
|
+
function ft(e) {
|
|
208
|
+
if (l !== this) throw new Error("Out-of-order effect");
|
|
209
|
+
rt(this), l = e, this.f &= -2, 8 & this.f && X(this), G();
|
|
210
|
+
}
|
|
211
|
+
function K(e, t) {
|
|
212
|
+
this.x = e, this.u = void 0, this.s = void 0, this.o = void 0, this.f = 32, this.name = t == null ? void 0 : t.name;
|
|
213
|
+
}
|
|
214
|
+
K.prototype.c = function() {
|
|
215
|
+
var e = this.S();
|
|
216
|
+
try {
|
|
217
|
+
if (8 & this.f || this.x === void 0) return;
|
|
218
|
+
var t = this.x();
|
|
219
|
+
typeof t == "function" && (this.u = t);
|
|
220
|
+
} finally {
|
|
221
|
+
e();
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
K.prototype.S = function() {
|
|
225
|
+
if (1 & this.f) throw new Error("Cycle detected");
|
|
226
|
+
this.f |= 1, this.f &= -9, st(this), ot(this), E++;
|
|
227
|
+
var e = l;
|
|
228
|
+
return l = this, ft.bind(this, e);
|
|
229
|
+
};
|
|
230
|
+
K.prototype.N = function() {
|
|
231
|
+
2 & this.f || (this.f |= 2, this.o = A, A = this);
|
|
232
|
+
};
|
|
233
|
+
K.prototype.d = function() {
|
|
234
|
+
this.f |= 8, 1 & this.f || X(this);
|
|
235
|
+
};
|
|
236
|
+
K.prototype.dispose = function() {
|
|
237
|
+
this.d();
|
|
238
|
+
};
|
|
239
|
+
function ut(e, t) {
|
|
240
|
+
var o = new K(e, t);
|
|
241
|
+
try {
|
|
242
|
+
o.c();
|
|
243
|
+
} catch (O) {
|
|
244
|
+
throw o.d(), O;
|
|
245
|
+
}
|
|
246
|
+
var d = o.d.bind(o);
|
|
247
|
+
return d[Symbol.dispose] = d, d;
|
|
248
|
+
}
|
|
249
|
+
function dt(e = {}) {
|
|
250
|
+
const t = (e.namespace ?? "default").trim() || "default", o = e.plugins ?? [], d = /* @__PURE__ */ new Map();
|
|
251
|
+
function O(x, D) {
|
|
252
|
+
return function() {
|
|
253
|
+
var Z;
|
|
254
|
+
const j = `${t}:${x}`, R = d.get(x);
|
|
255
|
+
if (R) return R;
|
|
256
|
+
const N = D.state(), S = D.modules ?? {}, z = { ...N };
|
|
257
|
+
for (const [i, n] of Object.entries(S))
|
|
258
|
+
z[i] = n.state();
|
|
259
|
+
const y = ct(z), I = /* @__PURE__ */ new Map(), H = /* @__PURE__ */ new Map(), q = /* @__PURE__ */ new Map(), P = /* @__PURE__ */ new Map(), $ = /* @__PURE__ */ new Map(), T = /* @__PURE__ */ new Set(), M = new Set(Object.keys(N)), W = new Set(Object.keys(D.getters ?? {})), C = new Set(Object.keys(D.actions ?? {})), r = (i) => y.value[i] ?? {}, a = (i, n) => {
|
|
260
|
+
y.value = {
|
|
261
|
+
...y.value,
|
|
262
|
+
[i]: n
|
|
263
|
+
};
|
|
264
|
+
}, h = new Proxy(
|
|
265
|
+
{},
|
|
266
|
+
{
|
|
267
|
+
get(i, n) {
|
|
268
|
+
var c, f;
|
|
269
|
+
if (I.has(n)) return (c = I.get(n)) == null ? void 0 : c.value;
|
|
270
|
+
if ($.has(n)) return (f = $.get(n)) == null ? void 0 : f.value;
|
|
271
|
+
if (M.has(n)) return y.value[n];
|
|
272
|
+
const p = P.get(n);
|
|
273
|
+
return p ? r(p.moduleName)[p.key] : y.value[n];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
);
|
|
277
|
+
for (const [i, n] of Object.entries(D.getters ?? {}))
|
|
278
|
+
I.set(
|
|
279
|
+
i,
|
|
280
|
+
tt(() => n(y.value, h))
|
|
281
|
+
);
|
|
282
|
+
const w = (i, n) => {
|
|
283
|
+
var c;
|
|
284
|
+
for (const f of T) f(i);
|
|
285
|
+
for (const f of o)
|
|
286
|
+
(c = f.onMutation) == null || c.call(f, n, i);
|
|
287
|
+
}, J = (i, n, c, f) => {
|
|
288
|
+
const p = y.value[i];
|
|
289
|
+
Object.is(p, n) || (y.value = {
|
|
290
|
+
...y.value,
|
|
291
|
+
[i]: n
|
|
292
|
+
}, w(
|
|
293
|
+
{
|
|
294
|
+
namespace: t,
|
|
295
|
+
scopeId: j,
|
|
296
|
+
storeId: x,
|
|
297
|
+
key: i,
|
|
298
|
+
oldValue: p,
|
|
299
|
+
newValue: n,
|
|
300
|
+
origin: c
|
|
301
|
+
},
|
|
302
|
+
f
|
|
303
|
+
));
|
|
304
|
+
}, B = (i, n, c, f, p) => {
|
|
305
|
+
const m = r(i), s = m[n];
|
|
306
|
+
Object.is(s, c) || (a(i, {
|
|
307
|
+
...m,
|
|
308
|
+
[n]: c
|
|
309
|
+
}), w(
|
|
310
|
+
{
|
|
311
|
+
namespace: t,
|
|
312
|
+
scopeId: j,
|
|
313
|
+
storeId: x,
|
|
314
|
+
key: `${i}.${n}`,
|
|
315
|
+
oldValue: s,
|
|
316
|
+
newValue: c,
|
|
317
|
+
origin: f
|
|
318
|
+
},
|
|
319
|
+
p
|
|
320
|
+
));
|
|
321
|
+
}, g = {
|
|
322
|
+
$id: x,
|
|
323
|
+
$namespace: t,
|
|
324
|
+
$scopeId: j,
|
|
325
|
+
$subscribe(i) {
|
|
326
|
+
return T.add(i), () => T.delete(i);
|
|
327
|
+
},
|
|
328
|
+
$dispose() {
|
|
329
|
+
var i;
|
|
330
|
+
T.clear();
|
|
331
|
+
for (const n of o)
|
|
332
|
+
(i = n.onDispose) == null || i.call(n, v);
|
|
333
|
+
d.delete(x);
|
|
334
|
+
},
|
|
335
|
+
$patch(i, n = "local") {
|
|
336
|
+
L(() => {
|
|
337
|
+
for (const [c, f] of Object.entries(i)) {
|
|
338
|
+
const p = P.get(c);
|
|
339
|
+
if (p) {
|
|
340
|
+
B(p.moduleName, p.key, f, n, v);
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
if (c.includes(".")) {
|
|
344
|
+
const [m, s] = c.split(".", 2);
|
|
345
|
+
if (S[m]) {
|
|
346
|
+
B(m, s, f, n, v);
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (S[c] && f && typeof f == "object" && !Array.isArray(f)) {
|
|
351
|
+
for (const [m, s] of Object.entries(f))
|
|
352
|
+
B(c, m, s, n, v);
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
J(c, f, n, v);
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
},
|
|
359
|
+
$snapshot() {
|
|
360
|
+
return { ...y.value };
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
for (const [i, n] of Object.entries(S)) {
|
|
364
|
+
const c = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map(), p = new Proxy(
|
|
365
|
+
{},
|
|
366
|
+
{
|
|
367
|
+
get(s, u) {
|
|
368
|
+
var k, V, Y;
|
|
369
|
+
if (c.has(u)) return (k = c.get(u)) == null ? void 0 : k.value;
|
|
370
|
+
if (I.has(u)) return (V = I.get(u)) == null ? void 0 : V.value;
|
|
371
|
+
if ($.has(u)) return (Y = $.get(u)) == null ? void 0 : Y.value;
|
|
372
|
+
const _ = r(i);
|
|
373
|
+
if (u in _) return _[u];
|
|
374
|
+
if (M.has(u)) return y.value[u];
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
);
|
|
378
|
+
for (const [s, u] of Object.entries(n.getters ?? {}))
|
|
379
|
+
c.set(
|
|
380
|
+
s,
|
|
381
|
+
tt(() => u(r(i), y.value, p))
|
|
382
|
+
);
|
|
383
|
+
let m;
|
|
384
|
+
for (const [s, u] of Object.entries(n.actions ?? {}))
|
|
385
|
+
f.set(s, (...k) => L(() => u.apply(m, k)));
|
|
386
|
+
m = new Proxy(
|
|
387
|
+
{},
|
|
388
|
+
{
|
|
389
|
+
get(s, u) {
|
|
390
|
+
var k;
|
|
391
|
+
if (f.has(u)) return f.get(u);
|
|
392
|
+
if (c.has(u)) return (k = c.get(u)) == null ? void 0 : k.value;
|
|
393
|
+
const V = r(i);
|
|
394
|
+
return u in V ? V[u] : v[u];
|
|
395
|
+
},
|
|
396
|
+
set(s, u, k) {
|
|
397
|
+
if (f.has(u) || c.has(u)) return !1;
|
|
398
|
+
const V = r(i);
|
|
399
|
+
return u in V ? B(i, u, k, "local", v) : v[u] = k, !0;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
), q.set(i, m), H.set(i, c);
|
|
403
|
+
for (const s of Object.keys(r(i)))
|
|
404
|
+
!(M.has(s) || W.has(s) || C.has(s) || Reflect.has(g, s) || S[s] !== void 0) && !P.has(s) && P.set(s, { moduleName: i, key: s });
|
|
405
|
+
for (const [s, u] of c.entries())
|
|
406
|
+
!(M.has(s) || W.has(s) || C.has(s) || Reflect.has(g, s) || S[s] !== void 0) && !$.has(s) && $.set(s, u);
|
|
407
|
+
for (const [s, u] of f.entries())
|
|
408
|
+
!(M.has(s) || W.has(s) || C.has(s) || Reflect.has(g, s) || S[s] !== void 0) && !Reflect.has(g, s) && (g[s] = u);
|
|
409
|
+
}
|
|
410
|
+
const v = new Proxy(g, {
|
|
411
|
+
get(i, n, c) {
|
|
412
|
+
var f, p;
|
|
413
|
+
if (Reflect.has(i, n)) return Reflect.get(i, n, c);
|
|
414
|
+
if (q.has(n)) return q.get(n);
|
|
415
|
+
if (I.has(n)) return (f = I.get(n)) == null ? void 0 : f.value;
|
|
416
|
+
if ($.has(n)) return (p = $.get(n)) == null ? void 0 : p.value;
|
|
417
|
+
if (M.has(n)) return y.value[n];
|
|
418
|
+
const m = P.get(n);
|
|
419
|
+
return m ? r(m.moduleName)[m.key] : y.value[n];
|
|
420
|
+
},
|
|
421
|
+
set(i, n, c, f) {
|
|
422
|
+
if (Reflect.has(i, n))
|
|
423
|
+
return Reflect.set(i, n, c, f);
|
|
424
|
+
const p = P.get(n);
|
|
425
|
+
return p ? (B(p.moduleName, p.key, c, "local", f), !0) : (J(n, c, "local", f), !0);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
for (const [i, n] of Object.entries(D.actions ?? {}))
|
|
429
|
+
g[i] = (...c) => L(() => n.apply(v, c));
|
|
430
|
+
for (const i of o)
|
|
431
|
+
(Z = i.onInit) == null || Z.call(i, v);
|
|
432
|
+
return d.set(x, v), v;
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
return {
|
|
436
|
+
defineStore: O,
|
|
437
|
+
use(x) {
|
|
438
|
+
o.push(x);
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
dt();
|
|
443
|
+
function lt(e = {}) {
|
|
444
|
+
var W, C;
|
|
445
|
+
const t = e.keyPrefix ?? "storix", o = new Set(e.include ?? []), d = e.storage ?? "localStorage", O = e.serialize ?? JSON.stringify, x = e.deserialize ?? ((r) => JSON.parse(r)), D = e.debounce ?? 100, Z = ((W = e.indexedDB) == null ? void 0 : W.dbName) ?? `${t}-persist`, j = ((C = e.indexedDB) == null ? void 0 : C.storeName) ?? "stores", R = /* @__PURE__ */ new Map(), N = /* @__PURE__ */ new Map();
|
|
446
|
+
let S = null;
|
|
447
|
+
const z = (r) => {
|
|
448
|
+
const a = [r.$id, r.$scopeId];
|
|
449
|
+
return !(o.size > 0 && !a.some((h) => o.has(h)));
|
|
450
|
+
}, y = (r) => `${t}:${r.$namespace}:${r.$id}`, I = () => S || (S = new Promise((r, a) => {
|
|
451
|
+
const h = window.indexedDB.open(Z, 1);
|
|
452
|
+
h.onupgradeneeded = () => {
|
|
453
|
+
const w = h.result;
|
|
454
|
+
w.objectStoreNames.contains(j) || w.createObjectStore(j);
|
|
455
|
+
}, h.onsuccess = () => r(h.result), h.onerror = () => a(h.error ?? new Error("IndexedDB open failed"));
|
|
456
|
+
}), S), H = async (r) => {
|
|
457
|
+
const a = await I(), h = y(r);
|
|
458
|
+
return new Promise((w, J) => {
|
|
459
|
+
const g = a.transaction(j, "readonly").objectStore(j).get(h);
|
|
460
|
+
g.onsuccess = () => {
|
|
461
|
+
const v = g.result;
|
|
462
|
+
if (typeof v != "string") {
|
|
463
|
+
w(null);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
try {
|
|
467
|
+
w(x(v));
|
|
468
|
+
} catch {
|
|
469
|
+
w(null);
|
|
470
|
+
}
|
|
471
|
+
}, g.onerror = () => J(g.error ?? new Error("IndexedDB read failed"));
|
|
472
|
+
});
|
|
473
|
+
}, q = async (r, a) => {
|
|
474
|
+
const h = await I(), w = y(r), J = O(a);
|
|
475
|
+
return new Promise((B, g) => {
|
|
476
|
+
const v = h.transaction(j, "readwrite");
|
|
477
|
+
v.objectStore(j).put(J, w), v.oncomplete = () => B(), v.onerror = () => g(v.error ?? new Error("IndexedDB write failed")), v.onabort = () => g(v.error ?? new Error("IndexedDB write aborted"));
|
|
478
|
+
});
|
|
479
|
+
}, P = async (r) => {
|
|
480
|
+
if (typeof window > "u") return null;
|
|
481
|
+
if (d === "indexedDB" && "indexedDB" in window)
|
|
482
|
+
try {
|
|
483
|
+
return await H(r);
|
|
484
|
+
} catch {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
try {
|
|
488
|
+
const a = window.localStorage.getItem(y(r));
|
|
489
|
+
return a ? x(a) : null;
|
|
490
|
+
} catch {
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
493
|
+
}, $ = (r) => {
|
|
494
|
+
if (typeof window > "u") return;
|
|
495
|
+
const a = R.get(r.$scopeId);
|
|
496
|
+
if (a) {
|
|
497
|
+
if (d === "indexedDB" && "indexedDB" in window) {
|
|
498
|
+
q(r, a).catch(() => {
|
|
499
|
+
});
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
try {
|
|
503
|
+
window.localStorage.setItem(y(r), O(a));
|
|
504
|
+
} catch {
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}, T = (r) => {
|
|
508
|
+
const a = r.$scopeId, h = N.get(a);
|
|
509
|
+
if (h && (clearTimeout(h), N.delete(a)), D <= 0) {
|
|
510
|
+
$(r);
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
const w = setTimeout(() => {
|
|
514
|
+
N.delete(a), $(r);
|
|
515
|
+
}, D);
|
|
516
|
+
N.set(a, w);
|
|
517
|
+
}, M = (r) => {
|
|
518
|
+
const a = r.$scopeId, h = N.get(a);
|
|
519
|
+
h && (clearTimeout(h), N.delete(a)), $(r);
|
|
520
|
+
};
|
|
521
|
+
return {
|
|
522
|
+
name: "persist",
|
|
523
|
+
onInit(r) {
|
|
524
|
+
const a = r;
|
|
525
|
+
typeof window > "u" || z(a) && (async () => {
|
|
526
|
+
const h = await P(a);
|
|
527
|
+
h && (R.set(a.$scopeId, h), a.$patch(h, "remote"));
|
|
528
|
+
})();
|
|
529
|
+
},
|
|
530
|
+
onMutation(r, a) {
|
|
531
|
+
const h = r;
|
|
532
|
+
if (typeof window > "u" || !z(h)) return;
|
|
533
|
+
const w = R.get(h.$scopeId) ?? {};
|
|
534
|
+
w[a.key] = a.newValue, R.set(h.$scopeId, w), T(h);
|
|
535
|
+
},
|
|
536
|
+
onDispose(r) {
|
|
537
|
+
const a = r;
|
|
538
|
+
z(a) && M(a);
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
export {
|
|
543
|
+
lt as persistPlugin
|
|
544
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@storix-js/persist",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "vite build && tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
17
|
+
"dev": "vite build --watch",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@storix-js/core": "workspace:*"
|
|
23
|
+
}
|
|
24
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { definePlugin } from '@storix-js/core';
|
|
2
|
+
|
|
3
|
+
type PersistStorage = 'localStorage' | 'indexedDB';
|
|
4
|
+
|
|
5
|
+
export interface IndexedDBPersistOptions {
|
|
6
|
+
dbName?: string;
|
|
7
|
+
storeName?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface PersistPluginOptions {
|
|
11
|
+
keyPrefix?: string;
|
|
12
|
+
include?: string[];
|
|
13
|
+
storage?: PersistStorage;
|
|
14
|
+
serialize?: (value: Record<string, unknown>) => string;
|
|
15
|
+
deserialize?: (raw: string) => Record<string, unknown>;
|
|
16
|
+
debounce?: number;
|
|
17
|
+
indexedDB?: IndexedDBPersistOptions;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type ScopedStore = {
|
|
21
|
+
$id: string;
|
|
22
|
+
$namespace: string;
|
|
23
|
+
$scopeId: string;
|
|
24
|
+
$patch: (patch: Record<string, unknown>, origin?: 'local' | 'remote') => void;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function persistPlugin(options: PersistPluginOptions = {}) {
|
|
28
|
+
const keyPrefix = options.keyPrefix ?? 'storix';
|
|
29
|
+
const include = new Set(options.include ?? []);
|
|
30
|
+
const storage = options.storage ?? 'localStorage';
|
|
31
|
+
const serialize = options.serialize ?? JSON.stringify;
|
|
32
|
+
const deserialize = options.deserialize ?? ((raw: string) => JSON.parse(raw) as Record<string, unknown>);
|
|
33
|
+
const debounceMs = options.debounce ?? 100;
|
|
34
|
+
const idbDatabaseName = options.indexedDB?.dbName ?? `${keyPrefix}-persist`;
|
|
35
|
+
const idbStoreName = options.indexedDB?.storeName ?? 'stores';
|
|
36
|
+
|
|
37
|
+
const cache = new Map<string, Record<string, unknown>>();
|
|
38
|
+
const timers = new Map<string, ReturnType<typeof setTimeout>>();
|
|
39
|
+
|
|
40
|
+
let dbPromise: Promise<IDBDatabase> | null = null;
|
|
41
|
+
|
|
42
|
+
const shouldPersistStore = (store: ScopedStore) => {
|
|
43
|
+
const ids = [store.$id, store.$scopeId];
|
|
44
|
+
if (include.size > 0 && !ids.some((value) => include.has(value))) return false;
|
|
45
|
+
return true;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const getKey = (store: ScopedStore) => `${keyPrefix}:${store.$namespace}:${store.$id}`;
|
|
49
|
+
|
|
50
|
+
const getDb = () => {
|
|
51
|
+
if (dbPromise) return dbPromise;
|
|
52
|
+
|
|
53
|
+
dbPromise = new Promise<IDBDatabase>((resolve, reject) => {
|
|
54
|
+
const request = window.indexedDB.open(idbDatabaseName, 1);
|
|
55
|
+
request.onupgradeneeded = () => {
|
|
56
|
+
const db = request.result;
|
|
57
|
+
if (!db.objectStoreNames.contains(idbStoreName)) {
|
|
58
|
+
db.createObjectStore(idbStoreName);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
request.onsuccess = () => resolve(request.result);
|
|
62
|
+
request.onerror = () => reject(request.error ?? new Error('IndexedDB open failed'));
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return dbPromise;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const readFromIndexedDb = async (store: ScopedStore) => {
|
|
69
|
+
const db = await getDb();
|
|
70
|
+
const key = getKey(store);
|
|
71
|
+
|
|
72
|
+
return new Promise<Record<string, unknown> | null>((resolve, reject) => {
|
|
73
|
+
const tx = db.transaction(idbStoreName, 'readonly');
|
|
74
|
+
const req = tx.objectStore(idbStoreName).get(key);
|
|
75
|
+
|
|
76
|
+
req.onsuccess = () => {
|
|
77
|
+
const result = req.result;
|
|
78
|
+
if (typeof result !== 'string') {
|
|
79
|
+
resolve(null);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
resolve(deserialize(result));
|
|
85
|
+
} catch {
|
|
86
|
+
resolve(null);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
req.onerror = () => reject(req.error ?? new Error('IndexedDB read failed'));
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const writeToIndexedDb = async (store: ScopedStore, value: Record<string, unknown>) => {
|
|
95
|
+
const db = await getDb();
|
|
96
|
+
const key = getKey(store);
|
|
97
|
+
const raw = serialize(value);
|
|
98
|
+
|
|
99
|
+
return new Promise<void>((resolve, reject) => {
|
|
100
|
+
const tx = db.transaction(idbStoreName, 'readwrite');
|
|
101
|
+
tx.objectStore(idbStoreName).put(raw, key);
|
|
102
|
+
|
|
103
|
+
tx.oncomplete = () => resolve();
|
|
104
|
+
tx.onerror = () => reject(tx.error ?? new Error('IndexedDB write failed'));
|
|
105
|
+
tx.onabort = () => reject(tx.error ?? new Error('IndexedDB write aborted'));
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const readSnapshot = async (store: ScopedStore) => {
|
|
110
|
+
if (typeof window === 'undefined') return null;
|
|
111
|
+
|
|
112
|
+
if (storage === 'indexedDB' && 'indexedDB' in window) {
|
|
113
|
+
try {
|
|
114
|
+
return await readFromIndexedDb(store);
|
|
115
|
+
} catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
const raw = window.localStorage.getItem(getKey(store));
|
|
122
|
+
if (!raw) return null;
|
|
123
|
+
return deserialize(raw);
|
|
124
|
+
} catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const writeSnapshot = (store: ScopedStore) => {
|
|
130
|
+
if (typeof window === 'undefined') return;
|
|
131
|
+
|
|
132
|
+
const snapshot = cache.get(store.$scopeId);
|
|
133
|
+
if (!snapshot) return;
|
|
134
|
+
|
|
135
|
+
if (storage === 'indexedDB' && 'indexedDB' in window) {
|
|
136
|
+
void writeToIndexedDb(store, snapshot).catch(() => {
|
|
137
|
+
// noop
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
window.localStorage.setItem(getKey(store), serialize(snapshot));
|
|
144
|
+
} catch {
|
|
145
|
+
// noop
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const scheduleWrite = (store: ScopedStore) => {
|
|
150
|
+
const timerKey = store.$scopeId;
|
|
151
|
+
const existing = timers.get(timerKey);
|
|
152
|
+
if (existing) {
|
|
153
|
+
clearTimeout(existing);
|
|
154
|
+
timers.delete(timerKey);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (debounceMs <= 0) {
|
|
158
|
+
writeSnapshot(store);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const timer = setTimeout(() => {
|
|
163
|
+
timers.delete(timerKey);
|
|
164
|
+
writeSnapshot(store);
|
|
165
|
+
}, debounceMs);
|
|
166
|
+
|
|
167
|
+
timers.set(timerKey, timer);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const flush = (store: ScopedStore) => {
|
|
171
|
+
const timerKey = store.$scopeId;
|
|
172
|
+
const timer = timers.get(timerKey);
|
|
173
|
+
if (timer) {
|
|
174
|
+
clearTimeout(timer);
|
|
175
|
+
timers.delete(timerKey);
|
|
176
|
+
}
|
|
177
|
+
writeSnapshot(store);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
return definePlugin({
|
|
181
|
+
name: 'persist',
|
|
182
|
+
onInit(store) {
|
|
183
|
+
const scopedStore = store as ScopedStore;
|
|
184
|
+
if (typeof window === 'undefined') return;
|
|
185
|
+
if (!shouldPersistStore(scopedStore)) return;
|
|
186
|
+
|
|
187
|
+
void (async () => {
|
|
188
|
+
const snapshot = await readSnapshot(scopedStore);
|
|
189
|
+
if (!snapshot) return;
|
|
190
|
+
cache.set(scopedStore.$scopeId, snapshot);
|
|
191
|
+
scopedStore.$patch(snapshot, 'remote');
|
|
192
|
+
})();
|
|
193
|
+
},
|
|
194
|
+
onMutation(store, mutation) {
|
|
195
|
+
const scopedStore = store as ScopedStore;
|
|
196
|
+
if (typeof window === 'undefined') return;
|
|
197
|
+
if (!shouldPersistStore(scopedStore)) return;
|
|
198
|
+
|
|
199
|
+
const snapshot = cache.get(scopedStore.$scopeId) ?? {};
|
|
200
|
+
snapshot[mutation.key] = mutation.newValue;
|
|
201
|
+
cache.set(scopedStore.$scopeId, snapshot);
|
|
202
|
+
scheduleWrite(scopedStore);
|
|
203
|
+
},
|
|
204
|
+
onDispose(store) {
|
|
205
|
+
const scopedStore = store as ScopedStore;
|
|
206
|
+
if (!shouldPersistStore(scopedStore)) return;
|
|
207
|
+
flush(scopedStore);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
package/tsconfig.json
ADDED
package/vite.config.ts
ADDED