@yakocloud/state-vocab 3.0.2 → 3.0.4

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
@@ -188,6 +188,7 @@ Wraps a nested object of `defineState()` nodes and injects dot-separated paths i
188
188
  | Option | Type | Description | Default |
189
189
  |---|---|---|---|
190
190
  | `verbose` | `boolean \| undefined` | Log current state to the browser console on every change | `false` |
191
+ | `verbosePath` | `string \| undefined` | Narrow verbose logging to a specific subtree (dot-separated path). When set, only that subtree is logged instead of the entire state. TypeScript will autocomplete valid paths based on your tree. | `undefined` |
191
192
  | `ssr` | `boolean \| undefined` | Defer storage reads until after hydration (Next.js / SSR) | `false` |
192
193
 
193
194
  ```ts
@@ -208,6 +209,25 @@ Enable verbose logging during development:
208
209
  const storage = setupStorage({ ... }, { verbose: true })
209
210
  ```
210
211
 
212
+ Narrow verbose logging to a specific subtree:
213
+
214
+ ```ts
215
+ const storage = setupStorage({
216
+ user: {
217
+ profile: defineState({ ... }),
218
+ settings: defineState({ ... }),
219
+ },
220
+ cart: {
221
+ items: defineState({ ... }),
222
+ },
223
+ }, {
224
+ verbose: true,
225
+ verbosePath: "user", // only logs changes inside "user.*"
226
+ })
227
+ ```
228
+
229
+ TypeScript will only accept paths that exist in your tree — `"user"`, `"user.profile"`, `"cart.items"`, etc. Invalid paths are caught at compile time.
230
+
211
231
  ### SSR / Next.js
212
232
 
213
233
  When using localStorage or sessionStorage in a Next.js app, the server renders with `defaultValue` while the client reads the persisted value — causing a hydration mismatch. Pass `ssr: true` to fix this:
@@ -409,6 +429,7 @@ createRoot(document.getElementById('root')!).render(<Page />)
409
429
  | Option | Type | Default |
410
430
  |---|---|---|
411
431
  | `verbose` | `boolean \| undefined` | `false` |
432
+ | `verbosePath` | `Path<T> \| undefined` | `undefined` |
412
433
  | `ssr` | `boolean \| undefined` | `false` |
413
434
 
414
435
  Returns a proxied copy of `tree` with paths injected into all leaf nodes.
@@ -422,4 +443,4 @@ Returns a proxied copy of `tree` with paths injected into all leaf nodes.
422
443
  | `onSet` | `(next: T, prev: T) => void \| undefined` | Callback after state change |
423
444
  | `bidirectional` | `true \| undefined` | Sync state across browser tabs |
424
445
 
