@yakocloud/state-vocab 4.1.0 → 4.2.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 +26 -11
- package/dist/client.cjs.js +1 -1
- package/dist/client.es.js +3 -3
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -1
- package/dist/{provider-client-D0BmMWcY.mjs → provider-client-BhPeK8Kz.mjs} +2 -1
- package/dist/provider-client-DRdFy5dG.js +1 -0
- package/dist/server.cjs.js +1 -1
- package/dist/server.es.js +53 -81
- package/dist/types/context.server.d.ts +2 -11
- package/dist/types/setup.server.d.ts +17 -9
- package/dist/types/utils.d.ts +1 -0
- package/dist/utils-CuApuc3e.js +3 -0
- package/dist/utils-xNWifFE9.mjs +73 -0
- package/package.json +1 -1
- package/dist/provider-client-CAHe8VnM.js +0 -1
- package/dist/types/provider.d.ts +0 -8
- package/dist/types/provider.server.d.ts +0 -6
- package/dist/utils-0CTNJ4ZE.js +0 -3
- package/dist/utils-xV3x3fTc.mjs +0 -57
package/README.md
CHANGED
|
@@ -412,6 +412,10 @@ import { serverStorage } from '@/storage.server'
|
|
|
412
412
|
const { StateVocabProvider } = serverStorage
|
|
413
413
|
|
|
414
414
|
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
|
+
|
|
415
419
|
// Fetch data from DB / API
|
|
416
420
|
const user = await db.getUser()
|
|
417
421
|
|
|
@@ -433,8 +437,8 @@ export default async function Page() {
|
|
|
433
437
|
import { serverStorage } from '@/storage.server'
|
|
434
438
|
|
|
435
439
|
export default async function UserInfo() {
|
|
436
|
-
const name = serverStorage.user.name.getState()
|
|
437
|
-
const role = serverStorage.user.role.getState()
|
|
440
|
+
const name = await serverStorage.user.name.getState()
|
|
441
|
+
const role = await serverStorage.user.role.getState()
|
|
438
442
|
|
|
439
443
|
return <p>{name} — {role}</p>
|
|
440
444
|
}
|
|
@@ -490,7 +494,7 @@ Each `StateVocabProvider` wraps its own subtree; a component that calls `pageCli
|
|
|
490
494
|
|
|
491
495
|
#### `serverify(storage)`
|
|
492
496
|
|
|
493
|
-
Converts a storage tree into its server-side counterpart. Each leaf gains
|
|
497
|
+
Converts a storage tree into its server-side counterpart. Each leaf gains an async `.getState()` method that resolves once the nearest `StateVocabProvider` renders and provides its value. 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` and `start()` — call `start()` at the top of the component that renders `StateVocabProvider` so concurrent server children can await the value without timing out.
|
|
494
498
|
|
|
495
499
|
**`.seed()` syntax:**
|
|
496
500
|
|
|
@@ -508,7 +512,7 @@ serverStorage.person.address.seed({ city: 'NY' })
|
|
|
508
512
|
// → { person: { address: { city: 'NY' } } }
|
|
509
513
|
```
|
|
510
514
|
|
|
511
|
-
**`node.getState()`** reads the value for that leaf
|
|
515
|
+
**`node.getState()`** asynchronously reads the value for that leaf once the surrounding `StateVocabProvider` has rendered. Returns `Promise<V>` — always `await` it. Throws (rejects) if called outside a provider scope or if `serverTimeout` expires.
|
|
512
516
|
|
|
513
517
|
#### `clientify(storage)`
|
|
514
518
|
|
|
@@ -752,21 +756,32 @@ Converts a storage tree to its server-side counterpart. Available from `@yakoclo
|
|
|
752
756
|
| Option | Type | Description |
|
|
753
757
|
|---|---|---|
|
|
754
758
|
| `clientContext` | `Context<object>` | **Required.** A React context created with `createContext({})` in a `"use client"` file. Must match the `clientContext` passed to `clientify` for the same storage tree. |
|
|
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. |
|
|
760
|
+
|
|
761
|
+
The result exposes:
|
|
755
762
|
|
|
756
|
-
|
|
763
|
+
- **`start()`** — call once at the top of the component that renders `StateVocabProvider`, before any `await` expressions. It registers a pending promise in the per-request store (`React.cache()` scope), which lets concurrent server components `await getState()` without hanging. Must be called within a React render context.
|
|
764
|
+
- **`StateVocabProvider`** — synchronous server component that accepts a `value` prop and resolves the pending promise registered by `start()`.
|
|
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.
|
|
766
|
+
- **`node.seed(input)`** — wraps `input` under the node's ancestor path, returning a plain object ready to pass as the `value` prop.
|
|
757
767
|
|
|
758
768
|
```ts
|
|
759
769
|
import { serverify } from '@yakocloud/state-vocab/server'
|
|
760
770
|
import { MyClientContext } from '@/storage.context.client'
|
|
761
771
|
|
|
762
|
-
const serverStorage = serverify(storage, {
|
|
772
|
+
const serverStorage = serverify(storage, {
|
|
773
|
+
clientContext: MyClientContext,
|
|
774
|
+
serverTimeout: 2000, // optional, default 1000
|
|
775
|
+
})
|
|
763
776
|
|
|
764
|
-
const { StateVocabProvider } = serverStorage
|
|
777
|
+
const { StateVocabProvider } = serverStorage
|
|
765
778
|
|
|
766
|
-
|
|
767
|
-
serverStorage.
|
|
768
|
-
serverStorage.
|
|
769
|
-
serverStorage.seed({
|
|
779
|
+
// In a Server Component:
|
|
780
|
+
serverStorage.start() // register before rendering
|
|
781
|
+
await serverStorage.user.name.getState() // reads "user.name" (async)
|
|
782
|
+
serverStorage.user.seed({ name: 'Alice' }) // → { user: { name: 'Alice' } }
|
|
783
|
+
serverStorage.person.address.seed({ city: 'NY' }) // → { person: { address: { city: 'NY' } } }
|
|
784
|
+
serverStorage.seed({ user: { name: 'Alice' } }) // → { user: { name: 'Alice' } } (identity)
|
|
770
785
|
```
|
|
771
786
|
|
|
772
787
|
### `clientify<T>(storage: T, options?)`
|
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-CuApuc3e.js"),V=require("./provider-client-DRdFy5dG.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))},R=typeof window>"u",m=R?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 I(t){const n=R?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),z=f.useRef(!1);if(!z.current){z.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 p(t){const n=R?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 k(t){return typeof t=="object"&&t!==null&&"clientSlot"in t}function O(t,n={}){const s={};for(const o in t){const e=t[o];k(e)?(s[o]=e.clientSlot({useState(l){return I.apply(this,[{clientContext:n.clientContext,...l}])},useInitialState(l){p.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
2
|
import { useMemo as j, useRef as y, 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 C, u as _ } from "./provider-client-
|
|
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-xNWifFE9.mjs";
|
|
5
|
+
import { V as C, u as _ } from "./provider-client-BhPeK8Kz.mjs";
|
|
6
|
+
import { S as ne } from "./provider-client-BhPeK8Kz.mjs";
|
|
7
7
|
function K(t, s, i = []) {
|
|
8
8
|
return j(
|
|
9
9
|
() => G(t, s),
|
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-CuApuc3e.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,13 +1,14 @@
|
|
|
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-xNWifFE9.mjs";
|
|
5
5
|
const c = l({});
|
|
6
6
|
function m(e) {
|
|
7
7
|
const t = h(e.clientContext ?? c);
|
|
8
8
|
return e.verbose && console.log(`[Store uid]: ${t.uid}`), t;
|
|
9
9
|
}
|
|
10
10
|
class d {
|
|
11
|
+
uid;
|
|
11
12
|
#t;
|
|
12
13
|
#e;
|
|
13
14
|
constructor(t) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";"use strict";const h=require("react/jsx-runtime"),c=require("react"),r=require("./utils-CuApuc3e.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;
|
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 y=require("react/jsx-runtime"),S=require("./constants-CbsduCZ7.js"),l=require("react"),m=require("./provider-client-DRdFy5dG.js"),a=require("./utils-CuApuc3e.js"),d=e=>{if(l.useState)throw new Error(`${e} only intended for Server Components`)},c=l.cache(()=>new Map),f=async e=>(d("getStateVocab"),await c().get(e)),u="Make sure your component is wrapped in StateVocabProvider";async function w(e){const t=this[S.STATE_PATH],r=await a.withTimeout(f(e.serverContextKey),e.timeout,`Failed access to "${t}". Reason: Operation timed out after ${e.timeout}ms. ${u}.`);if(!r)throw new Error(u);return a.get(r,t)}function b(e){return typeof e=="object"&&e!==null&&"serverSlot"in e}function v(e,t){const r={};for(const o in e){const n=e[o];if(b(n))r[o]=n.serverSlot({getState(){return w.apply(this,[{serverContextKey:t.serverContextKey,timeout:t.serverTimeout}])}}),delete r[o].serverSlot,delete r[o].clientSlot;else if(n!==null&&typeof n=="object"){const i=s=>t.wrap({[o]:s});r[o]=v(n,{serverContextKey:t.serverContextKey,serverTimeout:t.serverTimeout,wrap:i})}else r[o]=n}return r.seed=o=>t.wrap(o),r}function x(e,t){const r=Object.keys(e).slice(0,3).join("-"),o=Symbol(r),n=Promise.withResolvers();return{...v(e,{serverContextKey:o,serverTimeout:t.serverTimeout??1e3,wrap:i=>i}),start(){const{size:i}=c(),s=Symbol("test");if(c().set(s,n.promise),c().size===i)throw new Error("Start execution only within a React render context (per-request)");c().delete(s),c().set(o,n.promise)},StateVocabProvider({children:i,value:s}){return s??={},n.resolve(s),y.jsx(m.StateVocabClientProvider,{clientContext:t.clientContext,value:s,children:i})}}}exports.serverify=x;
|
package/dist/server.es.js
CHANGED
|
@@ -1,104 +1,76 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { S as
|
|
3
|
-
import
|
|
4
|
-
import { S as
|
|
5
|
-
import { g as
|
|
6
|
-
const
|
|
7
|
-
if (
|
|
1
|
+
import { jsx as u } from "react/jsx-runtime";
|
|
2
|
+
import { S as m } from "./constants-BB1YAX6c.mjs";
|
|
3
|
+
import S, { cache as v } from "react";
|
|
4
|
+
import { S as y } from "./provider-client-BhPeK8Kz.mjs";
|
|
5
|
+
import { w as f, g as w } from "./utils-xNWifFE9.mjs";
|
|
6
|
+
const p = (e) => {
|
|
7
|
+
if (S.useState)
|
|
8
8
|
throw new Error(`${e} only intended for Server Components`);
|
|
9
|
-
},
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}, m = (e) => {
|
|
16
|
-
const { serverContextKey: o, value: t, children: r } = e;
|
|
17
|
-
return /* @__PURE__ */ c(
|
|
18
|
-
b.Provider,
|
|
19
|
-
{
|
|
20
|
-
serverContextKey: o,
|
|
21
|
-
value: t,
|
|
22
|
-
children: r
|
|
23
|
-
}
|
|
24
|
-
);
|
|
25
|
-
};
|
|
26
|
-
function h(e) {
|
|
27
|
-
const {
|
|
28
|
-
children: o,
|
|
29
|
-
serverContextKey: t,
|
|
30
|
-
clientContext: r,
|
|
31
|
-
value: n = {}
|
|
32
|
-
} = e;
|
|
33
|
-
return /* @__PURE__ */ c(
|
|
34
|
-
m,
|
|
35
|
-
{
|
|
36
|
-
serverContextKey: t,
|
|
37
|
-
value: n,
|
|
38
|
-
children: /* @__PURE__ */ c(
|
|
39
|
-
f,
|
|
40
|
-
{
|
|
41
|
-
clientContext: r,
|
|
42
|
-
value: n,
|
|
43
|
-
children: o
|
|
44
|
-
}
|
|
45
|
-
)
|
|
46
|
-
}
|
|
9
|
+
}, c = v(() => /* @__PURE__ */ new Map()), d = async (e) => (p("getStateVocab"), await c().get(e)), a = "Make sure your component is wrapped in StateVocabProvider";
|
|
10
|
+
async function x(e) {
|
|
11
|
+
const t = this[m], r = await f(
|
|
12
|
+
d(e.serverContextKey),
|
|
13
|
+
e.timeout,
|
|
14
|
+
`Failed access to "${t}". Reason: Operation timed out after ${e.timeout}ms. ${a}.`
|
|
47
15
|
);
|
|
16
|
+
if (!r)
|
|
17
|
+
throw new Error(a);
|
|
18
|
+
return w(r, t);
|
|
48
19
|
}
|
|
49
|
-
|
|
50
|
-
function w(e) {
|
|
51
|
-
const o = this[u], t = x(e.serverContextKey);
|
|
52
|
-
if (!t)
|
|
53
|
-
throw new Error(P);
|
|
54
|
-
return y(t, o);
|
|
55
|
-
}
|
|
56
|
-
function K(e) {
|
|
20
|
+
function b(e) {
|
|
57
21
|
return typeof e == "object" && e !== null && "serverSlot" in e;
|
|
58
22
|
}
|
|
59
|
-
function
|
|
60
|
-
const
|
|
61
|
-
for (const
|
|
62
|
-
const n = e[
|
|
63
|
-
if (
|
|
64
|
-
|
|
23
|
+
function l(e, t) {
|
|
24
|
+
const r = {};
|
|
25
|
+
for (const o in e) {
|
|
26
|
+
const n = e[o];
|
|
27
|
+
if (b(n))
|
|
28
|
+
r[o] = n.serverSlot({
|
|
65
29
|
getState() {
|
|
66
|
-
return
|
|
67
|
-
serverContextKey:
|
|
30
|
+
return x.apply(this, [{
|
|
31
|
+
serverContextKey: t.serverContextKey,
|
|
32
|
+
timeout: t.serverTimeout
|
|
68
33
|
}]);
|
|
69
34
|
}
|
|
70
|
-
}), delete
|
|
35
|
+
}), delete r[o].serverSlot, delete r[o].clientSlot;
|
|
71
36
|
else if (n !== null && typeof n == "object") {
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
serverContextKey:
|
|
75
|
-
|
|
37
|
+
const i = (s) => t.wrap({ [o]: s });
|
|
38
|
+
r[o] = l(n, {
|
|
39
|
+
serverContextKey: t.serverContextKey,
|
|
40
|
+
serverTimeout: t.serverTimeout,
|
|
41
|
+
wrap: i
|
|
76
42
|
});
|
|
77
43
|
} else
|
|
78
|
-
|
|
44
|
+
r[o] = n;
|
|
79
45
|
}
|
|
80
|
-
return
|
|
46
|
+
return r.seed = (o) => t.wrap(o), r;
|
|
81
47
|
}
|
|
82
|
-
function
|
|
83
|
-
const
|
|
48
|
+
function E(e, t) {
|
|
49
|
+
const r = Object.keys(e).slice(0, 3).join("-"), o = Symbol(r), n = Promise.withResolvers();
|
|
84
50
|
return {
|
|
85
|
-
...
|
|
86
|
-
serverContextKey:
|
|
87
|
-
|
|
51
|
+
...l(e, {
|
|
52
|
+
serverContextKey: o,
|
|
53
|
+
serverTimeout: t.serverTimeout ?? 1e3,
|
|
54
|
+
wrap: (i) => i
|
|
88
55
|
}),
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
56
|
+
start() {
|
|
57
|
+
const { size: i } = c(), s = /* @__PURE__ */ Symbol("test");
|
|
58
|
+
if (c().set(s, n.promise), c().size === i)
|
|
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,
|
|
92
65
|
{
|
|
93
|
-
clientContext:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
children: r
|
|
66
|
+
clientContext: t.clientContext,
|
|
67
|
+
value: s,
|
|
68
|
+
children: i
|
|
97
69
|
}
|
|
98
70
|
);
|
|
99
71
|
}
|
|
100
72
|
};
|
|
101
73
|
}
|
|
102
74
|
export {
|
|
103
|
-
|
|
75
|
+
E as serverify
|
|
104
76
|
};
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import type { PropsWithChildren, ReactNode } from "react";
|
|
3
1
|
import type { Vocab } from "./state.types";
|
|
4
|
-
export declare const
|
|
5
|
-
export declare const
|
|
6
|
-
Provider: (({ children }: PropsWithChildren<{
|
|
7
|
-
value?: Vocab;
|
|
8
|
-
}>) => ReactNode) | ((props: PropsWithChildren<{
|
|
9
|
-
serverContextKey: symbol;
|
|
10
|
-
value: Vocab;
|
|
11
|
-
}>) => Promise<React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | (string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined)>);
|
|
12
|
-
};
|
|
2
|
+
export declare const getRequestStore: () => Map<symbol, Promise<Vocab>>;
|
|
3
|
+
export declare const getStateVocab: (serverContextKey: symbol) => Promise<Vocab | undefined>;
|
|
@@ -1,28 +1,36 @@
|
|
|
1
1
|
import type { Context, PropsWithChildren, ReactNode } from "react";
|
|
2
|
-
import type { Vocab } from "./state.types";
|
|
2
|
+
import type { Vocab, VocabThis } from "./state.types";
|
|
3
3
|
type Placeholder<V> = {
|
|
4
|
-
getState(): V
|
|
5
|
-
};
|
|
6
|
-
type Slot<V> = {
|
|
7
|
-
serverSlot(input: Placeholder<V>): Placeholder<V>;
|
|
4
|
+
getState(): Promise<V>;
|
|
8
5
|
};
|
|
6
|
+
type SlotValue<T> = T extends {
|
|
7
|
+
serverSlot(input: {
|
|
8
|
+
getState(this: VocabThis): infer V;
|
|
9
|
+
}): unknown;
|
|
10
|
+
} ? V : never;
|
|
9
11
|
type ServerifiedValue<R> = {
|
|
10
|
-
[K in keyof 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]>;
|
|
11
15
|
};
|
|
12
|
-
type Serverified<R> =
|
|
16
|
+
type Serverified<R> = [
|
|
17
|
+
SlotValue<R>
|
|
18
|
+
] extends [never] ? R extends object ? {
|
|
13
19
|
seed(input: ServerifiedValue<R>): Vocab;
|
|
14
20
|
} & {
|
|
15
21
|
[K in keyof R]: Serverified<R[K]>;
|
|
16
|
-
} : R
|
|
22
|
+
} : R : Placeholder<SlotValue<R>>;
|
|
17
23
|
type ServerifyResult<R extends object> = {
|
|
24
|
+
start(): void;
|
|
18
25
|
seed(input: ServerifiedValue<R>): Vocab;
|
|
19
26
|
StateVocabProvider(props: PropsWithChildren<{
|
|
20
27
|
value?: ServerifiedValue<R>;
|
|
21
|
-
}>):
|
|
28
|
+
}>): ReactNode;
|
|
22
29
|
} & {
|
|
23
30
|
[K in keyof R]: Serverified<R[K]>;
|
|
24
31
|
};
|
|
25
32
|
export declare function serverify<R extends object>(tree: R, serverifyOptions: {
|
|
26
33
|
clientContext: Context<object>;
|
|
34
|
+
serverTimeout?: number;
|
|
27
35
|
}): ServerifyResult<R>;
|
|
28
36
|
export {};
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -7,3 +7,4 @@ export declare function logStyled(obj: unknown): void;
|
|
|
7
7
|
export declare const isTransformer: <V>(v: ValueOrTransformer<V>) => v is Transformer<V>;
|
|
8
8
|
export declare const isValueDefined: <V>(v: V | undefined) => v is V;
|
|
9
9
|
export declare const valueOrFactory: <V>(input: ValueOrFactory<V>) => V;
|
|
10
|
+
export declare function withTimeout<T>(promise: Promise<T>, ms: number, message: string): Promise<T>;
|
|
@@ -0,0 +1,3 @@
|
|
|
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;
|
|
@@ -0,0 +1,73 @@
|
|
|
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
|
+
};
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
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{#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;
|
package/dist/types/provider.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { Context, PropsWithChildren } from "react";
|
|
2
|
-
import type { Vocab } from "./state.types";
|
|
3
|
-
import VocabStore from "./store";
|
|
4
|
-
export declare function StateVocabProvider(props: PropsWithChildren<{
|
|
5
|
-
value?: Vocab;
|
|
6
|
-
serverContextKey: symbol;
|
|
7
|
-
clientContext: Context<VocabStore>;
|
|
8
|
-
}>): import("react/jsx-runtime").JSX.Element;
|
package/dist/utils-0CTNJ4ZE.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
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=$;
|
package/dist/utils-xV3x3fTc.mjs
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
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
|
-
};
|