@storix-js/persist 0.2.1 → 0.3.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/README.md CHANGED
@@ -22,3 +22,5 @@ const storix = createStorix({
22
22
  ```
23
23
 
24
24
  Use `storage: 'indexedDB'` for larger or more durable client-side state.
25
+
26
+ The plugin writes complete namespace-aware snapshots, including nested modules. If a local mutation occurs while asynchronous hydration is pending, the local state wins; disposed stores are not hydrated later. IndexedDB dispose flush remains best effort because plugin disposal is synchronous.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const T=require("@storix-js/core");function j(s={}){var D,I;const m=s.keyPrefix??"storix",y=new Set(s.include??[]),g=s.storage??"localStorage",b=s.serialize??JSON.stringify,x=s.deserialize??(e=>JSON.parse(e)),S=s.debounce??100,B=((D=s.indexedDB)==null?void 0:D.dbName)??`${m}-persist`,c=((I=s.indexedDB)==null?void 0:I.storeName)??"stores",a=new Map,d=new Map;let u=null;const w=e=>{const t=[e.$id,e.$scopeId];return!(y.size>0&&!t.some(n=>y.has(n)))},l=e=>`${m}:${e.$namespace}:${e.$id}`,h=()=>u||(u=new Promise((e,t)=>{const n=window.indexedDB.open(B,1);n.onupgradeneeded=()=>{const r=n.result;r.objectStoreNames.contains(c)||r.createObjectStore(c)},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error??new Error("IndexedDB open failed"))}),u),P=async e=>{const t=await h(),n=l(e);return new Promise((r,p)=>{const i=t.transaction(c,"readonly").objectStore(c).get(n);i.onsuccess=()=>{const o=i.result;if(typeof o!="string"){r(null);return}try{r(x(o))}catch{r(null)}},i.onerror=()=>p(i.error??new Error("IndexedDB read failed"))})},N=async(e,t)=>{const n=await h(),r=l(e),p=b(t);return new Promise(($,i)=>{const o=n.transaction(c,"readwrite");o.objectStore(c).put(p,r),o.oncomplete=()=>$(),o.onerror=()=>i(o.error??new Error("IndexedDB write failed")),o.onabort=()=>i(o.error??new Error("IndexedDB write aborted"))})},k=async e=>{if(typeof window>"u")return null;if(g==="indexedDB"&&"indexedDB"in window)try{return await P(e)}catch{return null}try{const t=window.localStorage.getItem(l(e));return t?x(t):null}catch{return null}},f=e=>{if(typeof window>"u")return;const t=a.get(e.$scopeId);if(t){if(g==="indexedDB"&&"indexedDB"in window){N(e,t).catch(()=>{});return}try{window.localStorage.setItem(l(e),b(t))}catch{}}},z=e=>{const t=e.$scopeId,n=d.get(t);if(n&&(clearTimeout(n),d.delete(t)),S<=0){f(e);return}const r=setTimeout(()=>{d.delete(t),f(e)},S);d.set(t,r)},M=e=>{const t=e.$scopeId,n=d.get(t);n&&(clearTimeout(n),d.delete(t)),f(e)};return T.definePlugin({name:"persist",onInit(e){const t=e;typeof window>"u"||w(t)&&(async()=>{const n=await k(t);n&&(a.set(t.$scopeId,n),t.$patch(n,"remote"))})()},onMutation(e,t){const n=e;if(typeof window>"u"||!w(n))return;const r=a.get(n.$scopeId)??{};r[t.key]=t.newValue,a.set(n.$scopeId,r),z(n)},onDispose(e){const t=e;w(t)&&M(t)}})}exports.persistPlugin=j;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@storix-js/core");function t(t={}){let n=t.keyPrefix??`storix`,r=new Set(t.include??[]),i=t.storage??`localStorage`,a=t.serialize??JSON.stringify,o=t.deserialize??(e=>JSON.parse(e)),s=t.debounce??100,c=t.indexedDB?.dbName??`${n}-persist`,l=t.indexedDB?.storeName??`stores`,u=new Map,d=new Map,f=new Set,p=new Set,m=new Set,h=new Set,g=null,_=e=>{let t=[e.$id,e.$scopeId];return!(r.size>0&&!t.some(e=>r.has(e)))},v=e=>`${n}:${e.$namespace}:${e.$id}`,y=()=>g||(g=new Promise((e,t)=>{let n=window.indexedDB.open(c,1);n.onupgradeneeded=()=>{let e=n.result;e.objectStoreNames.contains(l)||e.createObjectStore(l)},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error??Error(`IndexedDB open failed`))}),g),b=async e=>{let t=await y(),n=v(e);return new Promise((e,r)=>{let i=t.transaction(l,`readonly`).objectStore(l).get(n);i.onsuccess=()=>{let t=i.result;if(typeof t!=`string`){e(null);return}try{e(o(t))}catch{e(null)}},i.onerror=()=>r(i.error??Error(`IndexedDB read failed`))})},x=async(e,t)=>{let n=await y(),r=v(e),i=a(t);return new Promise((e,t)=>{let a=n.transaction(l,`readwrite`);a.objectStore(l).put(i,r),a.oncomplete=()=>e(),a.onerror=()=>t(a.error??Error(`IndexedDB write failed`)),a.onabort=()=>t(a.error??Error(`IndexedDB write aborted`))})},S=async e=>{if(typeof window>`u`)return null;if(i===`indexedDB`&&`indexedDB`in window)try{return await b(e)}catch{return null}try{let t=window.localStorage.getItem(v(e));return t?o(t):null}catch{return null}},C=e=>{if(typeof window>`u`)return;let t=u.get(e.$scopeId);if(t){if(i===`indexedDB`&&`indexedDB`in window){x(e,t).catch(()=>{});return}try{window.localStorage.setItem(v(e),a(t))}catch{}}},w=e=>{let t=e.$scopeId,n=d.get(t);if(n&&(clearTimeout(n),d.delete(t)),s<=0){C(e);return}let r=setTimeout(()=>{d.delete(t),C(e)},s);d.set(t,r)},T=e=>{let t=e.$scopeId,n=d.get(t);n&&(clearTimeout(n),d.delete(t)),C(e)};return(0,e.definePlugin)({name:`persist`,onInit(e){let t=e;typeof window>`u`||_(t)&&(h.delete(t.$scopeId),f.add(t.$scopeId),(async()=>{let e=await S(t);if(!h.has(t.$scopeId)){if(f.delete(t.$scopeId),p.delete(t.$scopeId)){u.set(t.$scopeId,t.$snapshot());return}if(!e){u.set(t.$scopeId,t.$snapshot());return}m.add(t.$scopeId);try{t.$patch(e,`remote`),u.set(t.$scopeId,t.$snapshot())}finally{m.delete(t.$scopeId)}}})())},onMutation(e){let t=e;typeof window>`u`||_(t)&&(m.has(t.$scopeId)||(f.has(t.$scopeId)&&p.add(t.$scopeId),u.set(t.$scopeId,t.$snapshot()),w(t)))},onDispose(e){let t=e;_(t)&&(h.add(t.$scopeId),f.delete(t.$scopeId),p.delete(t.$scopeId),m.delete(t.$scopeId),T(t),u.delete(t.$scopeId))}})}exports.persistPlugin=t;
package/dist/index.d.ts CHANGED
@@ -12,6 +12,11 @@ export interface PersistPluginOptions {
12
12
  debounce?: number;
13
13
  indexedDB?: IndexedDBPersistOptions;
14
14
  }
15
- export declare function persistPlugin(options?: PersistPluginOptions): import("@storix-js/core").StorePlugin;
15
+ export declare function persistPlugin(options?: PersistPluginOptions): {
16
+ name: string;
17
+ onInit(store: import("@storix-js/core").StoreInstance<{}, {}, {}, {}>): void;
18
+ onMutation(store: import("@storix-js/core").StoreInstance<{}, {}, {}, {}>): void;
19
+ onDispose(store: import("@storix-js/core").StoreInstance<{}, {}, {}, {}>): void;
20
+ };
16
21
  export {};
17
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +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"}
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;AAUD,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB;;;;;EAwN/D"}
package/dist/index.js CHANGED
@@ -1,103 +1,110 @@
1
- import { definePlugin as M } from "@storix-js/core";
2
- function j(s = {}) {
3
- var D, I;
4
- const m = s.keyPrefix ?? "storix", y = new Set(s.include ?? []), x = s.storage ?? "localStorage", b = s.serialize ?? JSON.stringify, g = s.deserialize ?? ((e) => JSON.parse(e)), S = s.debounce ?? 100, B = ((D = s.indexedDB) == null ? void 0 : D.dbName) ?? `${m}-persist`, c = ((I = s.indexedDB) == null ? void 0 : I.storeName) ?? "stores", a = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map();
5
- let u = null;
6
- const w = (e) => {
7
- const t = [e.$id, e.$scopeId];
8
- return !(y.size > 0 && !t.some((n) => y.has(n)));
9
- }, l = (e) => `${m}:${e.$namespace}:${e.$id}`, h = () => u || (u = new Promise((e, t) => {
10
- const n = window.indexedDB.open(B, 1);
11
- n.onupgradeneeded = () => {
12
- const r = n.result;
13
- r.objectStoreNames.contains(c) || r.createObjectStore(c);
14
- }, n.onsuccess = () => e(n.result), n.onerror = () => t(n.error ?? new Error("IndexedDB open failed"));
15
- }), u), P = async (e) => {
16
- const t = await h(), n = l(e);
17
- return new Promise((r, p) => {
18
- const i = t.transaction(c, "readonly").objectStore(c).get(n);
19
- i.onsuccess = () => {
20
- const o = i.result;
21
- if (typeof o != "string") {
22
- r(null);
23
- return;
24
- }
25
- try {
26
- r(g(o));
27
- } catch {
28
- r(null);
29
- }
30
- }, i.onerror = () => p(i.error ?? new Error("IndexedDB read failed"));
31
- });
32
- }, N = async (e, t) => {
33
- const n = await h(), r = l(e), p = b(t);
34
- return new Promise(($, i) => {
35
- const o = n.transaction(c, "readwrite");
36
- o.objectStore(c).put(p, r), o.oncomplete = () => $(), o.onerror = () => i(o.error ?? new Error("IndexedDB write failed")), o.onabort = () => i(o.error ?? new Error("IndexedDB write aborted"));
37
- });
38
- }, k = async (e) => {
39
- if (typeof window > "u") return null;
40
- if (x === "indexedDB" && "indexedDB" in window)
41
- try {
42
- return await P(e);
43
- } catch {
44
- return null;
45
- }
46
- try {
47
- const t = window.localStorage.getItem(l(e));
48
- return t ? g(t) : null;
49
- } catch {
50
- return null;
51
- }
52
- }, f = (e) => {
53
- if (typeof window > "u") return;
54
- const t = a.get(e.$scopeId);
55
- if (t) {
56
- if (x === "indexedDB" && "indexedDB" in window) {
57
- N(e, t).catch(() => {
58
- });
59
- return;
60
- }
61
- try {
62
- window.localStorage.setItem(l(e), b(t));
63
- } catch {
64
- }
65
- }
66
- }, z = (e) => {
67
- const t = e.$scopeId, n = d.get(t);
68
- if (n && (clearTimeout(n), d.delete(t)), S <= 0) {
69
- f(e);
70
- return;
71
- }
72
- const r = setTimeout(() => {
73
- d.delete(t), f(e);
74
- }, S);
75
- d.set(t, r);
76
- }, E = (e) => {
77
- const t = e.$scopeId, n = d.get(t);
78
- n && (clearTimeout(n), d.delete(t)), f(e);
79
- };
80
- return M({
81
- name: "persist",
82
- onInit(e) {
83
- const t = e;
84
- typeof window > "u" || w(t) && (async () => {
85
- const n = await k(t);
86
- n && (a.set(t.$scopeId, n), t.$patch(n, "remote"));
87
- })();
88
- },
89
- onMutation(e, t) {
90
- const n = e;
91
- if (typeof window > "u" || !w(n)) return;
92
- const r = a.get(n.$scopeId) ?? {};
93
- r[t.key] = t.newValue, a.set(n.$scopeId, r), z(n);
94
- },
95
- onDispose(e) {
96
- const t = e;
97
- w(t) && E(t);
98
- }
99
- });
1
+ import { definePlugin as e } from "@storix-js/core";
2
+ //#region src/index.ts
3
+ function t(t = {}) {
4
+ let n = t.keyPrefix ?? "storix", r = new Set(t.include ?? []), i = t.storage ?? "localStorage", a = t.serialize ?? JSON.stringify, o = t.deserialize ?? ((e) => JSON.parse(e)), s = t.debounce ?? 100, c = t.indexedDB?.dbName ?? `${n}-persist`, l = t.indexedDB?.storeName ?? "stores", u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Set(), p = /* @__PURE__ */ new Set(), m = /* @__PURE__ */ new Set(), h = /* @__PURE__ */ new Set(), g = null, _ = (e) => {
5
+ let t = [e.$id, e.$scopeId];
6
+ return !(r.size > 0 && !t.some((e) => r.has(e)));
7
+ }, v = (e) => `${n}:${e.$namespace}:${e.$id}`, y = () => g || (g = new Promise((e, t) => {
8
+ let n = window.indexedDB.open(c, 1);
9
+ n.onupgradeneeded = () => {
10
+ let e = n.result;
11
+ e.objectStoreNames.contains(l) || e.createObjectStore(l);
12
+ }, n.onsuccess = () => e(n.result), n.onerror = () => t(n.error ?? /* @__PURE__ */ Error("IndexedDB open failed"));
13
+ }), g), b = async (e) => {
14
+ let t = await y(), n = v(e);
15
+ return new Promise((e, r) => {
16
+ let i = t.transaction(l, "readonly").objectStore(l).get(n);
17
+ i.onsuccess = () => {
18
+ let t = i.result;
19
+ if (typeof t != "string") {
20
+ e(null);
21
+ return;
22
+ }
23
+ try {
24
+ e(o(t));
25
+ } catch {
26
+ e(null);
27
+ }
28
+ }, i.onerror = () => r(i.error ?? /* @__PURE__ */ Error("IndexedDB read failed"));
29
+ });
30
+ }, x = async (e, t) => {
31
+ let n = await y(), r = v(e), i = a(t);
32
+ return new Promise((e, t) => {
33
+ let a = n.transaction(l, "readwrite");
34
+ a.objectStore(l).put(i, r), a.oncomplete = () => e(), a.onerror = () => t(a.error ?? /* @__PURE__ */ Error("IndexedDB write failed")), a.onabort = () => t(a.error ?? /* @__PURE__ */ Error("IndexedDB write aborted"));
35
+ });
36
+ }, S = async (e) => {
37
+ if (typeof window > "u") return null;
38
+ if (i === "indexedDB" && "indexedDB" in window) try {
39
+ return await b(e);
40
+ } catch {
41
+ return null;
42
+ }
43
+ try {
44
+ let t = window.localStorage.getItem(v(e));
45
+ return t ? o(t) : null;
46
+ } catch {
47
+ return null;
48
+ }
49
+ }, C = (e) => {
50
+ if (typeof window > "u") return;
51
+ let t = u.get(e.$scopeId);
52
+ if (t) {
53
+ if (i === "indexedDB" && "indexedDB" in window) {
54
+ x(e, t).catch(() => {});
55
+ return;
56
+ }
57
+ try {
58
+ window.localStorage.setItem(v(e), a(t));
59
+ } catch {}
60
+ }
61
+ }, w = (e) => {
62
+ let t = e.$scopeId, n = d.get(t);
63
+ if (n && (clearTimeout(n), d.delete(t)), s <= 0) {
64
+ C(e);
65
+ return;
66
+ }
67
+ let r = setTimeout(() => {
68
+ d.delete(t), C(e);
69
+ }, s);
70
+ d.set(t, r);
71
+ }, T = (e) => {
72
+ let t = e.$scopeId, n = d.get(t);
73
+ n && (clearTimeout(n), d.delete(t)), C(e);
74
+ };
75
+ return e({
76
+ name: "persist",
77
+ onInit(e) {
78
+ let t = e;
79
+ typeof window > "u" || _(t) && (h.delete(t.$scopeId), f.add(t.$scopeId), (async () => {
80
+ let e = await S(t);
81
+ if (!h.has(t.$scopeId)) {
82
+ if (f.delete(t.$scopeId), p.delete(t.$scopeId)) {
83
+ u.set(t.$scopeId, t.$snapshot());
84
+ return;
85
+ }
86
+ if (!e) {
87
+ u.set(t.$scopeId, t.$snapshot());
88
+ return;
89
+ }
90
+ m.add(t.$scopeId);
91
+ try {
92
+ t.$patch(e, "remote"), u.set(t.$scopeId, t.$snapshot());
93
+ } finally {
94
+ m.delete(t.$scopeId);
95
+ }
96
+ }
97
+ })());
98
+ },
99
+ onMutation(e) {
100
+ let t = e;
101
+ typeof window > "u" || _(t) && (m.has(t.$scopeId) || (f.has(t.$scopeId) && p.add(t.$scopeId), u.set(t.$scopeId, t.$snapshot()), w(t)));
102
+ },
103
+ onDispose(e) {
104
+ let t = e;
105
+ _(t) && (h.add(t.$scopeId), f.delete(t.$scopeId), p.delete(t.$scopeId), m.delete(t.$scopeId), T(t), u.delete(t.$scopeId));
106
+ }
107
+ });
100
108
  }
101
- export {
102
- j as persistPlugin
103
- };
109
+ //#endregion
110
+ export { t as persistPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storix-js/persist",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -19,13 +19,13 @@
19
19
  "require": "./dist/index.cjs"
20
20
  }
21
21
  },
22
+ "dependencies": {
23
+ "@storix-js/core": "0.3.0"
24
+ },
22
25
  "scripts": {
23
26
  "build": "vite build && tsc -p tsconfig.build.json --emitDeclarationOnly",
24
27
  "dev": "vite build --watch",
25
28
  "test": "vitest run --passWithNoTests",
26
29
  "typecheck": "tsc -p tsconfig.json --noEmit"
27
- },
28
- "dependencies": {
29
- "@storix-js/core": "workspace:*"
30
30
  }
31
- }
31
+ }