425
- Returns `[value, setValue, resetValue]`.
446
+ Returns `[value, setValue, resetValue]`
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("react"),R=Symbol("state-def"),T=Symbol("state-path"),z=Symbol("state-verbose"),x=Symbol("state-ssr");function C(t,e,s){if(!e)return t;const o=e.split(".");let c=t;for(const r of o)if(c!==null&&typeof c=="object"&&r in c)c=c[r];else return s;return c===void 0?s:c}function j(t,e,s){const o=e.replace(/\[(\d+)\]/g,".$1").split(".");let c=t;for(let r=0;r<o.length-1;r++){const n=o[r],a=o[r+1];(c[n]===void 0||c[n]===null)&&(c[n]=/^\d+$/.test(a)?[]:{}),c=c[n]}return c[o[o.length-1]]=s,t}function D(t,e=0){let s;return function(...o){s!==void 0&&clearTimeout(s),s=setTimeout(()=>{s=void 0,t.apply(this,o)},e)}}function O(t,e,s=[]){return f.useMemo(()=>D(t,e),s)}function P(t){const e=JSON.stringify(t,null,2).split(`
2
- `),s=[],o=[];for(const c of e){const r=c.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);if(r){const[,n,a,d,h]=r;s.push(`${n}%c"${a}"%c${d}%c${h}`),o.push("color: #9cdcfe; font-weight: bold","color: #cccccc","color: #ce9178")}else s.push(`%c${c}`),o.push("color: #cccccc")}console.log(s.join(`
3
- `),...o,t)}const M=t=>typeof t=="function",_=t=>typeof t=="function",E=t=>typeof t<"u",$=t=>_(t)?t():t,A=typeof window>"u",F=A?f.useEffect:f.useLayoutEffect;class J{#e;#t;constructor(){this.#e={},this.#t=new Set}subscribe(e){return this.#t.add(e),()=>this.#t.delete(e)}getClientSnapshot(){return this.#e}getServerSnapshot(){return this.#e}get(e){return C(this.#e,e)}set(e,s){const o=C(this.#e,e),c=M(s)?s(o):s,r={...this.#e};j(r,e,c),this.#e=r,this.#t.forEach(n=>n())}}function B(t={}){const e=new J,s=t.serialize??JSON.stringify,o=t.deserialize??JSON.parse,c=(r,n,a)=>{const d=n.getItem(r);d===null?E(a)&&n.setItem(r,s(a)):e.set(r,o(d))};return{[R]:!0,[T]:"",[z]:!1,[x]:!1,useState(r){const n=A?void 0:$(t.storage),a=$(t.defaultValue),d=t.bidirectional;r??={};const h=$(r.defaultValue)??a,p=r.bidirectional??d,u=O(r.onSet??(()=>{}),r.delayedSet,[]),i=this[T],S=this[z],y=this[x],g=f.useRef(void 0),w=f.useRef(!1);if(!w.current){w.current=!0;let l=e.get(i);E(l)||(l=h,E(l)&&e.set(i,l)),!y&&n&&c(i,n,l)}const V=f.useSyncExternalStore(e.subscribe.bind(e),e.getClientSnapshot.bind(e),e.getServerSnapshot.bind(e));S&&P(V);const v=C(V,i,h);g.current=v,F(()=>{!y||!n||c(i,n,v)},[]);const b=f.useEffectEvent(l=>{if(l.key!==i)return;const m=l.newValue,I=(m===null?null:o(m))??h;E(I)&&(e.set(i,I),u(I,g.current))});f.useEffect(()=>{if(p)return window.addEventListener("storage",b),()=>window.removeEventListener("storage",b)},[p]);const k=f.useCallback(l=>{const m=M(l)?l(g.current):l;e.set(i,m),u(m,g.current),n&&n.setItem(i,s(m))},[i,n,s,u]),N=f.useCallback(()=>{const l=h;if(!E(l)){n?.removeItem(i);return}e.set(i,l),u(l,g.current),n&&n.setItem(i,s(l))},[i,h,n,s,u]);return[v,k,N]},toString(){return this[T]}}}function L(t,e){const{path:s="",verbose:o,ssr:c,cache:r}=e;let n=r.proxy.get(t);n||(n=new Map,r.proxy.set(t,n));const a=n.get(s);if(a)return a;const d=new Proxy(t,{get(h,p){const u=h[p],i=s?`${s}.${String(p)}`:String(p);if(u&&typeof u=="object"&&R in u){const S=u;let y=r.leaf.get(S);y||(y=new Map,r.leaf.set(S,y));const g=y.get(i);if(g)return g;const w=Reflect.ownKeys(S).filter(b=>typeof S[b]=="function"),V=Object.fromEntries(w.map(b=>[b,(...k)=>S[b].call({...S,[T]:i,[z]:o,[x]:c},...k)])),v={...S,...V};return y.set(i,v),v}return u&&typeof u=="object"?L(u,{...e,path:i}):u}});return n.set(s,d),d}function K(t,e){return L(t,{...e,cache:{proxy:new WeakMap,leaf:new WeakMap}})}exports.defineState=B;exports.setupStorage=K;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("react"),_=Symbol("state-def"),k=Symbol("state-path"),R=Symbol("state-verbose"),x=Symbol("state-verbose-path"),A=Symbol("state-ssr");function I(t,e,s){if(!e)return t;const i=e.split(".");let c=t;for(const r of i)if(c!==null&&typeof c=="object"&&r in c)c=c[r];else return s;return c===void 0?s:c}function j(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let c=t;for(let r=0;r<i.length-1;r++){const n=i[r],l=i[r+1];(c[n]===void 0||c[n]===null)&&(c[n]=/^\d+$/.test(l)?[]:{}),c=c[n]}return c[i[i.length-1]]=s,t}function D(t,e=0){let s;return function(...i){s!==void 0&&clearTimeout(s),s=setTimeout(()=>{s=void 0,t.apply(this,i)},e)}}function B(t,e,s=[]){return d.useMemo(()=>D(t,e),s)}function M(t){const e=JSON.stringify(t,null,2).split(`
2
+ `),s=[],i=[];for(const c of e){const r=c.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);if(r){const[,n,l,h,u]=r;s.push(`${n}%c"${l}"%c${h}%c${u}`),i.push("color: #9cdcfe; font-weight: bold","color: #cccccc","color: #ce9178")}else s.push(`%c${c}`),i.push("color: #cccccc")}console.log(s.join(`
3
+ `),...i,t)}const L=t=>typeof t=="function",F=t=>typeof t=="function",T=t=>typeof t<"u",P=t=>F(t)?t():t,C=typeof window>"u",J=C?d.useEffect:d.useLayoutEffect;class H{#e;#t;constructor(){this.#e={},this.#t=new Set}subscribe(e){return this.#t.add(e),()=>this.#t.delete(e)}getClientSnapshot(){return this.#e}getServerSnapshot(){return this.#e}get(e){return I(this.#e,e)}set(e,s){const i=I(this.#e,e),c=L(s)?s(i):s,r={...this.#e};j(r,e,c),this.#e=r,this.#t.forEach(n=>n())}}function K(t={}){const e=new H,s=t.serialize??JSON.stringify,i=t.deserialize??JSON.parse,c=(r,n,l)=>{const h=n.getItem(r);h===null?T(l)&&n.setItem(r,s(l)):e.set(r,i(h))};return{[_]:!0,[k]:"",[R]:!1,[x]:"",[A]:!1,useState(r){const n=C?void 0:P(t.storage),l=P(t.defaultValue),h=t.bidirectional;r??={};const u=P(r.defaultValue)??l,w=r.bidirectional??h,S=B(r.onSet??(()=>{}),r.delayedSet,[]),o=this[k],v=this[R],f=this[x],y=this[A],b=d.useRef(void 0),V=d.useRef(!1);if(!V.current){V.current=!0;let a=C?void 0:e.get(o);T(a)||(a=u,T(a)&&e.set(o,a)),!y&&n&&c(o,n,a)}const E=d.useSyncExternalStore(e.subscribe.bind(e),e.getClientSnapshot.bind(e),e.getServerSnapshot.bind(e));if(v)if(f){const a=I(E,f);a&&M(a)}else M(E);const p=I(E,o,u);b.current=p,J(()=>{!y||!n||c(o,n,p)},[]);const g=d.useEffectEvent(a=>{if(a.key!==o)return;const m=a.newValue,z=(m===null?null:i(m))??u;T(z)&&(e.set(o,z),S(z,b.current))});d.useEffect(()=>{if(w)return window.addEventListener("storage",g),()=>window.removeEventListener("storage",g)},[w]);const $=d.useCallback(a=>{const m=L(a)?a(b.current):a;e.set(o,m),S(m,b.current),n&&n.setItem(o,s(m))},[o,n,S]),O=d.useCallback(()=>{const a=u;if(!T(a)){n?.removeItem(o);return}e.set(o,a),S(a,b.current),n&&n.setItem(o,s(a))},[o,u,n,S]);return[p,$,O]},toString(){return this[k]}}}function N(t,e){const{path:s="",verbose:i,verbosePath:c,ssr:r,cache:n}=e;let l=n.proxy.get(t);l||(l=new Map,n.proxy.set(t,l));const h=l.get(s);if(h)return h;const u=new Proxy(t,{get(w,S){const o=w[S],v=s?`${s}.${String(S)}`:String(S);if(o&&typeof o=="object"&&_ in o){const f=o;let y=n.leaf.get(f);y||(y=new Map,n.leaf.set(f,y));const b=y.get(v);if(b)return b;const V=Reflect.ownKeys(f).filter(g=>typeof f[g]=="function"),E=Object.fromEntries(V.map(g=>[g,(...$)=>f[g].call({...f,[k]:v,[R]:i,[x]:c,[A]:r},...$)])),p={...f,...E};return y.set(v,p),p}return o&&typeof o=="object"?N(o,{...e,path:v}):o}});return l.set(s,u),u}function W(t,e){return N(t,{...e,verbosePath:e?.verbosePath??"",cache:{proxy:new WeakMap,leaf:new WeakMap}})}exports.defineState=K;exports.setupStorage=W;
@@ -1,61 +1,61 @@
1
- import { useMemo as j, useRef as C, useSyncExternalStore as F, useEffect as A, useLayoutEffect as J, useEffectEvent as O, useCallback as R } from "react";
2
- const L = Symbol("state-def"), V = Symbol("state-path"), k = Symbol("state-verbose"), z = Symbol("state-ssr");
3
- function x(t, e, n) {
1
+ import { useMemo as B, useRef as C, useSyncExternalStore as F, useEffect as M, useLayoutEffect as J, useEffectEvent as H, useCallback as _ } from "react";
2
+ const N = Symbol("state-def"), V = Symbol("state-path"), x = Symbol("state-verbose"), P = Symbol("state-verbose-path"), A = Symbol("state-ssr");
3
+ function I(t, e, s) {
4
4
  if (!e)
5
5
  return t;
6
- const o = e.split(".");
7
- let c = t;
8
- for (const r of o)
9
- if (c !== null && typeof c == "object" && r in c)
10
- c = c[r];
6
+ const i = e.split(".");
7
+ let o = t;
8
+ for (const r of i)
9
+ if (o !== null && typeof o == "object" && r in o)
10
+ o = o[r];
11
11
  else
12
- return n;
13
- return c === void 0 ? n : c;
12
+ return s;
13
+ return o === void 0 ? s : o;
14
14
  }
15
- function P(t, e, n) {
16
- const o = e.replace(/\[(\d+)\]/g, ".$1").split(".");
17
- let c = t;
18
- for (let r = 0; r < o.length - 1; r++) {
19
- const s = o[r], a = o[r + 1];
20
- (c[s] === void 0 || c[s] === null) && (c[s] = /^\d+$/.test(a) ? [] : {}), c = c[s];
15
+ function K(t, e, s) {
16
+ const i = e.replace(/\[(\d+)\]/g, ".$1").split(".");
17
+ let o = t;
18
+ for (let r = 0; r < i.length - 1; r++) {
19
+ const n = i[r], a = i[r + 1];
20
+ (o[n] === void 0 || o[n] === null) && (o[n] = /^\d+$/.test(a) ? [] : {}), o = o[n];
21
21
  }
22
- return c[o[o.length - 1]] = n, t;
22
+ return o[i[i.length - 1]] = s, t;
23
23
  }
24
- function B(t, e = 0) {
25
- let n;
26
- return function(...o) {
27
- n !== void 0 && clearTimeout(n), n = setTimeout(() => {
28
- n = void 0, t.apply(this, o);
24
+ function W(t, e = 0) {
25
+ let s;
26
+ return function(...i) {
27
+ s !== void 0 && clearTimeout(s), s = setTimeout(() => {
28
+ s = void 0, t.apply(this, i);
29
29
  }, e);
30
30
  };
31
31
  }
32
- function K(t, e, n = []) {
33
- return j(
34
- () => B(t, e),
32
+ function q(t, e, s = []) {
33
+ return B(
34
+ () => W(t, e),
35
35
  // eslint-disable-next-line react-hooks/exhaustive-deps
36
- n
36
+ s
37
37
  );
38
38
  }
39
- function W(t) {
39
+ function L(t) {
40
40
  const e = JSON.stringify(t, null, 2).split(`
41
- `), n = [], o = [];
42
- for (const c of e) {
43
- const r = c.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);
41
+ `), s = [], i = [];
42
+ for (const o of e) {
43
+ const r = o.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);
44
44
  if (r) {
45
- const [, s, a, f, d] = r;
46
- n.push(`${s}%c"${a}"%c${f}%c${d}`), o.push(
45
+ const [, n, a, d, u] = r;
46
+ s.push(`${n}%c"${a}"%c${d}%c${u}`), i.push(
47
47
  "color: #9cdcfe; font-weight: bold",
48
48
  "color: #cccccc",
49
49
  "color: #ce9178"
50
50
  );
51
51
  } else
52
- n.push(`%c${c}`), o.push("color: #cccccc");
52
+ s.push(`%c${o}`), i.push("color: #cccccc");
53
53
  }
