@yakocloud/state-vocab 4.2.0 → 4.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 +62 -62
- package/dist/client.cjs.js +1 -1
- package/dist/client.es.js +17 -16
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -1
- package/dist/{provider-client-DRdFy5dG.js → provider-client-DA53zfcT.js} +1 -1
- package/dist/{provider-client-BhPeK8Kz.mjs → provider-client-DLa3_Ms9.mjs} +1 -1
- package/dist/server.cjs.js +1 -1
- package/dist/server.es.js +51 -53
- package/dist/types/context.server.d.ts +3 -2
- package/dist/types/setup.client.d.ts +2 -18
- package/dist/types/setup.client.types.d.ts +29 -0
- package/dist/types/setup.client.utils.d.ts +3 -1
- package/dist/types/setup.d.ts +1 -13
- package/dist/types/setup.server.d.ts +4 -35
- package/dist/types/setup.server.types.d.ts +25 -0
- package/dist/types/setup.server.utils.d.ts +3 -0
- package/dist/types/setup.types.d.ts +12 -15
- package/dist/types/state.d.ts +1 -1
- package/dist/utils-0CTNJ4ZE.js +3 -0
- package/dist/utils-xV3x3fTc.mjs +57 -0
- package/package.json +1 -1
- package/dist/utils-CuApuc3e.js +0 -3
- package/dist/utils-xNWifFE9.mjs +0 -73
package/README.md
CHANGED
|
@@ -117,7 +117,7 @@ npm install @yakocloud/state-vocab react react-dom
|
|
|
117
117
|
|
|
118
118
|
## Quick Start
|
|
119
119
|
|
|
120
|
-
Define your storage tree once (`setupStorage`/`defineState`), call `clientify` to attach React hooks. If you use
|
|
120
|
+
Define your storage tree once (`setupStorage`/`defineState`), call `clientify` to attach React hooks. If you use React Server Components (RSC), wrap the relevant subtree with `StateVocabProvider` and call `serverify` to attach server-side `.getState()` methods. Use state anywhere in the tree.
|
|
121
121
|
|
|
122
122
|
Library SSR-requirements:
|
|
123
123
|
- `Per-request store`: A Next.js server can handle multiple requests simultaneously. This means that the store should be created per request and should not be shared across requests.
|
|
@@ -366,28 +366,14 @@ export const storage = setupStorage({
|
|
|
366
366
|
})
|
|
367
367
|
```
|
|
368
368
|
|
|
369
|
-
**2. Create
|
|
370
|
-
|
|
371
|
-
Each storage tree needs its own React context so that multiple independent providers can coexist on the same page without their state bleeding into each other.
|
|
372
|
-
|
|
373
|
-
```ts
|
|
374
|
-
// storage.context.client.ts ("use client")
|
|
375
|
-
"use client"
|
|
376
|
-
|
|
377
|
-
import { createContext } from 'react'
|
|
378
|
-
|
|
379
|
-
export const StorageClientContext = createContext({})
|
|
380
|
-
```
|
|
369
|
+
**2. Create server and client storage handles:**
|
|
381
370
|
|
|
382
371
|
```ts
|
|
383
372
|
// storage.server.ts
|
|
384
373
|
import { storage } from '@/storage'
|
|
385
374
|
import { serverify } from '@yakocloud/state-vocab/server'
|
|
386
|
-
import { StorageClientContext } from '@/storage.context.client'
|
|
387
375
|
|
|
388
|
-
export const serverStorage = serverify(storage
|
|
389
|
-
clientContext: StorageClientContext,
|
|
390
|
-
})
|
|
376
|
+
export const serverStorage = serverify(storage)
|
|
391
377
|
```
|
|
392
378
|
|
|
393
379
|
```ts
|
|
@@ -396,11 +382,8 @@ export const serverStorage = serverify(storage, {
|
|
|
396
382
|
|
|
397
383
|
import { storage } from '@/storage'
|
|
398
384
|
import { clientify } from '@yakocloud/state-vocab/client'
|
|
399
|
-
import { StorageClientContext } from '@/storage.context.client'
|
|
400
385
|
|
|
401
|
-
export const clientStorage = clientify(storage
|
|
402
|
-
clientContext: StorageClientContext,
|
|
403
|
-
})
|
|
386
|
+
export const clientStorage = clientify(storage)
|
|
404
387
|
```
|
|
405
388
|
|
|
406
389
|
**3. Seed initial state in the server component and read it in Server and Client children:**
|
|
@@ -412,10 +395,6 @@ import { serverStorage } from '@/storage.server'
|
|
|
412
395
|
const { StateVocabProvider } = serverStorage
|
|
413
396
|
|
|
414
397
|
export default async function Page() {
|
|
415
|
-
// Call start() before rendering the provider — registers the store for this
|
|
416
|
-
// request so child components can await getState() concurrently
|
|
417
|
-
serverStorage.start()
|
|
418
|
-
|
|
419
398
|
// Fetch data from DB / API
|
|
420
399
|
const user = await db.getUser()
|
|
421
400
|
|
|
@@ -437,8 +416,8 @@ export default async function Page() {
|
|
|
437
416
|
import { serverStorage } from '@/storage.server'
|
|
438
417
|
|
|
439
418
|
export default async function UserInfo() {
|
|
440
|
-
const name =
|
|
441
|
-
const role =
|
|
419
|
+
const name = serverStorage.user.name.getState()
|
|
420
|
+
const role = serverStorage.user.role.getState()
|
|
442
421
|
|
|
443
422
|
return <p>{name} — {role}</p>
|
|
444
423
|
}
|
|
@@ -460,41 +439,67 @@ export default function UserInfoClient() {
|
|
|
460
439
|
|
|
461
440
|
#### Multiple independent storage trees
|
|
462
441
|
|
|
463
|
-
Because each `serverify`/`clientify` pair is bound to its own context, you can have multiple independent providers active at the same time — for example, a layout-level store and a page-level store — without them interfering with each other:
|
|
442
|
+
Because each `serverify`/`clientify` pair is bound to its own React context, you can have multiple independent providers active at the same time — for example, a layout-level store and a page-level store — without them interfering with each other. Pass a `clientContext` to link the server and client sides of each tree:
|
|
464
443
|
|
|
465
444
|
```ts
|
|
466
|
-
// layout.context.client.ts ("use client")
|
|
467
|
-
export const LayoutClientContext = createContext({})
|
|
468
|
-
|
|
469
|
-
// page.context.client.ts ("use client")
|
|
470
|
-
export const PageClientContext = createContext({})
|
|
471
|
-
|
|
472
445
|
// layout.storage.server.ts
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
})
|
|
446
|
+
import { createContext } from 'react'
|
|
447
|
+
export const LayoutClientContext = createContext({})
|
|
448
|
+
export const layoutServerStorage = serverify(layoutStorage, { clientContext: LayoutClientContext })
|
|
476
449
|
|
|
477
450
|
// layout.storage.client.ts ("use client")
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
})
|
|
451
|
+
"use client"
|
|
452
|
+
export const layoutClientStorage = clientify(layoutStorage, { clientContext: LayoutClientContext })
|
|
481
453
|
|
|
482
454
|
// page.storage.server.ts
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
})
|
|
455
|
+
import { createContext } from 'react'
|
|
456
|
+
export const PageClientContext = createContext({})
|
|
457
|
+
export const pageServerStorage = serverify(pageStorage, { clientContext: PageClientContext })
|
|
486
458
|
|
|
487
459
|
// page.storage.client.ts ("use client")
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
})
|
|
460
|
+
"use client"
|
|
461
|
+
export const pageClientStorage = clientify(pageStorage, { clientContext: PageClientContext })
|
|
491
462
|
```
|
|
492
463
|
|
|
493
464
|
Each `StateVocabProvider` wraps its own subtree; a component that calls `pageClientStorage.user.name.useState()` reads only from the nearest `pageServerStorage.StateVocabProvider`, not from the layout provider.
|
|
494
465
|
|
|
466
|
+
#### Next.js App Router: layout and page are isolated contexts
|
|
467
|
+
|
|
468
|
+
In Next.js App Router, **layouts do not re-render during client-side navigation between pages**. Layout and page run as independent React render passes — the layout renders once on entry and stays mounted; the page renders fresh on every navigation.
|
|
469
|
+
|
|
470
|
+
Because `React.cache()` (which backs the per-request server store) is scoped to a single render pass, layout and page never share the same cache scope:
|
|
471
|
+
|
|
472
|
+
- A page server component **cannot** call `layoutServerStorage.someField.getState()` — the layout's `StateVocabProvider` ran in a separate pass, so its vocab is not in the page's cache scope.
|
|
473
|
+
- A layout server component **cannot** call `pageServerStorage.someField.getState()` for the same reason.
|
|
474
|
+
- **Each storage tree must be both seeded and consumed within the same route segment.**
|
|
475
|
+
|
|
476
|
+
```tsx
|
|
477
|
+
// ✅ Correct — layout seeds and reads from its own storage
|
|
478
|
+
// app/(dashboard)/layout.tsx
|
|
479
|
+
const LayoutProvider = layoutServerStorage.StateVocabProvider
|
|
480
|
+
export default async function Layout({ children }) {
|
|
481
|
+
return (
|
|
482
|
+
<LayoutProvider value={{ session: { id: 123 } }}>
|
|
483
|
+
<LayoutHeader /> {/* ← can call layoutServerStorage.session.getState() */}
|
|
484
|
+
{children}
|
|
485
|
+
</LayoutProvider>
|
|
486
|
+
)
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// ❌ Wrong — page cannot reach layout's storage
|
|
490
|
+
// app/(dashboard)/page.tsx
|
|
491
|
+
export default async function Page() {
|
|
492
|
+
const session = layoutServerStorage.session.getState() // throws — not in layout's render pass
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
If a page needs data that the layout already fetches (e.g., the current user session), fetch it independently in the page, pass it via URL params, or use a separate mechanism — do not attempt to share it through other state-vocab server storage across route segments.
|
|
497
|
+
|
|
498
|
+
This constraint is **server-only**. On the client, there is no such limitation — client components can freely call `.useState()` from any storage (`layoutClientStorage`, `pageClientStorage`, or any other) regardless of which route segment they live in.
|
|
499
|
+
|
|
495
500
|
#### `serverify(storage)`
|
|
496
501
|
|
|
497
|
-
Converts a storage tree into its server-side counterpart. Each leaf gains
|
|
502
|
+
Converts a storage tree into its server-side counterpart. Each leaf gains a synchronous `.getState()` method that reads the value injected by the nearest `StateVocabProvider`. Each namespace node (including the root) gains a `.seed()` method that returns the input wrapped under its full ancestor path. The result also exposes `StateVocabProvider`.
|
|
498
503
|
|
|
499
504
|
**`.seed()` syntax:**
|
|
500
505
|
|
|
@@ -512,7 +517,7 @@ serverStorage.person.address.seed({ city: 'NY' })
|
|
|
512
517
|
// → { person: { address: { city: 'NY' } } }
|
|
513
518
|
```
|
|
514
519
|
|
|
515
|
-
**`node.getState()`**
|
|
520
|
+
**`node.getState()`** synchronously reads the value for that leaf. Must be called within a React render context (i.e., inside a component that is a descendant of `StateVocabProvider`). Throws if called outside a provider scope or outside a React render context.
|
|
516
521
|
|
|
517
522
|
#### `clientify(storage)`
|
|
518
523
|
|
|
@@ -749,36 +754,31 @@ import { StateVocabClientProvider } from '@yakocloud/state-vocab/client'
|
|
|
749
754
|
</StateVocabClientProvider>
|
|
750
755
|
```
|
|
751
756
|
|
|
752
|
-
### `serverify<T>(storage: T, options)`
|
|
757
|
+
### `serverify<T>(storage: T, options?)`
|
|
753
758
|
|
|
754
759
|
Converts a storage tree to its server-side counterpart. Available from `@yakocloud/state-vocab/server`.
|
|
755
760
|
|
|
756
761
|
| Option | Type | Description |
|
|
757
762
|
|---|---|---|
|
|
758
|
-
| `clientContext` | `Context<object
|
|
759
|
-
| `serverTimeout` | `number \| undefined` | Timeout in ms for each `getState()` call. Defaults to `1000`. If the `StateVocabProvider` has not rendered within this window, `getState()` rejects with a descriptive error. |
|
|
763
|
+
| `clientContext` | `Context<object> \| undefined` | A React context created with `createContext({})`. Pass the same context to `clientify` when multiple independent storage trees coexist on the same page. Omit for single-tree setups. |
|
|
760
764
|
|
|
761
765
|
The result exposes:
|
|
762
766
|
|
|
763
|
-
- **`
|
|
764
|
-
- **`
|
|
765
|
-
- **`node.getState()`** — async; reads the value for that leaf once the nearest `StateVocabProvider` has rendered. Throws if called outside a provider scope or if the timeout expires.
|
|
767
|
+
- **`StateVocabProvider`** — server component that accepts a `value` prop and seeds the per-request store via `React.cache()`.
|
|
768
|
+
- **`node.getState()`** — synchronously reads the value for that leaf. Must be called within a React render context (descendant of `StateVocabProvider`). Throws if called outside a provider scope or outside a render context.
|
|
766
769
|
- **`node.seed(input)`** — wraps `input` under the node's ancestor path, returning a plain object ready to pass as the `value` prop.
|
|
767
770
|
|
|
768
771
|
```ts
|
|
769
772
|
import { serverify } from '@yakocloud/state-vocab/server'
|
|
770
|
-
import { MyClientContext } from '@/storage.context.client'
|
|
771
773
|
|
|
772
|
-
const serverStorage = serverify(storage
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
})
|
|
774
|
+
const serverStorage = serverify(storage)
|
|
775
|
+
// or, for multiple independent trees:
|
|
776
|
+
const serverStorage = serverify(storage, { clientContext: MyClientContext })
|
|
776
777
|
|
|
777
778
|
const { StateVocabProvider } = serverStorage
|
|
778
779
|
|
|
779
780
|
// In a Server Component:
|
|
780
|
-
serverStorage.
|
|
781
|
-
await serverStorage.user.name.getState() // reads "user.name" (async)
|
|
781
|
+
serverStorage.user.name.getState() // reads "user.name" (sync)
|
|
782
782
|
serverStorage.user.seed({ name: 'Alice' }) // → { user: { name: 'Alice' } }
|
|
783
783
|
serverStorage.person.address.seed({ city: 'NY' }) // → { person: { address: { city: 'NY' } } }
|
|
784
784
|
serverStorage.seed({ user: { name: 'Alice' } }) // → { user: { name: 'Alice' } } (identity)
|
|
@@ -790,7 +790,7 @@ Converts a storage tree to its client-side counterpart. Available from `@yakoclo
|
|
|
790
790
|
|
|
791
791
|
| Option | Type | Description |
|
|
792
792
|
|---|---|---|
|
|
793
|
-
| `clientContext` | `Context<object> \| undefined` | The React context
|
|
793
|
+
| `clientContext` | `Context<object> \| undefined` | The React context used to isolate this storage tree. Must match the `clientContext` passed to `serverify` for the same tree. Omit for single-tree setups. |
|
|
794
794
|
|
|
795
795
|
Each leaf gains `.useState()` and `.useInitialState()`. The tree structure mirrors the original.
|
|
796
796
|
|
package/dist/client.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("react"),v=require("./constants-CbsduCZ7.js"),a=require("./utils-
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("react"),v=require("./constants-CbsduCZ7.js"),a=require("./utils-0CTNJ4ZE.js"),V=require("./provider-client-DA53zfcT.js");function D(t,n,s=[]){return f.useMemo(()=>a.debounce(t,n),s)}const y=t=>{const{vocabStore:n,storage:s,statePath:o,value:e,deserialize:l,serialize:c}=t,d=s.getItem(o);d===null?a.isValueDefined(e)&&s.setItem(o,c(e)):n.set(o,l(d))};function I(t){return typeof t=="object"&&t!==null&&"clientSlot"in t}const z=typeof window>"u",m=z?f.useEffect:f.useLayoutEffect,A=new V.VocabStore,P="Make sure your component is wrapped in StateVocabProvider (RSC) or disable ssr option in setupStorage for SPA (RCC only)";function p(t){const n=z?void 0:a.valueOrFactory(t.storage),s=a.valueOrFactory(t.defaultValue),o=t.bidirectional,e=this[v.STATE_PATH],l=this[v.STATE_VERBOSE],c=this[v.STATE_VERBOSE_PATH],d=this[v.STATE_SSR];let i=V.useStateVocabClientContext({clientContext:t.clientContext,verbose:l});if(!(i instanceof V.VocabStore)){if(d)throw new Error(P);i=A}const S=t.serialize??JSON.stringify,u=t.deserialize??JSON.parse,E=D(t.onSet??(()=>{}),t.delayedSet,[]),g=f.useRef(void 0),R=f.useRef(!1);if(!R.current){R.current=!0;let r=i.get(e);a.isValueDefined(r)||(r=s,a.isValueDefined(r)&&i.set(e,r)),!d&&n&&y({vocabStore:i,storage:n,statePath:e,value:r,serialize:S,deserialize:u})}const C=f.useSyncExternalStore(i.subscribe.bind(i),i.getClientSnapshot.bind(i),i.getServerSnapshot.bind(i));if(l)if(c){const r=a.get(C,c);r&&a.logStyled(r)}else a.logStyled(C);const h=a.get(C,e,s);g.current=h,m(()=>{!d||!n||y({vocabStore:i,storage:n,statePath:e,value:h,serialize:S,deserialize:u})},[]);const w=f.useEffectEvent(r=>{if(r.key!==e)return;const b=r.newValue,T=(b===null?null:u(b))??s;a.isValueDefined(T)&&(i.set(e,T),E(T,g.current))});f.useEffect(()=>{if(o)return window.addEventListener("storage",w),()=>window.removeEventListener("storage",w)},[o]);const x=f.useCallback(r=>{const b=a.isTransformer(r)?r(g.current):r;i.set(e,b),E(b,g.current),n&&n.setItem(e,S(b))},[i,e,E,n,S]),_=f.useCallback(()=>{const r=s;if(!a.isValueDefined(r)){n?.removeItem(e);return}i.set(e,r),E(r,g.current),n&&n.setItem(e,S(r))},[s,i,e,E,n,S]);return[h,x,_]}function k(t){const n=z?void 0:a.valueOrFactory(t.storage),s=a.valueOrFactory(t.defaultValue),o=this[v.STATE_PATH],e=this[v.STATE_VERBOSE],l=this[v.STATE_SSR];let c=V.useStateVocabClientContext({clientContext:t.clientContext,verbose:e});if(!(c instanceof V.VocabStore)){if(l)throw new Error(P);c=A}const d=t.serialize??JSON.stringify,i=t.deserialize??JSON.parse,S=f.useRef(!1);let u;S.current||(S.current=!0,u=c.get(o),a.isValueDefined(u)||(u=s,a.isValueDefined(u)&&c.set(o,u)),!l&&n&&y({vocabStore:c,storage:n,statePath:o,value:u,serialize:d,deserialize:i})),m(()=>{!l||!n||y({vocabStore:c,storage:n,statePath:o,value:u,serialize:d,deserialize:i})},[])}function O(t,n={}){const s={};for(const o in t){const e=t[o];I(e)?(s[o]=e.clientSlot({useState(l){return p.apply(this,[{clientContext:n.clientContext,...l}])},useInitialState(l){k.apply(this,[{clientContext:n.clientContext,...l}])}}),delete s[o].serverSlot,delete s[o].clientSlot):e!==null&&typeof e=="object"?s[o]=O(e,n):s[o]=e}return s}exports.StateVocabClientProvider=V.StateVocabClientProvider;exports.clientify=O;
|
package/dist/client.es.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useMemo as j, useRef as
|
|
2
|
+
import { useMemo as j, useRef as C, useSyncExternalStore as B, useEffectEvent as D, useEffect as P, useCallback as p, useLayoutEffect as H } from "react";
|
|
3
3
|
import { S as A, a as I, b as O, c as F } from "./constants-BB1YAX6c.mjs";
|
|
4
|
-
import { a as d, d as G, v as g, g as T, l as x, i as q } from "./utils-
|
|
5
|
-
import { V as
|
|
6
|
-
import { S as ne } from "./provider-client-
|
|
4
|
+
import { a as d, d as G, v as g, g as T, l as x, i as q } from "./utils-xV3x3fTc.mjs";
|
|
5
|
+
import { V as y, u as _ } from "./provider-client-DLa3_Ms9.mjs";
|
|
6
|
+
import { S as ne } from "./provider-client-DLa3_Ms9.mjs";
|
|
7
7
|
function K(t, s, i = []) {
|
|
8
8
|
return j(
|
|
9
9
|
() => G(t, s),
|
|
@@ -21,14 +21,18 @@ const E = (t) => {
|
|
|
21
21
|
serialize: l
|
|
22
22
|
} = t, u = i.getItem(o);
|
|
23
23
|
u === null ? d(e) && i.setItem(o, l(e)) : s.set(o, a(u));
|
|
24
|
-
}
|
|
24
|
+
};
|
|
25
25
|
function Q(t) {
|
|
26
|
+
return typeof t == "object" && t !== null && "clientSlot" in t;
|
|
27
|
+
}
|
|
28
|
+
const z = typeof window > "u", k = z ? P : H, J = new y(), L = "Make sure your component is wrapped in StateVocabProvider (RSC) or disable ssr option in setupStorage for SPA (RCC only)";
|
|
29
|
+
function U(t) {
|
|
26
30
|
const s = z ? void 0 : g(t.storage), i = g(t.defaultValue), o = t.bidirectional, e = this[A], a = this[I], l = this[F], u = this[O];
|
|
27
31
|
let r = _({
|
|
28
32
|
clientContext: t.clientContext,
|
|
29
33
|
verbose: a
|
|
30
34
|
});
|
|
31
|
-
if (!(r instanceof
|
|
35
|
+
if (!(r instanceof y)) {
|
|
32
36
|
if (u)
|
|
33
37
|
throw new Error(L);
|
|
34
38
|
r = J;
|
|
@@ -38,7 +42,7 @@ function Q(t) {
|
|
|
38
42
|
}),
|
|
39
43
|
t.delayedSet,
|
|
40
44
|
[]
|
|
41
|
-
), b =
|
|
45
|
+
), b = C(void 0), w = C(!1);
|
|
42
46
|
if (!w.current) {
|
|
43
47
|
w.current = !0;
|
|
44
48
|
let n = r.get(e);
|
|
@@ -100,18 +104,18 @@ function Q(t) {
|
|
|
100
104
|
M
|
|
101
105
|
];
|
|
102
106
|
}
|
|
103
|
-
function
|
|
107
|
+
function W(t) {
|
|
104
108
|
const s = z ? void 0 : g(t.storage), i = g(t.defaultValue), o = this[A], e = this[I], a = this[O];
|
|
105
109
|
let l = _({
|
|
106
110
|
clientContext: t.clientContext,
|
|
107
111
|
verbose: e
|
|
108
112
|
});
|
|
109
|
-
if (!(l instanceof
|
|
113
|
+
if (!(l instanceof y)) {
|
|
110
114
|
if (a)
|
|
111
115
|
throw new Error(L);
|
|
112
116
|
l = J;
|
|
113
117
|
}
|
|
114
|
-
const u = t.serialize ?? JSON.stringify, r = t.deserialize ?? JSON.parse, f =
|
|
118
|
+
const u = t.serialize ?? JSON.stringify, r = t.deserialize ?? JSON.parse, f = C(!1);
|
|
115
119
|
let c;
|
|
116
120
|
f.current || (f.current = !0, c = l.get(o), d(c) || (c = i, d(c) && l.set(o, c)), !a && s && E({
|
|
117
121
|
vocabStore: l,
|
|
@@ -131,22 +135,19 @@ function U(t) {
|
|
|
131
135
|
});
|
|
132
136
|
}, []);
|
|
133
137
|
}
|
|
134
|
-
function W(t) {
|
|
135
|
-
return typeof t == "object" && t !== null && "clientSlot" in t;
|
|
136
|
-
}
|
|
137
138
|
function X(t, s = {}) {
|
|
138
139
|
const i = {};
|
|
139
140
|
for (const o in t) {
|
|
140
141
|
const e = t[o];
|
|
141
|
-
|
|
142
|
+
Q(e) ? (i[o] = e.clientSlot({
|
|
142
143
|
useState(a) {
|
|
143
|
-
return
|
|
144
|
+
return U.apply(this, [{
|
|
144
145
|
clientContext: s.clientContext,
|
|
145
146
|
...a
|
|
146
147
|
}]);
|
|
147
148
|
},
|
|
148
149
|
useInitialState(a) {
|
|
149
|
-
|
|
150
|
+
W.apply(this, [{
|
|
150
151
|
clientContext: s.clientContext,
|
|
151
152
|
...a
|
|
152
153
|
}]);
|
package/dist/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./constants-CbsduCZ7.js"),h=require("./utils-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./constants-CbsduCZ7.js"),h=require("./utils-0CTNJ4ZE.js");function z(t={}){return{[r.STATE_DEFINITION]:!0,[r.STATE_PATH]:"",[r.STATE_VERBOSE]:!1,[r.STATE_VERBOSE_PATH]:"",[r.STATE_SSR]:!1,serverSlot(a){return Object.assign(this,{getState(...e){return a.getState.apply(this,e)}})},clientSlot(a){return Object.assign(this,{useState(e){return e??={},a.useState.apply(this,[{defaultValue:h.valueOrFactory(e.defaultValue)??h.valueOrFactory(t.defaultValue),bidirectional:e.bidirectional??t.bidirectional,storage:e.storage??t.storage,serialize:t.serialize??JSON.stringify,deserialize:t.deserialize??JSON.parse,delayedSet:e.delayedSet,onSet(...f){e.onSet&&e.onSet(...f)}}])},useInitialState(e){a.useInitialState.apply(this,[{defaultValue:e.defaultValue,storage:t.storage,serialize:t.serialize,deserialize:t.deserialize}])}})},toString(){return this[r.STATE_PATH]}}}function y(t,a){const{path:e="",verbose:f,verbosePath:A,ssr:b,cache:c}=a;let s=c.proxy.get(t);s||(s=new Map,c.proxy.set(t,s));const o=s.get(e);if(o)return o;const d=new Proxy(t,{get(P,T){const l=P[T],S=e?`${e}.${String(T)}`:String(T);if(l&&typeof l=="object"&&r.STATE_DEFINITION in l){const i=l;let n=c.leaf.get(i);n||(n=new Map,c.leaf.set(i,n));const g=n.get(S);if(g)return g;const _=Reflect.ownKeys(i).filter(u=>typeof i[u]=="function"),v=Object.fromEntries(_.map(u=>[u,(...V)=>i[u].call({...i,[r.STATE_PATH]:S,[r.STATE_VERBOSE]:f,[r.STATE_VERBOSE_PATH]:A,[r.STATE_SSR]:b},...V)])),E={...i,...v};return n.set(S,E),E}return l&&typeof l=="object"?y(l,{...a,path:S}):l}});return s.set(e,d),d}function I(t,a){return y(t,{...a,ssr:a?.ssr??!0,verbosePath:a?.verbosePath??"",cache:{proxy:new WeakMap,leaf:new WeakMap}})}exports.defineState=z;exports.setupStorage=I;
|
package/dist/index.es.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";"use strict";const h=require("react/jsx-runtime"),c=require("react"),r=require("./utils-
|
|
1
|
+
"use client";"use strict";const h=require("react/jsx-runtime"),c=require("react"),r=require("./utils-0CTNJ4ZE.js"),a=c.createContext({});function S(e){const t=c.useContext(e.clientContext??a);return e.verbose&&console.log(`[Store uid]: ${t.uid}`),t}class u{uid;#t;#e;constructor(t){this.uid=Math.random().toString(36).slice(2),this.#t=t??{},this.#e=new Set}subscribe(t){return this.#e.add(t),()=>this.#e.delete(t)}getClientSnapshot(){return this.#t}getServerSnapshot(){return this.#t}get(t){return r.get(this.#t,t)}set(t,n){const s=r.get(this.#t,t),i=r.isTransformer(n)?n(s):n,o={...this.#t};r.set(o,t,i),this.#t=o,this.#e.forEach(l=>l())}}function b(e){const{clientContext:t,value:n,children:s}=e,[i]=c.useState(()=>new u(n)),o=t??a;return h.jsx(o.Provider,{value:i,children:s})}exports.StateVocabClientProvider=b;exports.VocabStore=u;exports.useStateVocabClientContext=S;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as u } from "react/jsx-runtime";
|
|
3
3
|
import { createContext as l, useContext as h, useState as S } from "react";
|
|
4
|
-
import { g as i, i as C, s as b } from "./utils-
|
|
4
|
+
import { g as i, i as C, s as b } from "./utils-xV3x3fTc.mjs";
|
|
5
5
|
const c = l({});
|
|
6
6
|
function m(e) {
|
|
7
7
|
const t = h(e.clientContext ?? c);
|
package/dist/server.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),u=require("./constants-CbsduCZ7.js"),y=require("react"),S=require("./provider-client-DA53zfcT.js"),d=require("./utils-0CTNJ4ZE.js"),s=y.cache(()=>new Map),f=e=>s().get(e),v=(e,t)=>s().set(e,t);function b(e=""){const t=Symbol("test"),{size:n}=s();if(s().set(t,{}),s().size===n)throw new Error([e,"Start execution only within a React render context (per-request)."].join(" "));s().delete(t)}function x(e){return typeof e=="object"&&e!==null&&"serverSlot"in e}function p(e){const t=this[u.STATE_PATH],n=`Failed access to "${t}".`;b(n);const r=f(e.serverContextKey);if(!r)throw new Error(`${n} Reason: no data. Make sure your component is wrapped in StateVocabProvider.`);return d.get(r,t)}function i(e,t){const n={};for(const r in e){const o=e[r];if(x(o))n[r]=o.serverSlot({getState(){return p.apply(this,[{serverContextKey:t.serverContextKey}])}}),delete n[r].serverSlot,delete n[r].clientSlot;else if(o!==null&&typeof o=="object"){const c=a=>t.wrap({[r]:a});n[r]=i(o,{serverContextKey:t.serverContextKey,wrap:c})}else n[r]=o}return n.seed=r=>t.wrap(r),n}function w(e,t){t??={};const n=Object.keys(e).slice(0,3).join("-"),r=Symbol(n);return{...i(e,{serverContextKey:r,wrap:o=>o}),StateVocabProvider({children:o,value:c}){return c??={},v(r,c),l.jsx(S.StateVocabClientProvider,{clientContext:t.clientContext,value:c,children:o})}}}exports.serverify=w;
|
package/dist/server.es.js
CHANGED
|
@@ -1,76 +1,74 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { S
|
|
3
|
-
import
|
|
4
|
-
import { S as
|
|
5
|
-
import {
|
|
6
|
-
const p = (e) =>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
);
|
|
16
|
-
if (!r)
|
|
17
|
-
throw new Error(a);
|
|
18
|
-
return w(r, t);
|
|
1
|
+
import { jsx as l } from "react/jsx-runtime";
|
|
2
|
+
import { S } from "./constants-BB1YAX6c.mjs";
|
|
3
|
+
import { cache as f } from "react";
|
|
4
|
+
import { S as u } from "./provider-client-DLa3_Ms9.mjs";
|
|
5
|
+
import { g as y } from "./utils-xV3x3fTc.mjs";
|
|
6
|
+
const s = f(() => /* @__PURE__ */ new Map()), p = (e) => s().get(e), x = (e, t) => s().set(e, t);
|
|
7
|
+
function d(e = "") {
|
|
8
|
+
const t = /* @__PURE__ */ Symbol("test"), { size: o } = s();
|
|
9
|
+
if (s().set(t, {}), s().size === o)
|
|
10
|
+
throw new Error([
|
|
11
|
+
e,
|
|
12
|
+
"Start execution only within a React render context (per-request)."
|
|
13
|
+
].join(" "));
|
|
14
|
+
s().delete(t);
|
|
19
15
|
}
|
|
20
|
-
function
|
|
16
|
+
function m(e) {
|
|
21
17
|
return typeof e == "object" && e !== null && "serverSlot" in e;
|
|
22
18
|
}
|
|
23
|
-
function
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
function b(e) {
|
|
20
|
+
const t = this[S], o = `Failed access to "${t}".`;
|
|
21
|
+
d(o);
|
|
22
|
+
const r = p(e.serverContextKey);
|
|
23
|
+
if (!r)
|
|
24
|
+
throw new Error(
|
|
25
|
+
`${o} Reason: no data. Make sure your component is wrapped in StateVocabProvider.`
|
|
26
|
+
);
|
|
27
|
+
return y(r, t);
|
|
28
|
+
}
|
|
29
|
+
function i(e, t) {
|
|
30
|
+
const o = {};
|
|
31
|
+
for (const r in e) {
|
|
32
|
+
const n = e[r];
|
|
33
|
+
if (m(n))
|
|
34
|
+
o[r] = n.serverSlot({
|
|
29
35
|
getState() {
|
|
30
|
-
return
|
|
31
|
-
serverContextKey: t.serverContextKey
|
|
32
|
-
timeout: t.serverTimeout
|
|
36
|
+
return b.apply(this, [{
|
|
37
|
+
serverContextKey: t.serverContextKey
|
|
33
38
|
}]);
|
|
34
39
|
}
|
|
35
|
-
}), delete r
|
|
40
|
+
}), delete o[r].serverSlot, delete o[r].clientSlot;
|
|
36
41
|
else if (n !== null && typeof n == "object") {
|
|
37
|
-
const
|
|
38
|
-
r
|
|
42
|
+
const c = (a) => t.wrap({ [r]: a });
|
|
43
|
+
o[r] = i(n, {
|
|
39
44
|
serverContextKey: t.serverContextKey,
|
|
40
|
-
|
|
41
|
-
wrap: i
|
|
45
|
+
wrap: c
|
|
42
46
|
});
|
|
43
47
|
} else
|
|
44
|
-
r
|
|
48
|
+
o[r] = n;
|
|
45
49
|
}
|
|
46
|
-
return
|
|
50
|
+
return o.seed = (r) => t.wrap(r), o;
|
|
47
51
|
}
|
|
48
|
-
function
|
|
49
|
-
|
|
52
|
+
function K(e, t) {
|
|
53
|
+
t ??= {};
|
|
54
|
+
const o = Object.keys(e).slice(0, 3).join("-"), r = Symbol(o);
|
|
50
55
|
return {
|
|
51
|
-
...
|
|
52
|
-
serverContextKey:
|
|
53
|
-
|
|
54
|
-
wrap: (i) => i
|
|
56
|
+
...i(e, {
|
|
57
|
+
serverContextKey: r,
|
|
58
|
+
wrap: (n) => n
|
|
55
59
|
}),
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
throw new Error("Start execution only within a React render context (per-request)");
|
|
60
|
-
c().delete(s), c().set(o, n.promise);
|
|
61
|
-
},
|
|
62
|
-
StateVocabProvider({ children: i, value: s }) {
|
|
63
|
-
return s ??= {}, n.resolve(s), /* @__PURE__ */ u(
|
|
64
|
-
y,
|
|
60
|
+
StateVocabProvider({ children: n, value: c }) {
|
|
61
|
+
return c ??= {}, x(r, c), /* @__PURE__ */ l(
|
|
62
|
+
u,
|
|
65
63
|
{
|
|
66
64
|
clientContext: t.clientContext,
|
|
67
|
-
value:
|
|
68
|
-
children:
|
|
65
|
+
value: c,
|
|
66
|
+
children: n
|
|
69
67
|
}
|
|
70
68
|
);
|
|
71
69
|
}
|
|
72
70
|
};
|
|
73
71
|
}
|
|
74
72
|
export {
|
|
75
|
-
|
|
73
|
+
K as serverify
|
|
76
74
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { Vocab } from "./state.types";
|
|
2
|
-
export declare const getRequestStore: () => Map<symbol,
|
|
3
|
-
export declare const getStateVocab: (serverContextKey: symbol) =>
|
|
2
|
+
export declare const getRequestStore: () => Map<symbol, Vocab>;
|
|
3
|
+
export declare const getStateVocab: (serverContextKey: symbol) => Vocab | undefined;
|
|
4
|
+
export declare const setStateVocab: (serverContextKey: symbol, value: Vocab) => Map<symbol, Vocab>;
|
|
@@ -1,21 +1,5 @@
|
|
|
1
1
|
import { type Context } from "react";
|
|
2
|
-
import type {
|
|
3
|
-
import VocabStore from "./store";
|
|
4
|
-
import type { UseInitialStateOptions, UseStateOptions } from "./setup.types";
|
|
5
|
-
declare function useState<V>(this: VocabThis, options: UseStateOptions<V> & {
|
|
6
|
-
clientContext: Context<VocabStore> | undefined;
|
|
7
|
-
}): readonly [V, (nextValue: ValueOrTransformer<V>) => void, () => void];
|
|
8
|
-
type Placeholder<V> = {
|
|
9
|
-
useState(options?: UseStateOptions<V>): ReturnType<typeof useState<V>>;
|
|
10
|
-
useInitialState(options?: UseInitialStateOptions<V>): void;
|
|
11
|
-
};
|
|
12
|
-
type Slot<V> = {
|
|
13
|
-
clientSlot(input: Placeholder<V>): Placeholder<V>;
|
|
14
|
-
};
|
|
15
|
-
type Clientified<R> = R extends Slot<infer TValue> ? Placeholder<TValue> : R extends object ? {
|
|
16
|
-
[K in keyof R]: Clientified<R[K]>;
|
|
17
|
-
} : R;
|
|
2
|
+
import type { ClientifyResult } from "./setup.client.types";
|
|
18
3
|
export declare function clientify<R extends object>(tree: R, clientifyOptions?: {
|
|
19
4
|
clientContext?: Context<object>;
|
|
20
|
-
}):
|
|
21
|
-
export {};
|
|
5
|
+
}): ClientifyResult<R>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Deserialize, Serialize, ValueOrFactory, ValueOrTransformer } from "./state.types";
|
|
2
|
+
export type UseStateOptions<V> = {
|
|
3
|
+
defaultValue?: ValueOrFactory<V>;
|
|
4
|
+
delayedSet?: number;
|
|
5
|
+
bidirectional?: true;
|
|
6
|
+
onSet?(nextValue: NoInfer<V>, prevValue: NoInfer<V>): void;
|
|
7
|
+
storage?: unknown;
|
|
8
|
+
serialize?: Serialize<V>;
|
|
9
|
+
deserialize?: Deserialize<V>;
|
|
10
|
+
};
|
|
11
|
+
type UseStateResult<V> = readonly [V, (nextValue: ValueOrTransformer<V>) => void, () => void];
|
|
12
|
+
export type UseInitialStateOptions<V> = {
|
|
13
|
+
defaultValue?: ValueOrFactory<V>;
|
|
14
|
+
storage?: unknown;
|
|
15
|
+
serialize?: Serialize<V>;
|
|
16
|
+
deserialize?: Deserialize<V>;
|
|
17
|
+
};
|
|
18
|
+
type Placeholder<V> = {
|
|
19
|
+
useState(options?: UseStateOptions<V>): UseStateResult<V>;
|
|
20
|
+
useInitialState(options?: UseInitialStateOptions<V>): void;
|
|
21
|
+
};
|
|
22
|
+
export type ClientSlot<V> = {
|
|
23
|
+
clientSlot(input: Placeholder<V>): Placeholder<V>;
|
|
24
|
+
};
|
|
25
|
+
type Clientified<R> = R extends ClientSlot<infer V> ? Placeholder<V> : R extends object ? {
|
|
26
|
+
[K in keyof R]: Clientified<R[K]>;
|
|
27
|
+
} : R;
|
|
28
|
+
export type ClientifyResult<R> = Clientified<R>;
|
|
29
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { ClientSlot } from "./setup.client.types";
|
|
2
|
+
import type { Deserialize, Serialize } from "./state.types";
|
|
1
3
|
import { type DependencyList } from "react";
|
|
2
4
|
import VocabStore from "./store";
|
|
3
|
-
import type { Deserialize, Serialize } from "./state.types";
|
|
4
5
|
export declare function useDebounce<T extends (...args: never[]) => unknown>(effect: T, wait: number | undefined, deps?: DependencyList): (...args: Parameters<T>) => void;
|
|
5
6
|
export declare const sync: <V>(options: {
|
|
6
7
|
vocabStore: VocabStore;
|
|
@@ -10,3 +11,4 @@ export declare const sync: <V>(options: {
|
|
|
10
11
|
deserialize: Deserialize<V>;
|
|
11
12
|
value: V | undefined;
|
|
12
13
|
}) => void;
|
|
14
|
+
export declare function isClientSlot(value: unknown): value is ClientSlot<unknown>;
|
package/dist/types/setup.d.ts
CHANGED
|
@@ -1,14 +1,2 @@
|
|
|
1
|
-
import {
|
|
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> = {
|
|
8
|
-
path: string;
|
|
9
|
-
verbose: boolean;
|
|
10
|
-
verbosePath: Path<T>;
|
|
11
|
-
ssr: boolean;
|
|
12
|
-
};
|
|
1
|
+
import type { InjectPathsOptions } from "./setup.types";
|
|
13
2
|
export declare function setupStorage<T extends object>(tree: T, options?: Partial<Omit<InjectPathsOptions<T>, "path">>): T;
|
|
14
|
-
export {};
|
|
@@ -1,36 +1,5 @@
|
|
|
1
|
-
import type { Context
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
};
|
|
6
|
-
type SlotValue<T> = T extends {
|
|
7
|
-
serverSlot(input: {
|
|
8
|
-
getState(this: VocabThis): infer V;
|
|
9
|
-
}): unknown;
|
|
10
|
-
} ? V : never;
|
|
11
|
-
type ServerifiedValue<R> = {
|
|
12
|
-
[K in keyof R]?: [
|
|
13
|
-
SlotValue<R[K]>
|
|
14
|
-
] extends [never] ? R[K] extends object ? ServerifiedValue<R[K]> : R[K] : SlotValue<R[K]>;
|
|
15
|
-
};
|
|
16
|
-
type Serverified<R> = [
|
|
17
|
-
SlotValue<R>
|
|
18
|
-
] extends [never] ? R extends object ? {
|
|
19
|
-
seed(input: ServerifiedValue<R>): Vocab;
|
|
20
|
-
} & {
|
|
21
|
-
[K in keyof R]: Serverified<R[K]>;
|
|
22
|
-
} : R : Placeholder<SlotValue<R>>;
|
|
23
|
-
type ServerifyResult<R extends object> = {
|
|
24
|
-
start(): void;
|
|
25
|
-
seed(input: ServerifiedValue<R>): Vocab;
|
|
26
|
-
StateVocabProvider(props: PropsWithChildren<{
|
|
27
|
-
value?: ServerifiedValue<R>;
|
|
28
|
-
}>): ReactNode;
|
|
29
|
-
} & {
|
|
30
|
-
[K in keyof R]: Serverified<R[K]>;
|
|
31
|
-
};
|
|
32
|
-
export declare function serverify<R extends object>(tree: R, serverifyOptions: {
|
|
33
|
-
clientContext: Context<object>;
|
|
34
|
-
serverTimeout?: number;
|
|
1
|
+
import type { Context } from "react";
|
|
2
|
+
import type { ServerifyResult } from "./setup.server.types";
|
|
3
|
+
export declare function serverify<R extends object>(tree: R, serverifyOptions?: {
|
|
4
|
+
clientContext?: Context<object>;
|
|
35
5
|
}): ServerifyResult<R>;
|
|
36
|
-
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { PropsWithChildren, ReactNode } from "react";
|
|
2
|
+
import type { Vocab } from "./state.types";
|
|
3
|
+
type Placeholder<V> = {
|
|
4
|
+
getState(): V;
|
|
5
|
+
};
|
|
6
|
+
export type ServerSlot<V> = {
|
|
7
|
+
serverSlot(input: Placeholder<V>): Placeholder<V>;
|
|
8
|
+
};
|
|
9
|
+
type ServerifiedValue<R> = {
|
|
10
|
+
[K in keyof R]?: R[K] extends ServerSlot<infer V> ? V : R[K] extends object ? ServerifiedValue<R[K]> : R[K];
|
|
11
|
+
};
|
|
12
|
+
type Serverified<R> = R extends ServerSlot<infer V> ? Placeholder<V> : R extends object ? {
|
|
13
|
+
seed(input: ServerifiedValue<R>): Vocab;
|
|
14
|
+
} & {
|
|
15
|
+
[K in keyof R]: Serverified<R[K]>;
|
|
16
|
+
} : R;
|
|
17
|
+
export type ServerifyResult<R extends object> = {
|
|
18
|
+
seed(input: ServerifiedValue<R>): Vocab;
|
|
19
|
+
StateVocabProvider(props: PropsWithChildren<{
|
|
20
|
+
value?: ServerifiedValue<R>;
|
|
21
|
+
}>): ReactNode;
|
|
22
|
+
} & {
|
|
23
|
+
[K in keyof R]: Serverified<R[K]>;
|
|
24
|
+
};
|
|
25
|
+
export {};
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
defaultValue?: ValueOrFactory<V>;
|
|
13
|
-
storage?: unknown;
|
|
14
|
-
serialize?: Serialize<V>;
|
|
15
|
-
deserialize?: Deserialize<V>;
|
|
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
|
+
export type InjectPathsOptions<T extends object> = {
|
|
8
|
+
path: string;
|
|
9
|
+
verbose: boolean;
|
|
10
|
+
verbosePath: Path<T>;
|
|
11
|
+
ssr: boolean;
|
|
16
12
|
};
|
|
13
|
+
export {};
|
package/dist/types/state.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { STATE_DEFINITION, STATE_PATH, STATE_SSR, STATE_VERBOSE, STATE_VERBOSE_PATH } from "./constants";
|
|
2
1
|
import type { Deserialize, Serialize, ValueOrFactory, ValueOrTransformer, VocabThis } from "./state.types";
|
|
2
|
+
import { STATE_DEFINITION, STATE_PATH, STATE_SSR, STATE_VERBOSE, STATE_VERBOSE_PATH } from "./constants";
|
|
3
3
|
export declare function defineState<V>(superOptions?: {
|
|
4
4
|
defaultValue?: ValueOrFactory<V>;
|
|
5
5
|
bidirectional?: true;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";function f(e,s,n){if(!s)return e;const o=s.split(".");let t=e;for(const c of o)if(t!==null&&typeof t=="object"&&c in t)t=t[c];else return n;return t===void 0?n:t}function y(e,s,n){const o=s.replace(/\[(\d+)\]/g,".$1").split(".");let t=e;for(let c=0;c<o.length-1;c++){const r=o[c],i=o[c+1];(t[r]===void 0||t[r]===null)&&(t[r]=/^\d+$/.test(i)?[]:{}),t=t[r]}return t[o[o.length-1]]=n,e}function d(e,s=0){let n;return function(...o){n!==void 0&&clearTimeout(n),n=setTimeout(()=>{n=void 0,e.apply(this,o)},s)}}function a(e){const s=JSON.stringify(e,null,2).split(`
|
|
2
|
+
`),n=[],o=[];for(const t of s){const c=t.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);if(c){const[,r,i,l,u]=c;n.push(`${r}%c"${i}"%c${l}%c${u}`),o.push("color: #9cdcfe; font-weight: bold","color: #cccccc","color: #ce9178")}else n.push(`%c${t}`),o.push("color: #cccccc")}console.log(n.join(`
|
|
3
|
+
`),...o,e)}const p=e=>typeof e=="function",g=e=>typeof e=="function",h=e=>typeof e<"u",$=e=>g(e)?e():e;exports.debounce=d;exports.get=f;exports.isTransformer=p;exports.isValueDefined=h;exports.logStyled=a;exports.set=y;exports.valueOrFactory=$;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
function a(t, s, n) {
|
|
2
|
+
if (!s)
|
|
3
|
+
return t;
|
|
4
|
+
const o = s.split(".");
|
|
5
|
+
let e = t;
|
|
6
|
+
for (const c of o)
|
|
7
|
+
if (e !== null && typeof e == "object" && c in e)
|
|
8
|
+
e = e[c];
|
|
9
|
+
else
|
|
10
|
+
return n;
|
|
11
|
+
return e === void 0 ? n : e;
|
|
12
|
+
}
|
|
13
|
+
function y(t, s, n) {
|
|
14
|
+
const o = s.replace(/\[(\d+)\]/g, ".$1").split(".");
|
|
15
|
+
let e = t;
|
|
16
|
+
for (let c = 0; c < o.length - 1; c++) {
|
|
17
|
+
const r = o[c], i = o[c + 1];
|
|
18
|
+
(e[r] === void 0 || e[r] === null) && (e[r] = /^\d+$/.test(i) ? [] : {}), e = e[r];
|
|
19
|
+
}
|
|
20
|
+
return e[o[o.length - 1]] = n, t;
|
|
21
|
+
}
|
|
22
|
+
function d(t, s = 0) {
|
|
23
|
+
let n;
|
|
24
|
+
return function(...o) {
|
|
25
|
+
n !== void 0 && clearTimeout(n), n = setTimeout(() => {
|
|
26
|
+
n = void 0, t.apply(this, o);
|
|
27
|
+
}, s);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function p(t) {
|
|
31
|
+
const s = JSON.stringify(t, null, 2).split(`
|
|
32
|
+
`), n = [], o = [];
|
|
33
|
+
for (const e of s) {
|
|
34
|
+
const c = e.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);
|
|
35
|
+
if (c) {
|
|
36
|
+
const [, r, i, l, u] = c;
|
|
37
|
+
n.push(`${r}%c"${i}"%c${l}%c${u}`), o.push(
|
|
38
|
+
"color: #9cdcfe; font-weight: bold",
|
|
39
|
+
"color: #cccccc",
|
|
40
|
+
"color: #ce9178"
|
|
41
|
+
);
|
|
42
|
+
} else
|
|
43
|
+
n.push(`%c${e}`), o.push("color: #cccccc");
|
|
44
|
+
}
|
|
45
|
+
console.log(n.join(`
|
|
46
|
+
`), ...o, t);
|
|
47
|
+
}
|
|
48
|
+
const g = (t) => typeof t == "function", f = (t) => typeof t == "function", h = (t) => typeof t < "u", $ = (t) => f(t) ? t() : t;
|
|
49
|
+
export {
|
|
50
|
+
h as a,
|
|
51
|
+
d,
|
|
52
|
+
a as g,
|
|
53
|
+
g as i,
|
|
54
|
+
p as l,
|
|
55
|
+
y as s,
|
|
56
|
+
$ as v
|
|
57
|
+
};
|
package/package.json
CHANGED
package/dist/utils-CuApuc3e.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use strict";function f(e,r,o){if(!r)return e;const n=r.split(".");let t=e;for(const c of n)if(t!==null&&typeof t=="object"&&c in t)t=t[c];else return o;return t===void 0?o:t}function y(e,r,o){const n=r.replace(/\[(\d+)\]/g,".$1").split(".");let t=e;for(let c=0;c<n.length-1;c++){const s=n[c],i=n[c+1];(t[s]===void 0||t[s]===null)&&(t[s]=/^\d+$/.test(i)?[]:{}),t=t[s]}return t[n[n.length-1]]=o,e}function a(e,r=0){let o;return function(...n){o!==void 0&&clearTimeout(o),o=setTimeout(()=>{o=void 0,e.apply(this,n)},r)}}function d(e){const r=JSON.stringify(e,null,2).split(`
|
|
2
|
-
`),o=[],n=[];for(const t of r){const c=t.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);if(c){const[,s,i,l,u]=c;o.push(`${s}%c"${i}"%c${l}%c${u}`),n.push("color: #9cdcfe; font-weight: bold","color: #cccccc","color: #ce9178")}else o.push(`%c${t}`),n.push("color: #cccccc")}console.log(o.join(`
|
|
3
|
-
`),...n,e)}const m=e=>typeof e=="function",p=e=>typeof e=="function",h=e=>typeof e<"u",g=e=>p(e)?e():e;async function T(e,r,o){let n;try{return await Promise.race([e,new Promise((t,c)=>{n=setTimeout(()=>{c(new Error(o))},r)})])}finally{clearTimeout(n)}}exports.debounce=a;exports.get=f;exports.isTransformer=m;exports.isValueDefined=h;exports.logStyled=d;exports.set=y;exports.valueOrFactory=g;exports.withTimeout=T;
|
package/dist/utils-xNWifFE9.mjs
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
function a(t, s, o) {
|
|
2
|
-
if (!s)
|
|
3
|
-
return t;
|
|
4
|
-
const n = s.split(".");
|
|
5
|
-
let e = t;
|
|
6
|
-
for (const c of n)
|
|
7
|
-
if (e !== null && typeof e == "object" && c in e)
|
|
8
|
-
e = e[c];
|
|
9
|
-
else
|
|
10
|
-
return o;
|
|
11
|
-
return e === void 0 ? o : e;
|
|
12
|
-
}
|
|
13
|
-
function y(t, s, o) {
|
|
14
|
-
const n = s.replace(/\[(\d+)\]/g, ".$1").split(".");
|
|
15
|
-
let e = t;
|
|
16
|
-
for (let c = 0; c < n.length - 1; c++) {
|
|
17
|
-
const r = n[c], i = n[c + 1];
|
|
18
|
-
(e[r] === void 0 || e[r] === null) && (e[r] = /^\d+$/.test(i) ? [] : {}), e = e[r];
|
|
19
|
-
}
|
|
20
|
-
return e[n[n.length - 1]] = o, t;
|
|
21
|
-
}
|
|
22
|
-
function d(t, s = 0) {
|
|
23
|
-
let o;
|
|
24
|
-
return function(...n) {
|
|
25
|
-
o !== void 0 && clearTimeout(o), o = setTimeout(() => {
|
|
26
|
-
o = void 0, t.apply(this, n);
|
|
27
|
-
}, s);
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
function p(t) {
|
|
31
|
-
const s = JSON.stringify(t, null, 2).split(`
|
|
32
|
-
`), o = [], n = [];
|
|
33
|
-
for (const e of s) {
|
|
34
|
-
const c = e.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);
|
|
35
|
-
if (c) {
|
|
36
|
-
const [, r, i, l, u] = c;
|
|
37
|
-
o.push(`${r}%c"${i}"%c${l}%c${u}`), n.push(
|
|
38
|
-
"color: #9cdcfe; font-weight: bold",
|
|
39
|
-
"color: #cccccc",
|
|
40
|
-
"color: #ce9178"
|
|
41
|
-
);
|
|
42
|
-
} else
|
|
43
|
-
o.push(`%c${e}`), n.push("color: #cccccc");
|
|
44
|
-
}
|
|
45
|
-
console.log(o.join(`
|
|
46
|
-
`), ...n, t);
|
|
47
|
-
}
|
|
48
|
-
const m = (t) => typeof t == "function", f = (t) => typeof t == "function", h = (t) => typeof t < "u", g = (t) => f(t) ? t() : t;
|
|
49
|
-
async function $(t, s, o) {
|
|
50
|
-
let n;
|
|
51
|
-
try {
|
|
52
|
-
return await Promise.race([
|
|
53
|
-
t,
|
|
54
|
-
new Promise((e, c) => {
|
|
55
|
-
n = setTimeout(() => {
|
|
56
|
-
c(new Error(o));
|
|
57
|
-
}, s);
|
|
58
|
-
})
|
|
59
|
-
]);
|
|
60
|
-
} finally {
|
|
61
|
-
clearTimeout(n);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
export {
|
|
65
|
-
h as a,
|
|
66
|
-
d,
|
|
67
|
-
a as g,
|
|
68
|
-
m as i,
|
|
69
|
-
p as l,
|
|
70
|
-
y as s,
|
|
71
|
-
g as v,
|
|
72
|
-
$ as w
|
|
73
|
-
};
|