54
- console.log(n.join(`
55
- `), ...o, t);
54
+ console.log(s.join(`
55
+ `), ...i, t);
56
56
  }
57
- const M = (t) => typeof t == "function", H = (t) => typeof t == "function", m = (t) => typeof t < "u", $ = (t) => H(t) ? t() : t, N = typeof window > "u", q = N ? A : J;
58
- class G {
57
+ const D = (t) => typeof t == "function", G = (t) => typeof t == "function", E = (t) => typeof t < "u", z = (t) => G(t) ? t() : t, R = typeof window > "u", Q = R ? M : J;
58
+ class U {
59
59
  #e;
60
60
  #t;
61
61
  constructor() {
@@ -71,87 +71,83 @@ class G {
71
71
  return this.#e;
72
72
  }
73
73
  get(e) {
74
- return x(this.#e, e);
74
+ return I(this.#e, e);
75
75
  }
76
- set(e, n) {
77
- const o = x(this.#e, e), c = M(n) ? n(o) : n, r = { ...this.#e };
78
- P(r, e, c), this.#e = r, this.#t.forEach((s) => s());
76
+ set(e, s) {
77
+ const i = I(this.#e, e), o = D(s) ? s(i) : s, r = { ...this.#e };
78
+ K(r, e, o), this.#e = r, this.#t.forEach((n) => n());
79
79
  }
80
80
  }
81
- function X(t = {}) {
82
- const e = new G(), n = t.serialize ?? JSON.stringify, o = t.deserialize ?? JSON.parse, c = (r, s, a) => {
83
- const f = s.getItem(r);
84
- f === null ? m(a) && s.setItem(r, n(a)) : e.set(r, o(f));
81
+ function Z(t = {}) {
82
+ const e = new U(), s = t.serialize ?? JSON.stringify, i = t.deserialize ?? JSON.parse, o = (r, n, a) => {
83
+ const d = n.getItem(r);
84
+ d === null ? E(a) && n.setItem(r, s(a)) : e.set(r, i(d));
85
85
  };
86
86
  return {
87
- [L]: !0,
87
+ [N]: !0,
88
88
  // marks this object as a leaf in the router tree
89
89
  [V]: "",
90
90
  // placeholder; injected at runtime by injectPaths()
91
- [k]: !1,
91
+ [x]: !1,
92
92
  // placeholder
93
- [z]: !1,
93
+ [P]: "",
94
+ // placeholder
95
+ [A]: !1,
94
96
  // placeholder
95
97
  useState(r) {
96
- const s = N ? void 0 : $(t.storage), a = $(t.defaultValue), f = t.bidirectional;
98
+ const n = R ? void 0 : z(t.storage), a = z(t.defaultValue), d = t.bidirectional;
97
99
  r ??= {};
98
- const d = $(r.defaultValue) ?? a, p = r.bidirectional ?? f, u = K(
100
+ const u = z(r.defaultValue) ?? a, w = r.bidirectional ?? d, h = q(
99
101
  r.onSet ?? (() => {
100
102
  }),
101
103
  r.delayedSet,
102
104
  []
103
- ), i = this[V], h = this[k], y = this[z], S = C(void 0), E = C(!1);
104
- if (!E.current) {
105
- E.current = !0;
106
- let l = e.get(i);
107
- m(l) || (l = d, m(l) && e.set(i, l)), !y && s && c(i, s, l);
105
+ ), c = this[V], g = this[x], f = this[P], S = this[A], y = C(void 0), T = C(!1);
106
+ if (!T.current) {
107
+ T.current = !0;
108
+ let l = R ? void 0 : e.get(c);
109
+ E(l) || (l = u, E(l) && e.set(c, l)), !S && n && o(c, n, l);
108
110
  }
109
- const w = F(
111
+ const m = F(
110
112
  e.subscribe.bind(e),
111
113
  e.getClientSnapshot.bind(e),
112
114
  e.getServerSnapshot.bind(e)
113
115
  );
114
- h && W(w);
115
- const b = x(w, i, d);
116
- S.current = b, q(() => {
117
- !y || !s || c(i, s, b);
116
+ if (g)
117
+ if (f) {
118
+ const l = I(m, f);
119
+ l && L(l);
120
+ } else
121
+ L(m);
122
+ const v = I(m, c, u);
123
+ y.current = v, Q(() => {
124
+ !S || !n || o(c, n, v);
118
125
  }, []);
119
- const g = O((l) => {
120
- if (l.key !== i)
126
+ const b = H((l) => {
127
+ if (l.key !== c)
121
128
  return;
122
- const v = l.newValue, I = (v === null ? null : o(v)) ?? d;
123
- m(I) && (e.set(i, I), u(I, S.current));
129
+ const p = l.newValue, k = (p === null ? null : i(p)) ?? u;
130
+ E(k) && (e.set(c, k), h(k, y.current));
124
131
  });
125
- A(() => {
126
- if (p)
127
- return window.addEventListener("storage", g), () => window.removeEventListener("storage", g);
128
- }, [p]);
129
- const T = R((l) => {
130
- const v = M(l) ? l(S.current) : l;
131
- e.set(i, v), u(v, S.current), s && s.setItem(i, n(v));
132
- }, [
133
- i,
134
- s,
135
- n,
136
- u
137
- ]), _ = R(() => {
138
- const l = d;
139
- if (!m(l)) {
140
- s?.removeItem(i);
132
+ M(() => {
133
+ if (w)
134
+ return window.addEventListener("storage", b), () => window.removeEventListener("storage", b);
135
+ }, [w]);
136
+ const $ = _((l) => {
137
+ const p = D(l) ? l(y.current) : l;
138
+ e.set(c, p), h(p, y.current), n && n.setItem(c, s(p));
139
+ }, [c, n, h]), j = _(() => {
140
+ const l = u;
141
+ if (!E(l)) {
142
+ n?.removeItem(c);
141
143
  return;
142
144
  }
143
- e.set(i, l), u(l, S.current), s && s.setItem(i, n(l));
144
- }, [
145
- i,
146
- d,
147
- s,
148
- n,
149
- u
150
- ]);
145
+ e.set(c, l), h(l, y.current), n && n.setItem(c, s(l));
146
+ }, [c, u, n, h]);
151
147
  return [
152
- b,
153
- T,
154
- _
148
+ v,
149
+ $,
150
+ j
155
151
  ];
156
152
  },
157
153
  /** Returns the fully qualified job name (dot-separated path). */
@@ -160,57 +156,60 @@ function X(t = {}) {
160
156
  }
161
157
  };
162
158
  }
163
- function D(t, e) {
159
+ function O(t, e) {
164
160
  const {
165
- path: n = "",
166
- verbose: o,
167
- ssr: c,
168
- cache: r
161
+ path: s = "",
162
+ verbose: i,
163
+ verbosePath: o,
164
+ ssr: r,
165
+ cache: n
169
166
  } = e;
170
- let s = r.proxy.get(t);
171
- s || (s = /* @__PURE__ */ new Map(), r.proxy.set(t, s));
172
- const a = s.get(n);
173
- if (a)
174
- return a;
175
- const f = new Proxy(t, {
176
- get(d, p) {
177
- const u = d[p], i = n ? `${n}.${String(p)}` : String(p);
178
- if (u && typeof u == "object" && L in u) {
179
- const h = u;
180
- let y = r.leaf.get(h);
181
- y || (y = /* @__PURE__ */ new Map(), r.leaf.set(h, y));
182
- const S = y.get(i);
183
- if (S)
184
- return S;
185
- const E = Reflect.ownKeys(h).filter(
186
- (g) => typeof h[g] == "function"
187
- ), w = Object.fromEntries(
188
- E.map((g) => [
189
- g,
190
- (...T) => h[g].call(
167
+ let a = n.proxy.get(t);
168
+ a || (a = /* @__PURE__ */ new Map(), n.proxy.set(t, a));
169
+ const d = a.get(s);
170
+ if (d)
171
+ return d;
172
+ const u = new Proxy(t, {
173
+ get(w, h) {
174
+ const c = w[h], g = s ? `${s}.${String(h)}` : String(h);
175
+ if (c && typeof c == "object" && N in c) {
176
+ const f = c;
177
+ let S = n.leaf.get(f);
178
+ S || (S = /* @__PURE__ */ new Map(), n.leaf.set(f, S));
179
+ const y = S.get(g);
180
+ if (y)
181
+ return y;
182
+ const T = Reflect.ownKeys(f).filter(
183
+ (b) => typeof f[b] == "function"
184
+ ), m = Object.fromEntries(
185
+ T.map((b) => [
186
+ b,
187
+ (...$) => f[b].call(
191
188
  {
192
- ...h,
193
- [V]: i,
194
- [k]: o,
195
- [z]: c
189
+ ...f,
190
+ [V]: g,
191
+ [x]: i,
192
+ [P]: o,
193
+ [A]: r
196
194
  },
197
- ...T
195
+ ...$
198
196
  )
199
197
  ])
200
- ), b = { ...h, ...w };
201
- return y.set(i, b), b;
198
+ ), v = { ...f, ...m };
199
+ return S.set(g, v), v;
202
200
  }
203
- return u && typeof u == "object" ? D(u, {
201
+ return c && typeof c == "object" ? O(c, {
204
202
  ...e,
205
- path: i
206
- }) : u;
203
+ path: g
204
+ }) : c;
207
205
  }
208
206
  });
209
- return s.set(n, f), f;
207
+ return a.set(s, u), u;
210
208
  }
211
- function Y(t, e) {
212
- return D(t, {
209
+ function ee(t, e) {
210
+ return O(t, {
213
211
  ...e,
212
+ verbosePath: e?.verbosePath ?? "",
214
213
  cache: {
215
214
  proxy: /* @__PURE__ */ new WeakMap(),
216
215
  leaf: /* @__PURE__ */ new WeakMap()
@@ -218,6 +217,6 @@ function Y(t, e) {
218
217
  });
219
218
  }
220
219
  export {
221
- X as defineState,
222
- Y as setupStorage
220
+ Z as defineState,
221
+ ee as setupStorage
223
222
  };
@@ -1,4 +1,5 @@
1
1
  export declare const STATE_DEFINITION: unique symbol;
2
2
  export declare const STATE_PATH: unique symbol;
3
3
  export declare const STATE_VERBOSE: unique symbol;
4
+ export declare const STATE_VERBOSE_PATH: unique symbol;
4
5
  export declare const STATE_SSR: unique symbol;
@@ -1,7 +1,14 @@
1
- type InjectPathsOptions = {
1
+ import { STATE_DEFINITION } from "./constants";
2
+ type Path<T, Prefix extends string = ""> = {
3
+ [K in keyof T & string]: T[K] extends object ? T[K] extends {
4
+ [STATE_DEFINITION]: unknown;
5
+ } ? `${Prefix}${K}` : `${Prefix}${K}` | Path<T[K], `${Prefix}${K}.`> : `${Prefix}${K}`;
6
+ }[keyof T & string];
7
+ type InjectPathsOptions<T extends object> = {
2
8
  path: string;
3
9
  verbose: boolean;
10
+ verbosePath: Path<T>;
4
11
  ssr: boolean;
5
12
  };
6
- export declare function setupStorage<T extends object>(native: T, options?: Partial<Omit<InjectPathsOptions, "path">>): T;
13
+ export declare function setupStorage<T extends object>(native: T, options?: Partial<Omit<InjectPathsOptions<T>, "path">>): T;
7
14
  export {};
@@ -1,4 +1,4 @@
1
- import { STATE_DEFINITION, STATE_PATH, STATE_SSR, STATE_VERBOSE } from "./constants";
1
+ import { STATE_DEFINITION, STATE_PATH, STATE_SSR, STATE_VERBOSE, STATE_VERBOSE_PATH } from "./constants";
2
2
  import type { Deserialize, Serialize, ValueOrFactory, ValueOrTransformer } from "./state.types";
3
3
  export declare function defineState<D>(definitionOptions?: {
4
4
  storage?: ValueOrFactory<Storage>;
@@ -10,10 +10,12 @@ export declare function defineState<D>(definitionOptions?: {
10
10
  [STATE_DEFINITION]: boolean;
11
11
  [STATE_PATH]: string;
12
12
  [STATE_VERBOSE]: boolean;
13
+ [STATE_VERBOSE_PATH]: string;
13
14
  [STATE_SSR]: boolean;
14
15
  useState(this: {
15
16
  [STATE_PATH]: string;
16
17
  [STATE_VERBOSE]: boolean;
18
+ [STATE_VERBOSE_PATH]: string;
17
19
  [STATE_SSR]: boolean;
18
20
  }, options?: {
19
21
  defaultValue?: ValueOrFactory<D>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yakocloud/state-vocab",
3
- "version": "3.0.2",
3
+ "version": "3.0.4",
4
4
  "main": "dist/state-vocab.cjs.js",
5
5
  "module": "dist/state-vocab.es.js",
6
6
  "types": "dist/types/index.d.ts",