chizu 0.2.65 → 0.2.67
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 +31 -27
- package/dist/action/index.d.ts +2 -2
- package/dist/boundary/components/broadcast/types.d.ts +1 -1
- package/dist/boundary/components/consumer/components/partition/index.d.ts +4 -4
- package/dist/boundary/components/consumer/index.d.ts +1 -1
- package/dist/boundary/components/consumer/types.d.ts +4 -4
- package/dist/chizu.js +7 -7
- package/dist/chizu.umd.cjs +1 -1
- package/dist/hooks/types.d.ts +19 -1
- package/dist/hooks/utils.d.ts +4 -13
- package/dist/types/index.d.ts +45 -39
- package/dist/utils/index.d.ts +18 -4
- package/package.json +26 -26
package/README.md
CHANGED
|
@@ -176,15 +176,7 @@ actions.useAction(Actions.Profile, async (context) => {
|
|
|
176
176
|
});
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
-
Once we have the broadcast action, if we want to
|
|
180
|
-
|
|
181
|
-
```tsx
|
|
182
|
-
const [model] = actions.derive("name", Actions.Broadcast.Name, (name) => name);
|
|
183
|
-
|
|
184
|
-
// model.name is null until the first dispatch, then stays in sync
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
If we want to listen for it and perform another operation in our local component we can do that via `useAction`:
|
|
179
|
+
Once we have the broadcast action, if we want to listen for it and perform another operation in our local component we can do that via `useAction`:
|
|
188
180
|
|
|
189
181
|
```tsx
|
|
190
182
|
actions.useAction(Actions.Broadcast.Name, async (context, name) => {
|
|
@@ -196,7 +188,7 @@ actions.useAction(Actions.Broadcast.Name, async (context, name) => {
|
|
|
196
188
|
});
|
|
197
189
|
```
|
|
198
190
|
|
|
199
|
-
|
|
191
|
+
Both `read` and `peek` access the latest cached broadcast value without subscribing via `useAction`. The difference is that `read` waits for any pending annotations on the corresponding model field to settle before resolving, whereas `peek` returns the value immediately:
|
|
200
192
|
|
|
201
193
|
```tsx
|
|
202
194
|
actions.useAction(Actions.FetchFriends, async (context) => {
|
|
@@ -209,6 +201,34 @@ actions.useAction(Actions.FetchFriends, async (context) => {
|
|
|
209
201
|
});
|
|
210
202
|
```
|
|
211
203
|
|
|
204
|
+
`peek` is useful for guard checks or synchronous reads where you don't need to wait for settled state:
|
|
205
|
+
|
|
206
|
+
```tsx
|
|
207
|
+
actions.useAction(Actions.Check, (context) => {
|
|
208
|
+
const name = context.actions.peek(Actions.Broadcast.Name);
|
|
209
|
+
if (!name) return;
|
|
210
|
+
console.log(name);
|
|
211
|
+
});
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
You can also render broadcast values declaratively in JSX with `actions.stream`. The renderer callback receives `(value, inspect)` and returns React nodes:
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
function Dashboard() {
|
|
218
|
+
const [model, actions] = useDashboardActions();
|
|
219
|
+
|
|
220
|
+
return (
|
|
221
|
+
<div>
|
|
222
|
+
{actions.stream(Actions.Broadcast.User, (user, inspect) => (
|
|
223
|
+
<span>Welcome, {user.name}</span>
|
|
224
|
+
))}
|
|
225
|
+
</div>
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Components that mount after a broadcast has already been dispatched automatically receive the cached value via their `useAction` handler. If you also fetch data in `Lifecycle.Mount`, see the [mount deduplication recipe](./recipes/mount-broadcast-deduplication.md) to avoid duplicate requests.
|
|
231
|
+
|
|
212
232
|
For targeted event delivery, use channeled actions. Define a channel type as the second generic argument and call the action with a channel object – handlers fire when the dispatch channel matches:
|
|
213
233
|
|
|
214
234
|
```tsx
|
|
@@ -279,12 +299,9 @@ function App() {
|
|
|
279
299
|
|
|
280
300
|
// Dispatch to all components within "TeamA" scope
|
|
281
301
|
actions.dispatch(Actions.Multicast.Update, 42, { scope: "TeamA" });
|
|
282
|
-
|
|
283
|
-
// Subscribe to multicast values with derive
|
|
284
|
-
const [model] = actions.derive("score", Actions.Multicast.Update, (v) => v);
|
|
285
302
|
```
|
|
286
303
|
|
|
287
|
-
Unlike broadcast which reaches all components, multicast is scoped to the named boundary – perfect for isolated widget groups, form sections, or distinct UI regions.
|
|
304
|
+
Unlike broadcast which reaches all components, multicast is scoped to the named boundary – perfect for isolated widget groups, form sections, or distinct UI regions. Like broadcast, multicast caches dispatched values per scope – components that mount later automatically receive the cached value. See the [mount deduplication recipe](./recipes/mount-broadcast-deduplication.md) if you also fetch data in `Lifecycle.Mount`.
|
|
288
305
|
|
|
289
306
|
For components that always render inside a scope, use the `withScope` HOC to eliminate the manual `<Scope>` wrapper:
|
|
290
307
|
|
|
@@ -359,16 +376,3 @@ context.actions.invalidate(CacheStore.User({ UserId: 5 }));
|
|
|
359
376
|
```
|
|
360
377
|
|
|
361
378
|
The cache is scoped to the nearest `<Boundary>`. See the [caching recipe](./recipes/caching.md) for more details.
|
|
362
|
-
|
|
363
|
-
When you want to expose a derived value alongside your model without storing it separately, use `derive` to overlay computed properties on top of the model:
|
|
364
|
-
|
|
365
|
-
```tsx
|
|
366
|
-
return actions
|
|
367
|
-
.derive("greeting", (model) => `Hello #${model.count}`)
|
|
368
|
-
.derive("doubled", Actions.Broadcast.Counter, (counter) => counter * 2)
|
|
369
|
-
.derive("label", Actions.Decrement, () => "decremented");
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
Model-based entries receive the current model, evaluate on every render, and always have a value. Action-based entries are `null` before the action fires; callback parameters are auto-typed from the action's payload. Calls are chained, and the component renders once even when a normal handler and a derived entry fire together.
|
|
373
|
-
|
|
374
|
-
See the [derived values recipe](./recipes/derived-values.md) for more details.
|
package/dist/action/index.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ type ActionFactory = {
|
|
|
51
51
|
* // Action with channel support for targeted dispatches
|
|
52
52
|
* static UserUpdated = Action<User, { UserId: number }>("UserUpdated");
|
|
53
53
|
*
|
|
54
|
-
* // Broadcast action - can be
|
|
54
|
+
* // Broadcast action - can be read across components
|
|
55
55
|
* static Counter = Action<number>("Counter", Distribution.Broadcast);
|
|
56
56
|
* }
|
|
57
57
|
*
|
|
@@ -60,7 +60,7 @@ type ActionFactory = {
|
|
|
60
60
|
* actions.dispatch(Actions.Increment, 5);
|
|
61
61
|
* actions.dispatch(Actions.UserUpdated, user); // broadcast to all
|
|
62
62
|
* actions.dispatch(Actions.UserUpdated({ UserId: 5 }), user); // channeled dispatch
|
|
63
|
-
* actions.
|
|
63
|
+
* actions.stream(Actions.Counter, (box) => box.value);
|
|
64
64
|
* ```
|
|
65
65
|
*/
|
|
66
66
|
export declare const Action: ActionFactory;
|
|
@@ -3,7 +3,7 @@ import * as React from "react";
|
|
|
3
3
|
/**
|
|
4
4
|
* The broadcast context is a BroadcastEmitter used for distributed actions across components.
|
|
5
5
|
* Extends EventEmitter with a per-action value cache so late-mounting components can replay
|
|
6
|
-
* broadcast values even without a Partition (from `
|
|
6
|
+
* broadcast values even without a Partition (from `stream()`).
|
|
7
7
|
*/
|
|
8
8
|
export type BroadcastContext = BroadcastEmitter;
|
|
9
9
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Props } from './types.ts';
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
/**
|
|
4
|
-
* Renders output for the `
|
|
4
|
+
* Renders output for the `stream()` method by subscribing to distributed action events.
|
|
5
5
|
*
|
|
6
6
|
* This component manages a subscription to the broadcast emitter for distributed actions,
|
|
7
7
|
* storing the latest dispatched value in the Consumer context. When a new value arrives,
|
|
@@ -14,14 +14,14 @@ import * as React from "react";
|
|
|
14
14
|
* annotation tracking through the `inspect` proxy. When a payload containing annotated
|
|
15
15
|
* values is dispatched, the annotations are preserved and accessible via `inspect`.
|
|
16
16
|
*
|
|
17
|
-
* The renderer callback receives
|
|
17
|
+
* The renderer callback receives two arguments:
|
|
18
18
|
* - `value`: The latest dispatched payload
|
|
19
19
|
* - `inspect`: A proxy for checking annotation status (pending, is, draft, settled, etc.)
|
|
20
20
|
*
|
|
21
21
|
* @template T - The payload type for the action (must be an object type)
|
|
22
22
|
* @param props.action - The distributed action symbol to subscribe to
|
|
23
|
-
* @param props.renderer - Callback that receives
|
|
24
|
-
* @returns The result of calling renderer
|
|
23
|
+
* @param props.renderer - Callback that receives value and inspect, returns React nodes
|
|
24
|
+
* @returns The result of calling renderer, or null if no value exists
|
|
25
25
|
* @internal
|
|
26
26
|
*/
|
|
27
27
|
export declare function Partition<T extends object>({ action, renderer, }: Props<T>): React.ReactNode;
|
|
@@ -11,7 +11,7 @@ export type { ConsumerRenderer, Entry, ConsumerContext } from './types.ts';
|
|
|
11
11
|
*
|
|
12
12
|
* The Consumer stores the latest value for each distributed action, allowing components
|
|
13
13
|
* that mount later to access values that were dispatched before they mounted. This enables
|
|
14
|
-
* the `
|
|
14
|
+
* the `stream()` method to render the most recent value immediately.
|
|
15
15
|
*
|
|
16
16
|
* @param props.children - The children to render within the consumer context.
|
|
17
17
|
* @returns The children wrapped in a consumer context provider.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Inspect, State } from 'immertation';
|
|
2
2
|
import { ActionId } from '../tasks/types.ts';
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
/**
|
|
5
|
-
* Callback function for the
|
|
6
|
-
* Receives
|
|
5
|
+
* Callback function for the stream() method.
|
|
6
|
+
* Receives the dispatched value and an inspect proxy for annotation tracking.
|
|
7
7
|
*
|
|
8
8
|
* @template T - The payload type
|
|
9
9
|
*/
|
|
10
|
-
export type ConsumerRenderer<T> = (
|
|
10
|
+
export type ConsumerRenderer<T> = (value: T, inspect: Inspect<T>) => React.ReactNode;
|
|
11
11
|
/**
|
|
12
12
|
* Model for consumed values.
|
|
13
13
|
* Allows Immertation's State to manage the value with real inspect capabilities.
|
package/dist/chizu.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{G as e,A as t}from"@mobily/ts-belt";import{jsx as n}from"react/jsx-runtime";import*as r from"react";import{createContext as o,useContext as c}from"react";import{immerable as i,enablePatches as s,Immer as a}from"immer";class u{static Payload=/* @__PURE__ */Symbol("chizu.brand/Payload");static Broadcast=/* @__PURE__ */Symbol("chizu.brand/Broadcast");static Multicast=/* @__PURE__ */Symbol("chizu.brand/Multicast");static Action=/* @__PURE__ */Symbol("chizu.brand/Action");static Channel=/* @__PURE__ */Symbol("chizu.brand/Channel");static Node=/* @__PURE__ */Symbol("chizu.action.lifecycle/Node");static Cache=/* @__PURE__ */Symbol("chizu.brand/Cache")}class l{static Mount=/* @__PURE__ */Symbol("chizu.action.lifecycle/Mount");static Unmount=/* @__PURE__ */Symbol("chizu.action.lifecycle/Unmount");static Error=/* @__PURE__ */Symbol("chizu.action.lifecycle/Error");static Update=/* @__PURE__ */Symbol("chizu.action.lifecycle/Update");static Node=(()=>{const e=u.Node,t=function(t){return{[u.Action]:e,[u.Payload]:void 0,[u.Channel]:t,channel:t}};return Object.defineProperty(t,u.Action,{value:e,enumerable:!1}),Object.defineProperty(t,u.Payload,{value:void 0,enumerable:!1}),t})()}var f=/* @__PURE__ */(e=>(e.Unicast="unicast",e.Broadcast="broadcast",e.Multicast="multicast",e))(f||{}),d=/* @__PURE__ */(e=>(e.Mounting="mounting",e.Mounted="mounted",e.Unmounting="unmounting",e.Unmounted="unmounted",e))(d||{}),
|
|
2
|
-
return n(
|
|
3
|
-
return n(
|
|
4
|
-
return n(
|
|
5
|
-
return n(
|
|
6
|
-
return n(
|
|
7
|
-
return n(
|
|
1
|
+
import{G as e,A as t}from"@mobily/ts-belt";import{jsx as n}from"react/jsx-runtime";import*as r from"react";import{createContext as o,useContext as c}from"react";import{immerable as i,enablePatches as s,Immer as a}from"immer";class u{static Payload=/* @__PURE__ */Symbol("chizu.brand/Payload");static Broadcast=/* @__PURE__ */Symbol("chizu.brand/Broadcast");static Multicast=/* @__PURE__ */Symbol("chizu.brand/Multicast");static Action=/* @__PURE__ */Symbol("chizu.brand/Action");static Channel=/* @__PURE__ */Symbol("chizu.brand/Channel");static Node=/* @__PURE__ */Symbol("chizu.action.lifecycle/Node");static Cache=/* @__PURE__ */Symbol("chizu.brand/Cache")}class l{static Mount=/* @__PURE__ */Symbol("chizu.action.lifecycle/Mount");static Unmount=/* @__PURE__ */Symbol("chizu.action.lifecycle/Unmount");static Error=/* @__PURE__ */Symbol("chizu.action.lifecycle/Error");static Update=/* @__PURE__ */Symbol("chizu.action.lifecycle/Update");static Node=(()=>{const e=u.Node,t=function(t){return{[u.Action]:e,[u.Payload]:void 0,[u.Channel]:t,channel:t}};return Object.defineProperty(t,u.Action,{value:e,enumerable:!1}),Object.defineProperty(t,u.Payload,{value:void 0,enumerable:!1}),t})()}var f=/* @__PURE__ */(e=>(e.Unicast="unicast",e.Broadcast="broadcast",e.Multicast="multicast",e))(f||{}),d=/* @__PURE__ */(e=>(e.Mounting="mounting",e.Mounted="mounted",e.Unmounting="unmounting",e.Unmounted="unmounted",e))(d||{}),p=/* @__PURE__ */(e=>(e[e.Timedout=0]="Timedout",e[e.Supplanted=1]="Supplanted",e[e.Disallowed=2]="Disallowed",e[e.Errored=3]="Errored",e[e.Unmounted=4]="Unmounted",e))(p||{});class h extends Error{name="AbortError";constructor(e="Aborted"){super(e)}}const m={actionPrefix:"chizu.action/",broadcastActionPrefix:"chizu.action/broadcast/",multicastActionPrefix:"chizu.action/multicast/",channelPrefix:"chizu.channel/",cachePrefix:"chizu.cache/"};function y(e,t){return new Promise((n,r)=>{if(t?.aborted)return void r(new h);const o=setTimeout(n,e);t?.addEventListener("abort",()=>{clearTimeout(o),r(new h)},{once:!0})})}async function b(e,t,n){if(t?.aborted)throw new h;for(;;){if(await n())return;await y(e,t)}}function v(e){return e?Boolean(e&&"symbol"!=typeof e):/* @__PURE__ */Symbol(`pk.${Date.now()}.${crypto.randomUUID()}`)}const g=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,config:m,pk:v,poll:b,sleep:y,"ζ":y,"κ":v,"π":b},Symbol.toStringTag,{value:"Module"})),w=e=>"symbol"==typeof e;function x(t){return e.isString(t)||w(t)?t:(e.isObject(t)||e.isFunction(t))&&u.Action in t?t[u.Action]:t}function S(t){if(e.isString(t))return t.startsWith(m.broadcastActionPrefix);if(w(t))return t.description?.startsWith(m.broadcastActionPrefix)??!1;if(e.isObject(t)||e.isFunction(t)){if(u.Broadcast in t&&t[u.Broadcast])return!0;if(u.Action in t){const e=t[u.Action];return e.description?.startsWith(m.broadcastActionPrefix)??!1}}return!1}function P(t){const n=x(t),r=e.isString(n)?n:n.description??"";return r.startsWith(m.actionPrefix)&&r.slice(r.lastIndexOf("/")+1)||"unknown"}function E(t){return e.isObject(t)&&u.Channel in t&&"channel"in t}function O(t){if(e.isString(t))return t.startsWith(m.multicastActionPrefix);if(w(t))return t.description?.startsWith(m.multicastActionPrefix)??!1;if(e.isObject(t)||e.isFunction(t)){if(u.Multicast in t&&t[u.Multicast])return!0;if(u.Action in t){const e=t[u.Action];return e.description?.startsWith(m.multicastActionPrefix)??!1}}return!1}const j=(e,t=f.Unicast)=>{const n=t===f.Broadcast?/* @__PURE__ */Symbol(`${m.broadcastActionPrefix}${e}`):t===f.Multicast?/* @__PURE__ */Symbol(`${m.multicastActionPrefix}${e}`):/* @__PURE__ */Symbol(`${m.actionPrefix}${e}`),r=function(e){return{[u.Action]:n,[u.Payload]:void 0,[u.Channel]:e,channel:e}};return Object.defineProperty(r,u.Action,{value:n,enumerable:!1}),Object.defineProperty(r,u.Payload,{value:void 0,enumerable:!1}),t===f.Broadcast&&Object.defineProperty(r,u.Broadcast,{value:!0,enumerable:!1}),t===f.Multicast&&Object.defineProperty(r,u.Multicast,{value:!0,enumerable:!1}),r};function A(){const e=/* @__PURE__ */Symbol("chizu.cache/Entry"),t=function(t){return{[u.Cache]:e,channel:t}};return Object.defineProperty(t,u.Cache,{value:e,enumerable:!1}),t}function C(e){const t=function(e){return e[u.Cache]}(e),n=function(e){return"channel"in e}(e)&&(r=e.channel)?[...Object.keys(r)].toSorted().map(e=>`${e}=${String(r[e])}`).join("&"):"";var r;return`${String(t)}:${n}`}function M(e){if(e instanceof Error){if("TimeoutError"===e.name)return p.Timedout;if("AbortError"===e.name)return p.Supplanted}return p.Errored}function k(e){return e instanceof Error?e:new Error(String(e))}const _=o(void 0);function R({handler:e,children:t}){/* @__PURE__ */
|
|
2
|
+
return n(_.Provider,{value:e,children:t})}let N=(e=21)=>{let t="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)t+="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"[63&n[e]];return t};var U=/* @__PURE__ */(e=>(e[e.Add=1]="Add",e[e.Remove=2]="Remove",e[e.Update=4]="Update",e[e.Move=8]="Move",e[e.Replace=16]="Replace",e[e.Sort=32]="Sort",e[e.Create=64]="Create",e[e.Fetch=128]="Fetch",e[e.Clone=256]="Clone",e[e.Archive=512]="Archive",e[e.Restore=1024]="Restore",e[e.Merge=2048]="Merge",e[e.Reorder=4096]="Reorder",e[e.Sync=8192]="Sync",e[e.Publish=16384]="Publish",e[e.Link=32768]="Link",e[e.Unlink=65536]="Unlink",e[e.Lock=131072]="Lock",e[e.Unlock=262144]="Unlock",e[e.Import=524288]="Import",e[e.Export=1048576]="Export",e[e.Transfer=2097152]="Transfer",e))(U||{}),z=/* @__PURE__ */(e=>(e[e.Produce=0]="Produce",e[e.Hydrate=1]="Hydrate",e))(z||{}),L=/* @__PURE__ */(e=>(e.Property="property",e.Process="process",e.Value="value",e.Operation="operation",e))(L||{});class T{[i]=!0;static keys=new Set(Object.values(L));property=null;process=null;value;operation;constructor(e,t){this.value=e,this.operation=t}assign(e,t){const n=new T(this.value,this.operation);return n.property=e,n.process=t,n}}class ${static immer=(()=>{s();const e=new a;return e.setAutoFreeze(!1),e})();static tag="κ";static id=N}function B(e,t){const n="string"==typeof t?""===t?[]:t.split("."):t;let r=e;for(const o of n){if(null==r)return;r=r[o]}return r}function F(t){if(e.isNullable(t)||H(t))return t;if(e.isArray(t))return t.map(e=>F(e));if(e.isObject(t)&&D(t)){const e=Object.entries(t).map(([e,t])=>[e,F(t)]);return{...Object.fromEntries(e),[$.tag]:t[$.tag]??$.id()}}return t}function W(e){if(Array.isArray(e))return e.filter(e=>$.tag in e).map(e=>e[$.tag]??"").join(",");const t=e[$.tag];if(t)return t;try{return JSON.stringify(e)}catch{return`[unserializable:${typeof e}]`}}function D(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}function H(t){return e.isNullable(t)||e.isString(t)||e.isNumber(t)||e.isBoolean(t)||"symbol"==typeof t||"bigint"==typeof t}function G(t,n,r,o,c,i){return function s(a,u=n.path){if(a instanceof T){const n=B(r,u.join("."));if(Object.entries(a).filter(([e,t])=>!T.keys.has(e)&&t instanceof T).forEach(([e,t])=>s(t,u.concat(e))),H(a.value)){if(t===z.Hydrate)return a.value;const s=u.slice(0,-1),l=s.length>0?B(r,s.join(".")):r;return e.isNullable(l)||I(l,a,u.at(-1),o,c,i),n??a.value}if(t===z.Hydrate){const e=F(s(a.value,u));return I(e,a,null,o,c,i),e}const l=n??F(a.value);return I(l,a,null,o,c,i),e.isNullable(n)?l:(s(a.value,u),n)}if(e.isArray(a))return a.map((e,t)=>s(e,u.concat(t)));if(e.isObject(a)&&!D(a))return a;if(e.isObject(a)){const e=Object.entries(a).map(([e,t])=>[e,s(t,u.concat(e))]),n=Object.fromEntries(e);if(t===z.Hydrate){const e=F(n);return Object.entries(a).forEach(([t,n])=>{n instanceof T&&H(n.value)&&I(e,n,t,o,c,i)}),e}return n}return a}(n.value)}function I(e,t,n,r,o,c){const i=c(e),s=o.get(i)??[];o.set(i,[t.assign(n,r),...s])}class V{#e={};#t;#n=/* @__PURE__ */new Map;#r=/* @__PURE__ */new Set;#o=!1;constructor(e=W){this.#t=e}static pk(){return N()}static"κ"=V.pk;annotate(e,t){return new T(t,e)}"δ"=this.annotate;get model(){return this.#e}get inspect(){return function(n,r,o,c,i){function s(c){const i=c.at(-1),s=B(n(),c),a=c.slice(0,-1),u=t.isNotEmpty(a)?B(n(),a):n();return[...e.isObject(s)||e.isArray(s)?r.get(o(s))?.filter(t=>e.isNullable(t.property))??[]:[],...e.isObject(u)?r.get(o(u))?.filter(e=>e.property===i)??[]:[]]}return function e(r){return new Proxy(()=>{},{get:(o,a)=>"pending"===a?()=>!t.isEmpty(s(r)):"remaining"===a?()=>t.length(s(r)):"box"===a?()=>({value:B(n(),r),inspect:e(r)}):"is"===a?e=>s(r).some(t=>0!==(t.operation&e)):"draft"===a?()=>t.head(s(r))?.value??B(n(),r):"settled"===a?()=>new Promise(e=>{if(t.isEmpty(s(r)))return e(B(n(),r));const o=()=>{t.isEmpty(s(r))&&(i(o),e(B(n(),r)))};c(o)}):e([...r,String(a)])})}([])}(()=>this.#e,this.#n,this.#t,e=>this.#r.add(e),e=>this.#r.delete(e))}hydrate(e){return this.#o=!0,this.#c(z.Hydrate,()=>e)}produce(e){if(!this.#o)throw new Error("State must be hydrated using hydrate() before calling produce()");return this.#c(z.Produce,e)}#c(e,t){const n=/* @__PURE__ */Symbol("process"),[,r]=$.immer.produceWithPatches(this.#e,t);return this.#e=r.reduce((t,r)=>$.immer.applyPatches(t,[{...r,value:G(e,r,t,n,this.#n,this.#t)}]),this.#e),this.#e=F(this.#e),this.#i(),n}prune(e){this.#n.forEach((n,r)=>{const o=n.filter(t=>t.process!==e);t.isEmpty(o)?this.#n.delete(r):this.#n.set(r,o)}),this.#i()}#i(){this.#r.forEach(e=>e())}observe(e){const t=()=>e(this.#e);return this.#r.add(t),()=>this.#r.delete(t)}}const q=new V;function J(e,t){return q.annotate(e,t)}function K(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Q,X={exports:{}};const Y=/* @__PURE__ */K((Q||(Q=1,function(e){var t=Object.prototype.hasOwnProperty,n="~";function r(){}function o(e,t,n){this.fn=e,this.context=t,this.once=n||!1}function c(e,t,r,c,i){if("function"!=typeof r)throw new TypeError("The listener must be a function");var s=new o(r,c||e,i),a=n?n+t:t;return e._events[a]?e._events[a].fn?e._events[a]=[e._events[a],s]:e._events[a].push(s):(e._events[a]=s,e._eventsCount++),e}function i(e,t){0===--e._eventsCount?e._events=new r:delete e._events[t]}function s(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=/* @__PURE__ */Object.create(null),(new r).__proto__||(n=!1)),s.prototype.eventNames=function(){var e,r,o=[];if(0===this._eventsCount)return o;for(r in e=this._events)t.call(e,r)&&o.push(n?r.slice(1):r);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(e)):o},s.prototype.listeners=function(e){var t=this._events[n?n+e:e];if(!t)return[];if(t.fn)return[t.fn];for(var r=0,o=t.length,c=new Array(o);r<o;r++)c[r]=t[r].fn;return c},s.prototype.listenerCount=function(e){var t=this._events[n?n+e:e];return t?t.fn?1:t.length:0},s.prototype.emit=function(e,t,r,o,c,i){var s=n?n+e:e;if(!this._events[s])return!1;var a,u,l=this._events[s],f=arguments.length;if(l.fn){switch(l.once&&this.removeListener(e,l.fn,void 0,!0),f){case 1:return l.fn.call(l.context),!0;case 2:return l.fn.call(l.context,t),!0;case 3:return l.fn.call(l.context,t,r),!0;case 4:return l.fn.call(l.context,t,r,o),!0;case 5:return l.fn.call(l.context,t,r,o,c),!0;case 6:return l.fn.call(l.context,t,r,o,c,i),!0}for(u=1,a=new Array(f-1);u<f;u++)a[u-1]=arguments[u];l.fn.apply(l.context,a)}else{var d,p=l.length;for(u=0;u<p;u++)switch(l[u].once&&this.removeListener(e,l[u].fn,void 0,!0),f){case 1:l[u].fn.call(l[u].context);break;case 2:l[u].fn.call(l[u].context,t);break;case 3:l[u].fn.call(l[u].context,t,r);break;case 4:l[u].fn.call(l[u].context,t,r,o);break;default:if(!a)for(d=1,a=new Array(f-1);d<f;d++)a[d-1]=arguments[d];l[u].fn.apply(l[u].context,a)}}return!0},s.prototype.on=function(e,t,n){return c(this,e,t,n,!1)},s.prototype.once=function(e,t,n){return c(this,e,t,n,!0)},s.prototype.removeListener=function(e,t,r,o){var c=n?n+e:e;if(!this._events[c])return this;if(!t)return i(this,c),this;var s=this._events[c];if(s.fn)s.fn!==t||o&&!s.once||r&&s.context!==r||i(this,c);else{for(var a=0,u=[],l=s.length;a<l;a++)(s[a].fn!==t||o&&!s[a].once||r&&s[a].context!==r)&&u.push(s[a]);u.length?this._events[c]=1===u.length?u[0]:u:i(this,c)}return this},s.prototype.removeAllListeners=function(e){var t;return e?this._events[t=n?n+e:e]&&i(this,t):(this._events=new r,this._eventsCount=0),this},s.prototype.off=s.prototype.removeListener,s.prototype.addListener=s.prototype.on,s.prefixed=n,s.EventEmitter=s,e.exports=s}(X)),X.exports));class Z extends Y{cache=/* @__PURE__ */new Map;emit(e,...t){return this.cache.set(e,t[0]),super.emit(e,...t)}getCached(e){return this.cache.get(e)}}const ee=r.createContext(new Z);function te(){return r.useContext(ee)}function ne({children:e}){const t=r.useMemo(()=>new Z,[]);/* @__PURE__ */
|
|
3
|
+
return n(ee.Provider,{value:t,children:e})}const re=r.createContext(/* @__PURE__ */new Map);function oe({children:e}){const t=r.useMemo(()=>/* @__PURE__ */new Map,[]);/* @__PURE__ */
|
|
4
|
+
return n(re.Provider,{value:t,children:e})}const ce=r.createContext(/* @__PURE__ */new Set);function ie({children:e}){const t=r.useMemo(()=>/* @__PURE__ */new Set,[]);/* @__PURE__ */
|
|
5
|
+
return n(ce.Provider,{value:t,children:e})}function se({children:e}){/* @__PURE__ */
|
|
6
|
+
return n(ne,{children:/* @__PURE__ */n(oe,{children:/* @__PURE__ */n(ie,{children:e})})})}const ae=r.createContext(null);function ue(){return r.useContext(ae)}function le(e,t){return e?.get(t)??null}function fe({name:e,children:t}){const o=ue(),c=r.useMemo(()=>({name:e,emitter:new Z}),[]),i=r.useMemo(()=>{const t=new Map(o??[]);return t.set(e,c),t},[o,e,c]);/* @__PURE__ */
|
|
7
|
+
return n(ae.Provider,{value:i,children:t})}function de(e,t){const r=`Scoped${t.displayName||t.name||"Component"}`;return{[r]:r=>/* @__PURE__ */n(fe,{name:e,children:/* @__PURE__ */n(t,{...r})})}[r]}function pe(e){return(t,n)=>{t.actions.produce(t=>{t.model[e]=n})}}function he(){const[,e]=r.useReducer(e=>e+1,0);return e}const me=r.createContext(/* @__PURE__ */new Map);function ye({action:t,renderer:n}){const o=te(),c=r.useContext(me),i=he(),s=r.useMemo(()=>{const e=c.get(t);if(e)return e;const n={state:new V,listeners:/* @__PURE__ */new Set};return c.set(t,n),n},[t,c]);r.useLayoutEffect(()=>{function e(e){s.state.hydrate({value:e}),s.listeners.forEach(e=>e())}return s.listeners.add(i),o.on(t,e),()=>{s.listeners.delete(i),o.off(t,e)}},[t,o,s]);const a=s.state.model?.value;return e.isNullable(a)?null:n(a,s.state.inspect.value)}function be(...n){const o=e.isUndefined(n[0])||e.isFunction(n[0])?{}:n[0],i=e.isFunction(n[0])?n[0]:n[1]??(()=>({})),s=te(),a=ue(),f=c(_),p=r.useContext(ce),h=r.useContext(re),m=he(),y=r.useRef(!1),b=r.useRef(null),v=r.useRef(new V);y.current||(y.current=!0,b.current=v.current.hydrate(o));const[g,w]=r.useState(()=>v.current.model),j=function(e){const t=r.useRef(e);return r.useLayoutEffect(()=>{t.current=e},[e]),r.useMemo(()=>{return n=t,Object.keys(e).reduce((e,t)=>(Object.defineProperty(e,t,{get:()=>n.current[t],enumerable:!0}),e),{});var n},[e])}(i()),A=r.useMemo(()=>new Y,[]),R=r.useRef({handlers:/* @__PURE__ */new Map});R.current.handlers=/* @__PURE__ */new Map;const N=function(){const e=r.useRef(/* @__PURE__ */new Set),t=r.useRef(/* @__PURE__ */new Set);return r.useMemo(()=>({broadcast:e.current,multicast:t.current}),[])}(),U=r.useRef(d.Mounting),z=function(){const e=r.useRef({}),t=r.useRef(/* @__PURE__ */new Map),n=r.useRef(/* @__PURE__ */new Map);return r.useMemo(()=>({refs:e,pending:t,emitted:n}),[])}(),L=r.useRef(/* @__PURE__ */new Set),T=r.useRef(0),$=r.useCallback((e,t,n)=>{const r=new AbortController,o={controller:r,action:e,payload:t};return p.add(o),L.current.add(o),{model:v.current.model,get phase(){return U.current},task:o,data:j,tasks:p,nodes:z.refs.current,actions:{produce(e){if(r.signal.aborted)return;const t=v.current.produce(t=>e({model:t,inspect:v.current.inspect}));w(v.current.model),n.processes.add(t),b.current&&(n.processes.add(b.current),b.current=null)},dispatch(e,t,n){if(r.signal.aborted)return;const o=x(e),c=E(e)?e.channel:void 0;if(O(e)&&n?.scope){const e=le(a,n.scope);return void(e&&e.emitter.emit(o,t,c))}(S(e)?s:A).emit(o,t,c)},annotate:(e,t)=>v.current.annotate(e,t),async cacheable(e,t,n){if(r.signal.aborted)return{data:null};const o=C(e),c=h.get(o);if(c&&Date.now()<c.expiry)return{data:c.value};const i=function(e){return null!=e&&"object"==typeof e&&"TAG"in e?0===e.TAG?{ok:!0,value:e._0}:{ok:!1}:null==e?{ok:!1}:{ok:!0,value:e}}(await n());return i.ok?(h.set(o,{value:i.value,expiry:Date.now()+t}),{data:i.value}):{data:null}},invalidate(e){h.delete(C(e))},async read(e,t){if(r.signal.aborted)return null;const n=x(e),o=O(e)&&t?.scope?le(a,t.scope)?.emitter??null:s;if(!o)return null;if(void 0===o.getCached(n))return null;const c=P(e),i="unknown"!==c?c[0].toLowerCase()+c.slice(1):null;if(i){const e=v.current.inspect[i];e?.pending?.()&&await new Promise((t,n)=>{if(r.signal.aborted)return void n(r.signal.reason);const o=()=>n(r.signal.reason);r.signal.addEventListener("abort",o,{once:!0}),e.settled().then(()=>{r.signal.removeEventListener("abort",o),t()})})}return o.getCached(n)??null},peek(e,t){if(r.signal.aborted)return null;const n=x(e),o=O(e)&&t?.scope?le(a,t.scope)?.emitter??null:s;return o?o.getCached(n)??null:null}}}},[g]);r.useLayoutEffect(()=>{function t(t,n,r){return async function(o,c){const i=r();if(e.isNotNullable(c)&&e.isNotNullable(i)&&!function(e,t){for(const n of Object.keys(e))if(t[n]!==e[n])return!1;return!0}(c,i))return;const s={processes:/* @__PURE__ */new Set},a=Promise.withResolvers(),u=$(t,o,s);try{await n(u,o)}catch(d){const e=R.current.handlers.has(l.Error),n={reason:M(d),error:k(d),action:P(t),handled:e,tasks:p};f?.(n),e&&A.emit(l.Error,n)}finally{for(const e of p)if(e===u.task){p.delete(e),L.current.delete(e);break}s.processes.forEach(e=>v.current.prune(e)),s.processes.size>0&&m(),a.resolve()}}}T.current++;const n=/* @__PURE__ */new Set;return R.current.handlers.forEach((e,r)=>{for(const{getChannel:o,handler:c}of e){const e=t(r,c,o);if(O(r)){if(a)for(const t of a.values()){const o=t.emitter;o.on(r,e),n.add(()=>o.off(r,e))}A.on(r,e),N.multicast.add(r),n.add(()=>A.off(r,e))}else S(r)?(s.on(r,e),A.on(r,e),N.broadcast.add(r),n.add(()=>{s.off(r,e),A.off(r,e)})):(A.on(r,e),n.add(()=>A.off(r,e)))}}),()=>{const e=++T.current,t=new Set(n);queueMicrotask(()=>{if(T.current===e){for(const e of L.current)e.controller.abort(),p.delete(e);L.current.clear(),U.current=d.Unmounting,A.emit(l.Unmount),U.current=d.Unmounted;for(const e of t)e()}else for(const e of t)e()})}},[A]),r.useLayoutEffect(()=>{for(const[e,t]of z.pending.current)z.emitted.current.get(e)!==t&&(z.emitted.current.set(e,t),A.emit(u.Node,t,{Name:e}));z.pending.current.clear()}),function({unicast:n,broadcast:o,dispatchers:c,scope:i,phase:s,data:a}){const u=r.useRef(null);r.useLayoutEffect(()=>{s.current===d.Mounting&&(n.emit(l.Mount),c.broadcast.forEach(t=>{const r=o.getCached(t);e.isNullable(r)||n.emit(t,r)}),i&&c.multicast.forEach(t=>{for(const r of i.values()){const o=r.emitter.getCached(t);e.isNullable(o)||n.emit(t,o)}}),s.current=d.Mounted)},[]),r.useLayoutEffect(()=>{if(e.isNotNullable(u.current)){const e=function(e,t){return Object.keys(t).reduce((n,r)=>e[r]!==t[r]?{...n,[r]:t[r]}:n,{})}(u.current,a);t.isNotEmpty(Object.keys(e))&&n.emit(l.Update,e)}u.current=a},[a,n])}({unicast:A,broadcast:s,dispatchers:N,scope:a,phase:U,data:i()});const B=r.useMemo(()=>[g,{dispatch(e,t,n){const r=x(e),o=E(e)?e.channel:void 0;if(O(e)&&n?.scope){const e=le(a,n.scope);return void(e&&e.emitter.emit(r,t,o))}(S(e)?s:A).emit(r,t,o)},get inspect(){return v.current.inspect},get nodes(){return z.refs.current},node(e,t){z.refs.current[e]=t,z.pending.current.set(e,t)},stream:(e,t)=>r.createElement(ye,{action:x(e),renderer:t})}],[g,A]);return B.useAction=(e,t)=>{!function(e,t,n){const o=r.useRef(n);r.useLayoutEffect(()=>{o.current=n});const c=r.useRef(t);r.useLayoutEffect(()=>{c.current=t});const i=r.useCallback(async(e,t)=>{const n=o.current;if("GeneratorFunction"===n.constructor.name||"AsyncGeneratorFunction"===n.constructor.name){const r=n(e,t);for await(const e of r);}else await n(e,t)},[]),s=r.useCallback(()=>E(c.current)?c.current.channel:void 0,[]),a=x(t),u=e.current.handlers.get(a)??/* @__PURE__ */new Set;0===u.size&&e.current.handlers.set(a,u),u.add({getChannel:s,handler:i})}(R,e,t)},B}export{j as Action,se as Boundary,f as Distribution,A as Entry,R as Error,l as Lifecycle,U as Op,U as Operation,p as Reason,fe as Scope,V as State,pe as With,J as annotate,be as useActions,g as utils,de as withScope};
|
package/dist/chizu.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var global,factory;global=this,factory=function(e,t,n,r,o){"use strict";function c(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const n in e)if("default"!==n){const r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:()=>e[n]})}return t.default=e,Object.freeze(t)}const i=c(r);class s{static Payload=Symbol("chizu.brand/Payload");static Broadcast=Symbol("chizu.brand/Broadcast");static Multicast=Symbol("chizu.brand/Multicast");static Action=Symbol("chizu.brand/Action");static Channel=Symbol("chizu.brand/Channel");static Node=Symbol("chizu.action.lifecycle/Node");static Cache=Symbol("chizu.brand/Cache")}class a{static Mount=Symbol("chizu.action.lifecycle/Mount");static Unmount=Symbol("chizu.action.lifecycle/Unmount");static Error=Symbol("chizu.action.lifecycle/Error");static Update=Symbol("chizu.action.lifecycle/Update");static Node=(()=>{const e=s.Node,t=function(t){return{[s.Action]:e,[s.Payload]:void 0,[s.Channel]:t,channel:t}};return Object.defineProperty(t,s.Action,{value:e,enumerable:!1}),Object.defineProperty(t,s.Payload,{value:void 0,enumerable:!1}),t})()}var u=(e=>(e.Unicast="unicast",e.Broadcast="broadcast",e.Multicast="multicast",e))(u||{}),l=(e=>(e.Mounting="mounting",e.Mounted="mounted",e.Unmounting="unmounting",e.Unmounted="unmounted",e))(l||{}),f=(e=>(e[e.Timedout=0]="Timedout",e[e.Supplanted=1]="Supplanted",e[e.Disallowed=2]="Disallowed",e[e.Errored=3]="Errored",e[e.Unmounted=4]="Unmounted",e))(f||{});class d extends Error{name="AbortError";constructor(e="Aborted"){super(e)}}const h={actionPrefix:"chizu.action/",broadcastActionPrefix:"chizu.action/broadcast/",multicastActionPrefix:"chizu.action/multicast/",channelPrefix:"chizu.channel/",cachePrefix:"chizu.cache/"};function p(e,t){return new Promise((n,r)=>{if(t?.aborted)return void r(new d);const o=setTimeout(n,e);t?.addEventListener("abort",()=>{clearTimeout(o),r(new d)},{once:!0})})}function m(e){return e?Boolean(e&&"symbol"!=typeof e):Symbol(`pk.${Date.now()}.${crypto.randomUUID()}`)}const b=Object.freeze(Object.defineProperty({__proto__:null,config:h,pk:m,sleep:p,"ζ":p,"κ":m},Symbol.toStringTag,{value:"Module"})),y=e=>"symbol"==typeof e;function v(e){return t.G.isString(e)||y(e)?e:(t.G.isObject(e)||t.G.isFunction(e))&&s.Action in e?e[s.Action]:e}function g(e){if(t.G.isString(e))return e.startsWith(h.broadcastActionPrefix);if(y(e))return e.description?.startsWith(h.broadcastActionPrefix)??!1;if(t.G.isObject(e)||t.G.isFunction(e)){if(s.Broadcast in e&&e[s.Broadcast])return!0;if(s.Action in e){const t=e[s.Action];return t.description?.startsWith(h.broadcastActionPrefix)??!1}}return!1}function w(e){const n=v(e),r=t.G.isString(n)?n:n.description??"";return r.startsWith(h.actionPrefix)&&r.slice(r.lastIndexOf("/")+1)||"unknown"}function x(e){return t.G.isObject(e)&&s.Channel in e&&"channel"in e}function j(e){if(t.G.isString(e))return e.startsWith(h.multicastActionPrefix);if(y(e))return e.description?.startsWith(h.multicastActionPrefix)??!1;if(t.G.isObject(e)||t.G.isFunction(e)){if(s.Multicast in e&&e[s.Multicast])return!0;if(s.Action in e){const t=e[s.Action];return t.description?.startsWith(h.multicastActionPrefix)??!1}}return!1}function S(e){const t=function(e){return e[s.Cache]}(e),n=function(e){return"channel"in e}(e)&&(r=e.channel)?[...Object.keys(r)].toSorted().map(e=>`${e}=${String(r[e])}`).join("&"):"";var r;return`${String(t)}:${n}`}function A(e){if(e instanceof Error){if("TimeoutError"===e.name)return f.Timedout;if("AbortError"===e.name)return f.Supplanted}return f.Errored}function P(e){return e instanceof Error?e:new Error(String(e))}const O=r.createContext(void 0);let E=(e=21)=>{let t="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)t+="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"[63&n[e]];return t};var M=(e=>(e[e.Add=1]="Add",e[e.Remove=2]="Remove",e[e.Update=4]="Update",e[e.Move=8]="Move",e[e.Replace=16]="Replace",e[e.Sort=32]="Sort",e[e.Create=64]="Create",e[e.Fetch=128]="Fetch",e[e.Clone=256]="Clone",e[e.Archive=512]="Archive",e[e.Restore=1024]="Restore",e[e.Merge=2048]="Merge",e[e.Reorder=4096]="Reorder",e[e.Sync=8192]="Sync",e[e.Publish=16384]="Publish",e[e.Link=32768]="Link",e[e.Unlink=65536]="Unlink",e[e.Lock=131072]="Lock",e[e.Unlock=262144]="Unlock",e[e.Import=524288]="Import",e[e.Export=1048576]="Export",e[e.Transfer=2097152]="Transfer",e))(M||{}),C=(e=>(e[e.Produce=0]="Produce",e[e.Hydrate=1]="Hydrate",e))(C||{}),k=(e=>(e.Property="property",e.Process="process",e.Value="value",e.Operation="operation",e))(k||{});class G{[o.immerable]=!0;static keys=new Set(Object.values(k));property=null;process=null;value;operation;constructor(e,t){this.value=e,this.operation=t}assign(e,t){const n=new G(this.value,this.operation);return n.property=e,n.process=t,n}}class _{static immer=(()=>{o.enablePatches();const e=new o.Immer;return e.setAutoFreeze(!1),e})();static tag="κ";static id=E}function R(e,t){const n="string"==typeof t?""===t?[]:t.split("."):t;let r=e;for(const o of n){if(null==r)return;r=r[o]}return r}function N(e){if(t.G.isNullable(e)||L(e))return e;if(t.G.isArray(e))return e.map(e=>N(e));if(t.G.isObject(e)&&U(e)){const t=Object.entries(e).map(([e,t])=>[e,N(t)]);return{...Object.fromEntries(t),[_.tag]:e[_.tag]??_.id()}}return e}function z(e){if(Array.isArray(e))return e.filter(e=>_.tag in e).map(e=>e[_.tag]??"").join(",");const t=e[_.tag];if(t)return t;try{return JSON.stringify(e)}catch{return`[unserializable:${typeof e}]`}}function U(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}function L(e){return t.G.isNullable(e)||t.G.isString(e)||t.G.isNumber(e)||t.G.isBoolean(e)||"symbol"==typeof e||"bigint"==typeof e}function T(e,n,r,o,c,i){return function s(a,u=n.path){if(a instanceof G){const n=R(r,u.join("."));if(Object.entries(a).filter(([e,t])=>!G.keys.has(e)&&t instanceof G).forEach(([e,t])=>s(t,u.concat(e))),L(a.value)){if(e===C.Hydrate)return a.value;const s=u.slice(0,-1),l=s.length>0?R(r,s.join(".")):r;return t.G.isNullable(l)||$(l,a,u.at(-1),o,c,i),n??a.value}if(e===C.Hydrate){const e=N(s(a.value,u));return $(e,a,null,o,c,i),e}const l=n??N(a.value);return $(l,a,null,o,c,i),t.G.isNullable(n)?l:(s(a.value,u),n)}if(t.G.isArray(a))return a.map((e,t)=>s(e,u.concat(t)));if(t.G.isObject(a)&&!U(a))return a;if(t.G.isObject(a)){const t=Object.entries(a).map(([e,t])=>[e,s(t,u.concat(e))]),n=Object.fromEntries(t);if(e===C.Hydrate){const e=N(n);return Object.entries(a).forEach(([t,n])=>{n instanceof G&&L(n.value)&&$(e,n,t,o,c,i)}),e}return n}return a}(n.value)}function $(e,t,n,r,o,c){const i=c(e),s=o.get(i)??[];o.set(i,[t.assign(n,r),...s])}class B{#e={};#t;#n=new Map;#r=new Set;#o=!1;constructor(e=z){this.#t=e}static pk(){return E()}static"κ"=B.pk;annotate(e,t){return new G(t,e)}"δ"=this.annotate;get model(){return this.#e}get inspect(){return function(e,n,r,o,c){function i(o){const c=o.at(-1),i=R(e(),o),s=o.slice(0,-1),a=t.A.isNotEmpty(s)?R(e(),s):e();return[...t.G.isObject(i)||t.G.isArray(i)?n.get(r(i))?.filter(e=>t.G.isNullable(e.property))??[]:[],...t.G.isObject(a)?n.get(r(a))?.filter(e=>e.property===c)??[]:[]]}return function n(r){return new Proxy(()=>{},{get:(s,a)=>"pending"===a?()=>!t.A.isEmpty(i(r)):"remaining"===a?()=>t.A.length(i(r)):"box"===a?()=>({value:R(e(),r),inspect:n(r)}):"is"===a?e=>i(r).some(t=>0!==(t.operation&e)):"draft"===a?()=>t.A.head(i(r))?.value??R(e(),r):"settled"===a?()=>new Promise(n=>{if(t.A.isEmpty(i(r)))return n(R(e(),r));const s=()=>{t.A.isEmpty(i(r))&&(c(s),n(R(e(),r)))};o(s)}):n([...r,String(a)])})}([])}(()=>this.#e,this.#n,this.#t,e=>this.#r.add(e),e=>this.#r.delete(e))}hydrate(e){return this.#o=!0,this.#c(C.Hydrate,()=>e)}produce(e){if(!this.#o)throw new Error("State must be hydrated using hydrate() before calling produce()");return this.#c(C.Produce,e)}#c(e,t){const n=Symbol("process"),[,r]=_.immer.produceWithPatches(this.#e,t);return this.#e=r.reduce((t,r)=>_.immer.applyPatches(t,[{...r,value:T(e,r,t,n,this.#n,this.#t)}]),this.#e),this.#e=N(this.#e),this.#i(),n}prune(e){this.#n.forEach((n,r)=>{const o=n.filter(t=>t.process!==e);t.A.isEmpty(o)?this.#n.delete(r):this.#n.set(r,o)}),this.#i()}#i(){this.#r.forEach(e=>e())}observe(e){const t=()=>e(this.#e);return this.#r.add(t),()=>this.#r.delete(t)}}const F=new B;function W(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var D,H={exports:{}},I=(D||(D=1,function(e){var t=Object.prototype.hasOwnProperty,n="~";function r(){}function o(e,t,n){this.fn=e,this.context=t,this.once=n||!1}function c(e,t,r,c,i){if("function"!=typeof r)throw new TypeError("The listener must be a function");var s=new o(r,c||e,i),a=n?n+t:t;return e._events[a]?e._events[a].fn?e._events[a]=[e._events[a],s]:e._events[a].push(s):(e._events[a]=s,e._eventsCount++),e}function i(e,t){0===--e._eventsCount?e._events=new r:delete e._events[t]}function s(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=Object.create(null),(new r).__proto__||(n=!1)),s.prototype.eventNames=function(){var e,r,o=[];if(0===this._eventsCount)return o;for(r in e=this._events)t.call(e,r)&&o.push(n?r.slice(1):r);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(e)):o},s.prototype.listeners=function(e){var t=this._events[n?n+e:e];if(!t)return[];if(t.fn)return[t.fn];for(var r=0,o=t.length,c=new Array(o);r<o;r++)c[r]=t[r].fn;return c},s.prototype.listenerCount=function(e){var t=this._events[n?n+e:e];return t?t.fn?1:t.length:0},s.prototype.emit=function(e,t,r,o,c,i){var s=n?n+e:e;if(!this._events[s])return!1;var a,u,l=this._events[s],f=arguments.length;if(l.fn){switch(l.once&&this.removeListener(e,l.fn,void 0,!0),f){case 1:return l.fn.call(l.context),!0;case 2:return l.fn.call(l.context,t),!0;case 3:return l.fn.call(l.context,t,r),!0;case 4:return l.fn.call(l.context,t,r,o),!0;case 5:return l.fn.call(l.context,t,r,o,c),!0;case 6:return l.fn.call(l.context,t,r,o,c,i),!0}for(u=1,a=new Array(f-1);u<f;u++)a[u-1]=arguments[u];l.fn.apply(l.context,a)}else{var d,h=l.length;for(u=0;u<h;u++)switch(l[u].once&&this.removeListener(e,l[u].fn,void 0,!0),f){case 1:l[u].fn.call(l[u].context);break;case 2:l[u].fn.call(l[u].context,t);break;case 3:l[u].fn.call(l[u].context,t,r);break;case 4:l[u].fn.call(l[u].context,t,r,o);break;default:if(!a)for(d=1,a=new Array(f-1);d<f;d++)a[d-1]=arguments[d];l[u].fn.apply(l[u].context,a)}}return!0},s.prototype.on=function(e,t,n){return c(this,e,t,n,!1)},s.prototype.once=function(e,t,n){return c(this,e,t,n,!0)},s.prototype.removeListener=function(e,t,r,o){var c=n?n+e:e;if(!this._events[c])return this;if(!t)return i(this,c),this;var s=this._events[c];if(s.fn)s.fn!==t||o&&!s.once||r&&s.context!==r||i(this,c);else{for(var a=0,u=[],l=s.length;a<l;a++)(s[a].fn!==t||o&&!s[a].once||r&&s[a].context!==r)&&u.push(s[a]);u.length?this._events[c]=1===u.length?u[0]:u:i(this,c)}return this},s.prototype.removeAllListeners=function(e){var t;return e?this._events[t=n?n+e:e]&&i(this,t):(this._events=new r,this._eventsCount=0),this},s.prototype.off=s.prototype.removeListener,s.prototype.addListener=s.prototype.on,s.prefixed=n,s.EventEmitter=s,e.exports=s}(H)),H.exports);const q=W(I);class V extends q{cache=new Map;emit(e,...t){return this.cache.set(e,t[0]),super.emit(e,...t)}getCached(e){return this.cache.get(e)}}const J=i.createContext(new V);function K({children:e}){const t=i.useMemo(()=>new V,[]);return n.jsx(J.Provider,{value:t,children:e})}const Q=i.createContext(new Map);function X({children:e}){const t=i.useMemo(()=>new Map,[]);return n.jsx(Q.Provider,{value:t,children:e})}const Y=i.createContext(new Set);function Z({children:e}){const t=i.useMemo(()=>new Set,[]);return n.jsx(Y.Provider,{value:t,children:e})}const ee=i.createContext(null);function te(){return i.useContext(ee)}function ne(e,t){return e?.get(t)??null}function re({name:e,children:t}){const r=te(),o=i.useMemo(()=>({name:e,emitter:new V}),[]),c=i.useMemo(()=>{const t=new Map(r??[]);return t.set(e,o),t},[r,e,o]);return n.jsx(ee.Provider,{value:c,children:t})}function oe(e,t,n){const r=i.useRef(n);i.useLayoutEffect(()=>{r.current=n});const o=i.useRef(t);i.useLayoutEffect(()=>{o.current=t});const c=i.useCallback(async(e,t)=>{const n=r.current;if("GeneratorFunction"===n.constructor.name||"AsyncGeneratorFunction"===n.constructor.name){const r=n(e,t);for await(const e of r);}else await n(e,t)},[]),s=i.useCallback(()=>x(o.current)?o.current.channel:void 0,[]),a=v(t),u=e.current.handlers.get(a)??new Set;0===u.size&&e.current.handlers.set(a,u),u.add({getChannel:s,handler:c})}e.Action=(e,t=u.Unicast)=>{const n=t===u.Broadcast?Symbol(`${h.broadcastActionPrefix}${e}`):t===u.Multicast?Symbol(`${h.multicastActionPrefix}${e}`):Symbol(`${h.actionPrefix}${e}`),r=function(e){return{[s.Action]:n,[s.Payload]:void 0,[s.Channel]:e,channel:e}};return Object.defineProperty(r,s.Action,{value:n,enumerable:!1}),Object.defineProperty(r,s.Payload,{value:void 0,enumerable:!1}),t===u.Broadcast&&Object.defineProperty(r,s.Broadcast,{value:!0,enumerable:!1}),t===u.Multicast&&Object.defineProperty(r,s.Multicast,{value:!0,enumerable:!1}),r},e.Boundary=function({children:e}){return n.jsx(K,{children:n.jsx(X,{children:n.jsx(Z,{children:e})})})},e.Distribution=u,e.Entry=function(){const e=Symbol("chizu.cache/Entry"),t=function(t){return{[s.Cache]:e,channel:t}};return Object.defineProperty(t,s.Cache,{value:e,enumerable:!1}),t},e.Error=function({handler:e,children:t}){return n.jsx(O.Provider,{value:e,children:t})},e.Lifecycle=a,e.Op=M,e.Operation=M,e.Reason=f,e.Scope=re,e.State=B,e.With=function(e){return(t,n)=>{t.actions.produce(t=>{t.model[e]=n})}},e.annotate=function(e,t){return F.annotate(e,t)},e.useActions=function(...e){const n=t.G.isUndefined(e[0])||t.G.isFunction(e[0])?{}:e[0],o=t.G.isFunction(e[0])?e[0]:e[1]??(()=>({})),c=i.useContext(J),u=te(),f=r.useContext(O),d=i.useContext(Y),h=i.useContext(Q),p=function(){const[,e]=i.useReducer(e=>e+1,0);return e}(),m=i.useRef(!1),b=i.useRef(null),y=i.useRef(new B);m.current||(m.current=!0,b.current=y.current.hydrate(n));const[E,M]=i.useState(()=>y.current.model),C=function(e){const t=i.useRef(e);return i.useLayoutEffect(()=>{t.current=e},[e]),i.useMemo(()=>{return n=t,Object.keys(e).reduce((e,t)=>(Object.defineProperty(e,t,{get:()=>n.current[t],enumerable:!0}),e),{});var n},[e])}(o()),k=i.useMemo(()=>new q,[]),G=i.useRef({handlers:new Map});G.current.handlers=new Map;const _=function(){const e=i.useRef(new Set),t=i.useRef(new Set);return i.useMemo(()=>({broadcast:e.current,multicast:t.current}),[])}(),R=i.useRef(l.Mounting),N=function(){const e=i.useRef({}),t=i.useRef(new Map),n=i.useRef(new Map);return i.useMemo(()=>({refs:e,pending:t,emitted:n}),[])}(),z=i.useRef(new Set),U=i.useRef(0),L=i.useCallback((e,t,n)=>{const r=new AbortController,o={controller:r,action:e,payload:t};return d.add(o),z.current.add(o),{model:y.current.model,get phase(){return R.current},task:o,data:C,tasks:d,nodes:N.refs.current,actions:{produce(e){if(r.signal.aborted)return;const t=y.current.produce(t=>e({model:t,inspect:y.current.inspect}));M(y.current.model),n.processes.add(t),b.current&&(n.processes.add(b.current),b.current=null)},dispatch(e,t,n){if(r.signal.aborted)return;const o=v(e),i=x(e)?e.channel:void 0;if(j(e)&&n?.scope){const e=ne(u,n.scope);return void(e&&e.emitter.emit(o,t,i))}(g(e)?c:k).emit(o,t,i)},annotate:(e,t)=>y.current.annotate(e,t),async cacheable(e,t,n){if(r.signal.aborted)return{data:null};const o=S(e),c=h.get(o);if(c&&Date.now()<c.expiry)return{data:c.value};const i=function(e){return null!=e&&"object"==typeof e&&"TAG"in e?0===e.TAG?{ok:!0,value:e._0}:{ok:!1}:null==e?{ok:!1}:{ok:!0,value:e}}(await n());return i.ok?(h.set(o,{value:i.value,expiry:Date.now()+t}),{data:i.value}):{data:null}},invalidate(e){h.delete(S(e))},async read(e,t){if(r.signal.aborted)return null;const n=v(e),o=j(e)&&t?.scope?ne(u,t.scope)?.emitter??null:c;if(!o)return null;if(void 0===o.getCached(n))return null;const i=w(e),s="unknown"!==i?i[0].toLowerCase()+i.slice(1):null;if(s){const e=y.current.inspect[s];e?.pending?.()&&await new Promise((t,n)=>{if(r.signal.aborted)return void n(r.signal.reason);const o=()=>n(r.signal.reason);r.signal.addEventListener("abort",o,{once:!0}),e.settled().then(()=>{r.signal.removeEventListener("abort",o),t()})})}return o.getCached(n)??null}}}},[E]);i.useLayoutEffect(()=>{function e(e,n,r){return async function(o,c){const i=r();if(t.G.isNotNullable(c)&&t.G.isNotNullable(i)&&!function(e,t){for(const n of Object.keys(e))if(t[n]!==e[n])return!1;return!0}(c,i))return;const s={processes:new Set},u=Promise.withResolvers(),l=L(e,o,s);try{await n(l,o)}catch(h){const t=G.current.handlers.has(a.Error),n={reason:A(h),error:P(h),action:w(e),handled:t,tasks:d};f?.(n),t&&k.emit(a.Error,n)}finally{for(const e of d)if(e===l.task){d.delete(e),z.current.delete(e);break}s.processes.forEach(e=>y.current.prune(e)),s.processes.size>0&&p(),u.resolve()}}}U.current++;const n=new Set;return G.current.handlers.forEach((t,r)=>{for(const{getChannel:o,handler:i}of t){const t=e(r,i,o);if(j(r)){if(u)for(const e of u.values()){const o=e.emitter;o.on(r,t),n.add(()=>o.off(r,t))}k.on(r,t),_.multicast.add(r),n.add(()=>k.off(r,t))}else g(r)?(c.on(r,t),k.on(r,t),_.broadcast.add(r),n.add(()=>{c.off(r,t),k.off(r,t)})):(k.on(r,t),n.add(()=>k.off(r,t)))}}),()=>{const e=++U.current,t=new Set(n);queueMicrotask(()=>{if(U.current===e){for(const e of z.current)e.controller.abort(),d.delete(e);z.current.clear(),R.current=l.Unmounting,k.emit(a.Unmount),R.current=l.Unmounted;for(const e of t)e()}else for(const e of t)e()})}},[k]),i.useLayoutEffect(()=>{for(const[e,t]of N.pending.current)N.emitted.current.get(e)!==t&&(N.emitted.current.set(e,t),k.emit(s.Node,t,{Name:e}));N.pending.current.clear()}),function({unicast:e,broadcast:n,broadcastActions:r,phase:o,data:c}){const s=i.useRef(null);i.useLayoutEffect(()=>{o.current===l.Mounting&&(e.emit(a.Mount),r.forEach(r=>{const o=n.getCached(r);t.G.isNullable(o)||e.emit(r,o)}),o.current=l.Mounted)},[]),i.useLayoutEffect(()=>{if(t.G.isNotNullable(s.current)){const n=function(e,t){return Object.keys(t).reduce((n,r)=>e[r]!==t[r]?{...n,[r]:t[r]}:n,{})}(s.current,c);t.A.isNotEmpty(Object.keys(n))&&e.emit(a.Update,n)}s.current=c},[c,e])}({unicast:k,broadcast:c,broadcastActions:_.broadcast,phase:R,data:o()});const T=i.useMemo(()=>[E,{dispatch(e,t,n){const r=v(e),o=x(e)?e.channel:void 0;if(j(e)&&n?.scope){const e=ne(u,n.scope);return void(e&&e.emitter.emit(r,t,o))}(g(e)?c:k).emit(r,t,o)},get inspect(){return y.current.inspect},get nodes(){return N.refs.current},node(e,t){N.refs.current[e]=t,N.pending.current.set(e,t)}}],[E,k]);T.useAction=(e,t)=>{oe(G,e,t)};const $=T,F=i.useRef({}),W=e=>{e.derive=(e,n,r)=>{if(t.G.isNullable(r))F.current[e]=n($[0]);else if(r){e in F.current||(F.current[e]=null);const t=r;oe(G,n,(n,r)=>{F.current[e]=t(r),p()})}const o=[{...$[0],...F.current},$[1]];return o.useAction=$.useAction,W(o),o}};return W($),$},e.utils=b,e.withScope=function(e,t){const r=`Scoped${t.displayName||t.name||"Component"}`;return{[r]:r=>n.jsx(re,{name:e,children:n.jsx(t,{...r})})}[r]},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})},"object"==typeof exports&&"undefined"!=typeof module?factory(exports,require("@mobily/ts-belt"),require("react/jsx-runtime"),require("react"),require("immer")):"function"==typeof define&&define.amd?define(["exports","@mobily/ts-belt","react/jsx-runtime","react","immer"],factory):factory((global="undefined"!=typeof globalThis?globalThis:global||self).Chizu={},global.TsBelt,global.jsxRuntime,global.React,global.Immer);
|
|
1
|
+
var global,factory;global=this,factory=function(e,t,n,r,o){"use strict";function c(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const n in e)if("default"!==n){const r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:()=>e[n]})}return t.default=e,Object.freeze(t)}const i=c(r);class s{static Payload=Symbol("chizu.brand/Payload");static Broadcast=Symbol("chizu.brand/Broadcast");static Multicast=Symbol("chizu.brand/Multicast");static Action=Symbol("chizu.brand/Action");static Channel=Symbol("chizu.brand/Channel");static Node=Symbol("chizu.action.lifecycle/Node");static Cache=Symbol("chizu.brand/Cache")}class a{static Mount=Symbol("chizu.action.lifecycle/Mount");static Unmount=Symbol("chizu.action.lifecycle/Unmount");static Error=Symbol("chizu.action.lifecycle/Error");static Update=Symbol("chizu.action.lifecycle/Update");static Node=(()=>{const e=s.Node,t=function(t){return{[s.Action]:e,[s.Payload]:void 0,[s.Channel]:t,channel:t}};return Object.defineProperty(t,s.Action,{value:e,enumerable:!1}),Object.defineProperty(t,s.Payload,{value:void 0,enumerable:!1}),t})()}var u=(e=>(e.Unicast="unicast",e.Broadcast="broadcast",e.Multicast="multicast",e))(u||{}),l=(e=>(e.Mounting="mounting",e.Mounted="mounted",e.Unmounting="unmounting",e.Unmounted="unmounted",e))(l||{}),f=(e=>(e[e.Timedout=0]="Timedout",e[e.Supplanted=1]="Supplanted",e[e.Disallowed=2]="Disallowed",e[e.Errored=3]="Errored",e[e.Unmounted=4]="Unmounted",e))(f||{});class d extends Error{name="AbortError";constructor(e="Aborted"){super(e)}}const p={actionPrefix:"chizu.action/",broadcastActionPrefix:"chizu.action/broadcast/",multicastActionPrefix:"chizu.action/multicast/",channelPrefix:"chizu.channel/",cachePrefix:"chizu.cache/"};function h(e,t){return new Promise((n,r)=>{if(t?.aborted)return void r(new d);const o=setTimeout(n,e);t?.addEventListener("abort",()=>{clearTimeout(o),r(new d)},{once:!0})})}async function m(e,t,n){if(t?.aborted)throw new d;for(;;){if(await n())return;await h(e,t)}}function y(e){return e?Boolean(e&&"symbol"!=typeof e):Symbol(`pk.${Date.now()}.${crypto.randomUUID()}`)}const b=Object.freeze(Object.defineProperty({__proto__:null,config:p,pk:y,poll:m,sleep:h,"ζ":h,"κ":y,"π":m},Symbol.toStringTag,{value:"Module"})),v=e=>"symbol"==typeof e;function g(e){return t.G.isString(e)||v(e)?e:(t.G.isObject(e)||t.G.isFunction(e))&&s.Action in e?e[s.Action]:e}function w(e){if(t.G.isString(e))return e.startsWith(p.broadcastActionPrefix);if(v(e))return e.description?.startsWith(p.broadcastActionPrefix)??!1;if(t.G.isObject(e)||t.G.isFunction(e)){if(s.Broadcast in e&&e[s.Broadcast])return!0;if(s.Action in e){const t=e[s.Action];return t.description?.startsWith(p.broadcastActionPrefix)??!1}}return!1}function x(e){const n=g(e),r=t.G.isString(n)?n:n.description??"";return r.startsWith(p.actionPrefix)&&r.slice(r.lastIndexOf("/")+1)||"unknown"}function j(e){return t.G.isObject(e)&&s.Channel in e&&"channel"in e}function S(e){if(t.G.isString(e))return e.startsWith(p.multicastActionPrefix);if(v(e))return e.description?.startsWith(p.multicastActionPrefix)??!1;if(t.G.isObject(e)||t.G.isFunction(e)){if(s.Multicast in e&&e[s.Multicast])return!0;if(s.Action in e){const t=e[s.Action];return t.description?.startsWith(p.multicastActionPrefix)??!1}}return!1}function P(e){const t=function(e){return e[s.Cache]}(e),n=function(e){return"channel"in e}(e)&&(r=e.channel)?[...Object.keys(r)].toSorted().map(e=>`${e}=${String(r[e])}`).join("&"):"";var r;return`${String(t)}:${n}`}function A(e){if(e instanceof Error){if("TimeoutError"===e.name)return f.Timedout;if("AbortError"===e.name)return f.Supplanted}return f.Errored}function O(e){return e instanceof Error?e:new Error(String(e))}const E=r.createContext(void 0);let C=(e=21)=>{let t="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)t+="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"[63&n[e]];return t};var M=(e=>(e[e.Add=1]="Add",e[e.Remove=2]="Remove",e[e.Update=4]="Update",e[e.Move=8]="Move",e[e.Replace=16]="Replace",e[e.Sort=32]="Sort",e[e.Create=64]="Create",e[e.Fetch=128]="Fetch",e[e.Clone=256]="Clone",e[e.Archive=512]="Archive",e[e.Restore=1024]="Restore",e[e.Merge=2048]="Merge",e[e.Reorder=4096]="Reorder",e[e.Sync=8192]="Sync",e[e.Publish=16384]="Publish",e[e.Link=32768]="Link",e[e.Unlink=65536]="Unlink",e[e.Lock=131072]="Lock",e[e.Unlock=262144]="Unlock",e[e.Import=524288]="Import",e[e.Export=1048576]="Export",e[e.Transfer=2097152]="Transfer",e))(M||{}),k=(e=>(e[e.Produce=0]="Produce",e[e.Hydrate=1]="Hydrate",e))(k||{}),G=(e=>(e.Property="property",e.Process="process",e.Value="value",e.Operation="operation",e))(G||{});class _{[o.immerable]=!0;static keys=new Set(Object.values(G));property=null;process=null;value;operation;constructor(e,t){this.value=e,this.operation=t}assign(e,t){const n=new _(this.value,this.operation);return n.property=e,n.process=t,n}}class R{static immer=(()=>{o.enablePatches();const e=new o.Immer;return e.setAutoFreeze(!1),e})();static tag="κ";static id=C}function N(e,t){const n="string"==typeof t?""===t?[]:t.split("."):t;let r=e;for(const o of n){if(null==r)return;r=r[o]}return r}function z(e){if(t.G.isNullable(e)||T(e))return e;if(t.G.isArray(e))return e.map(e=>z(e));if(t.G.isObject(e)&&L(e)){const t=Object.entries(e).map(([e,t])=>[e,z(t)]);return{...Object.fromEntries(t),[R.tag]:e[R.tag]??R.id()}}return e}function U(e){if(Array.isArray(e))return e.filter(e=>R.tag in e).map(e=>e[R.tag]??"").join(",");const t=e[R.tag];if(t)return t;try{return JSON.stringify(e)}catch{return`[unserializable:${typeof e}]`}}function L(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}function T(e){return t.G.isNullable(e)||t.G.isString(e)||t.G.isNumber(e)||t.G.isBoolean(e)||"symbol"==typeof e||"bigint"==typeof e}function $(e,n,r,o,c,i){return function s(a,u=n.path){if(a instanceof _){const n=N(r,u.join("."));if(Object.entries(a).filter(([e,t])=>!_.keys.has(e)&&t instanceof _).forEach(([e,t])=>s(t,u.concat(e))),T(a.value)){if(e===k.Hydrate)return a.value;const s=u.slice(0,-1),l=s.length>0?N(r,s.join(".")):r;return t.G.isNullable(l)||B(l,a,u.at(-1),o,c,i),n??a.value}if(e===k.Hydrate){const e=z(s(a.value,u));return B(e,a,null,o,c,i),e}const l=n??z(a.value);return B(l,a,null,o,c,i),t.G.isNullable(n)?l:(s(a.value,u),n)}if(t.G.isArray(a))return a.map((e,t)=>s(e,u.concat(t)));if(t.G.isObject(a)&&!L(a))return a;if(t.G.isObject(a)){const t=Object.entries(a).map(([e,t])=>[e,s(t,u.concat(e))]),n=Object.fromEntries(t);if(e===k.Hydrate){const e=z(n);return Object.entries(a).forEach(([t,n])=>{n instanceof _&&T(n.value)&&B(e,n,t,o,c,i)}),e}return n}return a}(n.value)}function B(e,t,n,r,o,c){const i=c(e),s=o.get(i)??[];o.set(i,[t.assign(n,r),...s])}class F{#e={};#t;#n=new Map;#r=new Set;#o=!1;constructor(e=U){this.#t=e}static pk(){return C()}static"κ"=F.pk;annotate(e,t){return new _(t,e)}"δ"=this.annotate;get model(){return this.#e}get inspect(){return function(e,n,r,o,c){function i(o){const c=o.at(-1),i=N(e(),o),s=o.slice(0,-1),a=t.A.isNotEmpty(s)?N(e(),s):e();return[...t.G.isObject(i)||t.G.isArray(i)?n.get(r(i))?.filter(e=>t.G.isNullable(e.property))??[]:[],...t.G.isObject(a)?n.get(r(a))?.filter(e=>e.property===c)??[]:[]]}return function n(r){return new Proxy(()=>{},{get:(s,a)=>"pending"===a?()=>!t.A.isEmpty(i(r)):"remaining"===a?()=>t.A.length(i(r)):"box"===a?()=>({value:N(e(),r),inspect:n(r)}):"is"===a?e=>i(r).some(t=>0!==(t.operation&e)):"draft"===a?()=>t.A.head(i(r))?.value??N(e(),r):"settled"===a?()=>new Promise(n=>{if(t.A.isEmpty(i(r)))return n(N(e(),r));const s=()=>{t.A.isEmpty(i(r))&&(c(s),n(N(e(),r)))};o(s)}):n([...r,String(a)])})}([])}(()=>this.#e,this.#n,this.#t,e=>this.#r.add(e),e=>this.#r.delete(e))}hydrate(e){return this.#o=!0,this.#c(k.Hydrate,()=>e)}produce(e){if(!this.#o)throw new Error("State must be hydrated using hydrate() before calling produce()");return this.#c(k.Produce,e)}#c(e,t){const n=Symbol("process"),[,r]=R.immer.produceWithPatches(this.#e,t);return this.#e=r.reduce((t,r)=>R.immer.applyPatches(t,[{...r,value:$(e,r,t,n,this.#n,this.#t)}]),this.#e),this.#e=z(this.#e),this.#i(),n}prune(e){this.#n.forEach((n,r)=>{const o=n.filter(t=>t.process!==e);t.A.isEmpty(o)?this.#n.delete(r):this.#n.set(r,o)}),this.#i()}#i(){this.#r.forEach(e=>e())}observe(e){const t=()=>e(this.#e);return this.#r.add(t),()=>this.#r.delete(t)}}const W=new F;function D(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var H,I={exports:{}},q=(H||(H=1,function(e){var t=Object.prototype.hasOwnProperty,n="~";function r(){}function o(e,t,n){this.fn=e,this.context=t,this.once=n||!1}function c(e,t,r,c,i){if("function"!=typeof r)throw new TypeError("The listener must be a function");var s=new o(r,c||e,i),a=n?n+t:t;return e._events[a]?e._events[a].fn?e._events[a]=[e._events[a],s]:e._events[a].push(s):(e._events[a]=s,e._eventsCount++),e}function i(e,t){0===--e._eventsCount?e._events=new r:delete e._events[t]}function s(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=Object.create(null),(new r).__proto__||(n=!1)),s.prototype.eventNames=function(){var e,r,o=[];if(0===this._eventsCount)return o;for(r in e=this._events)t.call(e,r)&&o.push(n?r.slice(1):r);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(e)):o},s.prototype.listeners=function(e){var t=this._events[n?n+e:e];if(!t)return[];if(t.fn)return[t.fn];for(var r=0,o=t.length,c=new Array(o);r<o;r++)c[r]=t[r].fn;return c},s.prototype.listenerCount=function(e){var t=this._events[n?n+e:e];return t?t.fn?1:t.length:0},s.prototype.emit=function(e,t,r,o,c,i){var s=n?n+e:e;if(!this._events[s])return!1;var a,u,l=this._events[s],f=arguments.length;if(l.fn){switch(l.once&&this.removeListener(e,l.fn,void 0,!0),f){case 1:return l.fn.call(l.context),!0;case 2:return l.fn.call(l.context,t),!0;case 3:return l.fn.call(l.context,t,r),!0;case 4:return l.fn.call(l.context,t,r,o),!0;case 5:return l.fn.call(l.context,t,r,o,c),!0;case 6:return l.fn.call(l.context,t,r,o,c,i),!0}for(u=1,a=new Array(f-1);u<f;u++)a[u-1]=arguments[u];l.fn.apply(l.context,a)}else{var d,p=l.length;for(u=0;u<p;u++)switch(l[u].once&&this.removeListener(e,l[u].fn,void 0,!0),f){case 1:l[u].fn.call(l[u].context);break;case 2:l[u].fn.call(l[u].context,t);break;case 3:l[u].fn.call(l[u].context,t,r);break;case 4:l[u].fn.call(l[u].context,t,r,o);break;default:if(!a)for(d=1,a=new Array(f-1);d<f;d++)a[d-1]=arguments[d];l[u].fn.apply(l[u].context,a)}}return!0},s.prototype.on=function(e,t,n){return c(this,e,t,n,!1)},s.prototype.once=function(e,t,n){return c(this,e,t,n,!0)},s.prototype.removeListener=function(e,t,r,o){var c=n?n+e:e;if(!this._events[c])return this;if(!t)return i(this,c),this;var s=this._events[c];if(s.fn)s.fn!==t||o&&!s.once||r&&s.context!==r||i(this,c);else{for(var a=0,u=[],l=s.length;a<l;a++)(s[a].fn!==t||o&&!s[a].once||r&&s[a].context!==r)&&u.push(s[a]);u.length?this._events[c]=1===u.length?u[0]:u:i(this,c)}return this},s.prototype.removeAllListeners=function(e){var t;return e?this._events[t=n?n+e:e]&&i(this,t):(this._events=new r,this._eventsCount=0),this},s.prototype.off=s.prototype.removeListener,s.prototype.addListener=s.prototype.on,s.prefixed=n,s.EventEmitter=s,e.exports=s}(I)),I.exports);const V=D(q);class J extends V{cache=new Map;emit(e,...t){return this.cache.set(e,t[0]),super.emit(e,...t)}getCached(e){return this.cache.get(e)}}const K=i.createContext(new J);function Q(){return i.useContext(K)}function X({children:e}){const t=i.useMemo(()=>new J,[]);return n.jsx(K.Provider,{value:t,children:e})}const Y=i.createContext(new Map);function Z({children:e}){const t=i.useMemo(()=>new Map,[]);return n.jsx(Y.Provider,{value:t,children:e})}const ee=i.createContext(new Set);function te({children:e}){const t=i.useMemo(()=>new Set,[]);return n.jsx(ee.Provider,{value:t,children:e})}const ne=i.createContext(null);function re(){return i.useContext(ne)}function oe(e,t){return e?.get(t)??null}function ce({name:e,children:t}){const r=re(),o=i.useMemo(()=>({name:e,emitter:new J}),[]),c=i.useMemo(()=>{const t=new Map(r??[]);return t.set(e,o),t},[r,e,o]);return n.jsx(ne.Provider,{value:c,children:t})}function ie(){const[,e]=i.useReducer(e=>e+1,0);return e}const se=i.createContext(new Map);function ae({action:e,renderer:n}){const r=Q(),o=i.useContext(se),c=ie(),s=i.useMemo(()=>{const t=o.get(e);if(t)return t;const n={state:new F,listeners:new Set};return o.set(e,n),n},[e,o]);i.useLayoutEffect(()=>{function t(e){s.state.hydrate({value:e}),s.listeners.forEach(e=>e())}return s.listeners.add(c),r.on(e,t),()=>{s.listeners.delete(c),r.off(e,t)}},[e,r,s]);const a=s.state.model?.value;return t.G.isNullable(a)?null:n(a,s.state.inspect.value)}e.Action=(e,t=u.Unicast)=>{const n=t===u.Broadcast?Symbol(`${p.broadcastActionPrefix}${e}`):t===u.Multicast?Symbol(`${p.multicastActionPrefix}${e}`):Symbol(`${p.actionPrefix}${e}`),r=function(e){return{[s.Action]:n,[s.Payload]:void 0,[s.Channel]:e,channel:e}};return Object.defineProperty(r,s.Action,{value:n,enumerable:!1}),Object.defineProperty(r,s.Payload,{value:void 0,enumerable:!1}),t===u.Broadcast&&Object.defineProperty(r,s.Broadcast,{value:!0,enumerable:!1}),t===u.Multicast&&Object.defineProperty(r,s.Multicast,{value:!0,enumerable:!1}),r},e.Boundary=function({children:e}){return n.jsx(X,{children:n.jsx(Z,{children:n.jsx(te,{children:e})})})},e.Distribution=u,e.Entry=function(){const e=Symbol("chizu.cache/Entry"),t=function(t){return{[s.Cache]:e,channel:t}};return Object.defineProperty(t,s.Cache,{value:e,enumerable:!1}),t},e.Error=function({handler:e,children:t}){return n.jsx(E.Provider,{value:e,children:t})},e.Lifecycle=a,e.Op=M,e.Operation=M,e.Reason=f,e.Scope=ce,e.State=F,e.With=function(e){return(t,n)=>{t.actions.produce(t=>{t.model[e]=n})}},e.annotate=function(e,t){return W.annotate(e,t)},e.useActions=function(...e){const n=t.G.isUndefined(e[0])||t.G.isFunction(e[0])?{}:e[0],o=t.G.isFunction(e[0])?e[0]:e[1]??(()=>({})),c=Q(),u=re(),f=r.useContext(E),d=i.useContext(ee),p=i.useContext(Y),h=ie(),m=i.useRef(!1),y=i.useRef(null),b=i.useRef(new F);m.current||(m.current=!0,y.current=b.current.hydrate(n));const[v,C]=i.useState(()=>b.current.model),M=function(e){const t=i.useRef(e);return i.useLayoutEffect(()=>{t.current=e},[e]),i.useMemo(()=>{return n=t,Object.keys(e).reduce((e,t)=>(Object.defineProperty(e,t,{get:()=>n.current[t],enumerable:!0}),e),{});var n},[e])}(o()),k=i.useMemo(()=>new V,[]),G=i.useRef({handlers:new Map});G.current.handlers=new Map;const _=function(){const e=i.useRef(new Set),t=i.useRef(new Set);return i.useMemo(()=>({broadcast:e.current,multicast:t.current}),[])}(),R=i.useRef(l.Mounting),N=function(){const e=i.useRef({}),t=i.useRef(new Map),n=i.useRef(new Map);return i.useMemo(()=>({refs:e,pending:t,emitted:n}),[])}(),z=i.useRef(new Set),U=i.useRef(0),L=i.useCallback((e,t,n)=>{const r=new AbortController,o={controller:r,action:e,payload:t};return d.add(o),z.current.add(o),{model:b.current.model,get phase(){return R.current},task:o,data:M,tasks:d,nodes:N.refs.current,actions:{produce(e){if(r.signal.aborted)return;const t=b.current.produce(t=>e({model:t,inspect:b.current.inspect}));C(b.current.model),n.processes.add(t),y.current&&(n.processes.add(y.current),y.current=null)},dispatch(e,t,n){if(r.signal.aborted)return;const o=g(e),i=j(e)?e.channel:void 0;if(S(e)&&n?.scope){const e=oe(u,n.scope);return void(e&&e.emitter.emit(o,t,i))}(w(e)?c:k).emit(o,t,i)},annotate:(e,t)=>b.current.annotate(e,t),async cacheable(e,t,n){if(r.signal.aborted)return{data:null};const o=P(e),c=p.get(o);if(c&&Date.now()<c.expiry)return{data:c.value};const i=function(e){return null!=e&&"object"==typeof e&&"TAG"in e?0===e.TAG?{ok:!0,value:e._0}:{ok:!1}:null==e?{ok:!1}:{ok:!0,value:e}}(await n());return i.ok?(p.set(o,{value:i.value,expiry:Date.now()+t}),{data:i.value}):{data:null}},invalidate(e){p.delete(P(e))},async read(e,t){if(r.signal.aborted)return null;const n=g(e),o=S(e)&&t?.scope?oe(u,t.scope)?.emitter??null:c;if(!o)return null;if(void 0===o.getCached(n))return null;const i=x(e),s="unknown"!==i?i[0].toLowerCase()+i.slice(1):null;if(s){const e=b.current.inspect[s];e?.pending?.()&&await new Promise((t,n)=>{if(r.signal.aborted)return void n(r.signal.reason);const o=()=>n(r.signal.reason);r.signal.addEventListener("abort",o,{once:!0}),e.settled().then(()=>{r.signal.removeEventListener("abort",o),t()})})}return o.getCached(n)??null},peek(e,t){if(r.signal.aborted)return null;const n=g(e),o=S(e)&&t?.scope?oe(u,t.scope)?.emitter??null:c;return o?o.getCached(n)??null:null}}}},[v]);i.useLayoutEffect(()=>{function e(e,n,r){return async function(o,c){const i=r();if(t.G.isNotNullable(c)&&t.G.isNotNullable(i)&&!function(e,t){for(const n of Object.keys(e))if(t[n]!==e[n])return!1;return!0}(c,i))return;const s={processes:new Set},u=Promise.withResolvers(),l=L(e,o,s);try{await n(l,o)}catch(p){const t=G.current.handlers.has(a.Error),n={reason:A(p),error:O(p),action:x(e),handled:t,tasks:d};f?.(n),t&&k.emit(a.Error,n)}finally{for(const e of d)if(e===l.task){d.delete(e),z.current.delete(e);break}s.processes.forEach(e=>b.current.prune(e)),s.processes.size>0&&h(),u.resolve()}}}U.current++;const n=new Set;return G.current.handlers.forEach((t,r)=>{for(const{getChannel:o,handler:i}of t){const t=e(r,i,o);if(S(r)){if(u)for(const e of u.values()){const o=e.emitter;o.on(r,t),n.add(()=>o.off(r,t))}k.on(r,t),_.multicast.add(r),n.add(()=>k.off(r,t))}else w(r)?(c.on(r,t),k.on(r,t),_.broadcast.add(r),n.add(()=>{c.off(r,t),k.off(r,t)})):(k.on(r,t),n.add(()=>k.off(r,t)))}}),()=>{const e=++U.current,t=new Set(n);queueMicrotask(()=>{if(U.current===e){for(const e of z.current)e.controller.abort(),d.delete(e);z.current.clear(),R.current=l.Unmounting,k.emit(a.Unmount),R.current=l.Unmounted;for(const e of t)e()}else for(const e of t)e()})}},[k]),i.useLayoutEffect(()=>{for(const[e,t]of N.pending.current)N.emitted.current.get(e)!==t&&(N.emitted.current.set(e,t),k.emit(s.Node,t,{Name:e}));N.pending.current.clear()}),function({unicast:e,broadcast:n,dispatchers:r,scope:o,phase:c,data:s}){const u=i.useRef(null);i.useLayoutEffect(()=>{c.current===l.Mounting&&(e.emit(a.Mount),r.broadcast.forEach(r=>{const o=n.getCached(r);t.G.isNullable(o)||e.emit(r,o)}),o&&r.multicast.forEach(n=>{for(const r of o.values()){const o=r.emitter.getCached(n);t.G.isNullable(o)||e.emit(n,o)}}),c.current=l.Mounted)},[]),i.useLayoutEffect(()=>{if(t.G.isNotNullable(u.current)){const n=function(e,t){return Object.keys(t).reduce((n,r)=>e[r]!==t[r]?{...n,[r]:t[r]}:n,{})}(u.current,s);t.A.isNotEmpty(Object.keys(n))&&e.emit(a.Update,n)}u.current=s},[s,e])}({unicast:k,broadcast:c,dispatchers:_,scope:u,phase:R,data:o()});const T=i.useMemo(()=>[v,{dispatch(e,t,n){const r=g(e),o=j(e)?e.channel:void 0;if(S(e)&&n?.scope){const e=oe(u,n.scope);return void(e&&e.emitter.emit(r,t,o))}(w(e)?c:k).emit(r,t,o)},get inspect(){return b.current.inspect},get nodes(){return N.refs.current},node(e,t){N.refs.current[e]=t,N.pending.current.set(e,t)},stream:(e,t)=>i.createElement(ae,{action:g(e),renderer:t})}],[v,k]);return T.useAction=(e,t)=>{!function(e,t,n){const r=i.useRef(n);i.useLayoutEffect(()=>{r.current=n});const o=i.useRef(t);i.useLayoutEffect(()=>{o.current=t});const c=i.useCallback(async(e,t)=>{const n=r.current;if("GeneratorFunction"===n.constructor.name||"AsyncGeneratorFunction"===n.constructor.name){const r=n(e,t);for await(const e of r);}else await n(e,t)},[]),s=i.useCallback(()=>j(o.current)?o.current.channel:void 0,[]),a=g(t),u=e.current.handlers.get(a)??new Set;0===u.size&&e.current.handlers.set(a,u),u.add({getChannel:s,handler:c})}(G,e,t)},T},e.utils=b,e.withScope=function(e,t){const r=`Scoped${t.displayName||t.name||"Component"}`;return{[r]:r=>n.jsx(ce,{name:e,children:n.jsx(t,{...r})})}[r]},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})},"object"==typeof exports&&"undefined"!=typeof module?factory(exports,require("@mobily/ts-belt"),require("react/jsx-runtime"),require("react"),require("immer")):"function"==typeof define&&define.amd?define(["exports","@mobily/ts-belt","react/jsx-runtime","react","immer"],factory):factory((global="undefined"!=typeof globalThis?globalThis:global||self).Chizu={},global.TsBelt,global.jsxRuntime,global.React,global.Immer);
|
package/dist/hooks/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { default as EventEmitter } from 'eventemitter3';
|
|
|
2
2
|
import { RefObject } from 'react';
|
|
3
3
|
import { Model, HandlerContext, Actions, Props, Tasks, ActionId, Phase, Filter, Nodes } from '../types/index.ts';
|
|
4
4
|
import { BroadcastEmitter } from '../boundary/components/broadcast/utils.ts';
|
|
5
|
+
import { ScopeContext } from '../boundary/components/scope/types.ts';
|
|
5
6
|
/**
|
|
6
7
|
* Return type for the useNodes hook.
|
|
7
8
|
* Contains refs for captured nodes, pending captures, and last emitted nodes.
|
|
@@ -55,14 +56,31 @@ export type Scope<M extends Model | void = Model, A extends Actions | void = Act
|
|
|
55
56
|
* @template D - The data props type
|
|
56
57
|
*/
|
|
57
58
|
export type Data<D extends Props = Props> = () => D;
|
|
59
|
+
/**
|
|
60
|
+
* Return type for useDispatchers hook.
|
|
61
|
+
*/
|
|
62
|
+
export type Dispatchers = {
|
|
63
|
+
/** Set of registered broadcast action IDs */
|
|
64
|
+
broadcast: Set<ActionId>;
|
|
65
|
+
/** Set of registered multicast action IDs */
|
|
66
|
+
multicast: Set<ActionId>;
|
|
67
|
+
};
|
|
58
68
|
/**
|
|
59
69
|
* Configuration for {@link useLifecycles}.
|
|
60
70
|
*/
|
|
61
71
|
export type LifecycleConfig = {
|
|
72
|
+
/** Component-local event emitter for unicast action dispatch */
|
|
62
73
|
unicast: EventEmitter;
|
|
74
|
+
/** Shared broadcast emitter with cached values for cross-component events */
|
|
63
75
|
broadcast: BroadcastEmitter;
|
|
76
|
+
/** Global set of all in-flight tasks across components */
|
|
64
77
|
tasks: Tasks;
|
|
65
|
-
|
|
78
|
+
/** Tracked broadcast and multicast action sets for cached replay on mount */
|
|
79
|
+
dispatchers: Dispatchers;
|
|
80
|
+
/** Scope context for multicast cached replay (null when outside any scope) */
|
|
81
|
+
scope: ScopeContext;
|
|
82
|
+
/** Mutable ref tracking the component's current lifecycle phase */
|
|
66
83
|
phase: RefObject<Phase>;
|
|
84
|
+
/** Current snapshot of reactive data props for change detection */
|
|
67
85
|
data: Props;
|
|
68
86
|
};
|
package/dist/hooks/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RefObject } from 'react';
|
|
2
2
|
import { Props, Model, Actions, Filter, ActionId, HandlerPayload, ChanneledAction, HandlerContext } from '../types/index.ts';
|
|
3
|
-
import { LifecycleConfig, References, Scope } from './types.ts';
|
|
3
|
+
import { Dispatchers, LifecycleConfig, References, Scope } from './types.ts';
|
|
4
4
|
import { isChanneledAction, getActionSymbol } from '../action/index.ts';
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
/**
|
|
@@ -24,7 +24,7 @@ export declare function isGenerator(result: unknown): result is Generator | Asyn
|
|
|
24
24
|
* - Mounting → (cached broadcast action values emitted here) → Mounted
|
|
25
25
|
* - Mounted → Unmounting → Unmounted
|
|
26
26
|
*/
|
|
27
|
-
export declare function useLifecycles({ unicast, broadcast,
|
|
27
|
+
export declare function useLifecycles({ unicast, broadcast, dispatchers, scope, phase, data, }: LifecycleConfig): void;
|
|
28
28
|
/**
|
|
29
29
|
* Creates a data proxy for a given object, returning a memoized version.
|
|
30
30
|
* The proxy provides stable access to the object's properties,
|
|
@@ -70,15 +70,6 @@ export declare function useData<P extends Props>(props: P): P;
|
|
|
70
70
|
*/
|
|
71
71
|
export declare function With<K extends string>(key: K): <M extends Model, A extends Actions | void, D extends Props, P extends K extends keyof M ? M[K] : never>(context: HandlerContext<M, A, D>, payload: P) => void;
|
|
72
72
|
export { isChanneledAction, getActionSymbol };
|
|
73
|
-
/**
|
|
74
|
-
* Return type for useActionSets hook.
|
|
75
|
-
*/
|
|
76
|
-
export type ActionSets = {
|
|
77
|
-
/** Set of registered broadcast action IDs */
|
|
78
|
-
broadcast: Set<ActionId>;
|
|
79
|
-
/** Set of registered multicast action IDs */
|
|
80
|
-
multicast: Set<ActionId>;
|
|
81
|
-
};
|
|
82
73
|
/**
|
|
83
74
|
* Manages sets of broadcast and multicast action IDs.
|
|
84
75
|
*
|
|
@@ -91,7 +82,7 @@ export type ActionSets = {
|
|
|
91
82
|
*
|
|
92
83
|
* @example
|
|
93
84
|
* ```ts
|
|
94
|
-
* const actions =
|
|
85
|
+
* const actions = useDispatchers();
|
|
95
86
|
*
|
|
96
87
|
* // Register a broadcast action
|
|
97
88
|
* actions.broadcast.add(getActionSymbol(MyBroadcastAction));
|
|
@@ -104,7 +95,7 @@ export type ActionSets = {
|
|
|
104
95
|
*
|
|
105
96
|
* @internal
|
|
106
97
|
*/
|
|
107
|
-
export declare function
|
|
98
|
+
export declare function useDispatchers(): Dispatchers;
|
|
108
99
|
/**
|
|
109
100
|
* Registers an action handler within a component's scope.
|
|
110
101
|
*
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Operation, Process, Inspect, Box } from 'immertation';
|
|
|
2
2
|
import { ActionId, Task, Tasks } from '../boundary/components/tasks/types.ts';
|
|
3
3
|
import { Option } from '@mobily/ts-belt/Option';
|
|
4
4
|
import { Result as TsBeltResult } from '@mobily/ts-belt/Result';
|
|
5
|
+
import * as React from "react";
|
|
5
6
|
export type { ActionId, Box, Task, Tasks };
|
|
6
7
|
/**
|
|
7
8
|
* Type for objects with a Brand.Action symbol property.
|
|
@@ -586,7 +587,7 @@ export type HandlerContext<M extends Model | void, _AC extends Actions | void, D
|
|
|
586
587
|
*/
|
|
587
588
|
invalidate(entry: CacheId<unknown> | ChanneledCacheId<unknown>): void;
|
|
588
589
|
/**
|
|
589
|
-
* Reads the latest broadcast or multicast value, waiting for
|
|
590
|
+
* Reads the latest broadcast or multicast value, waiting for annotations to settle.
|
|
590
591
|
*
|
|
591
592
|
* If a value has already been dispatched it resolves immediately.
|
|
592
593
|
* Otherwise it waits until the next dispatch of the action.
|
|
@@ -610,6 +611,26 @@ export type HandlerContext<M extends Model | void, _AC extends Actions | void, D
|
|
|
610
611
|
*/
|
|
611
612
|
read<T>(action: BroadcastPayload<T>): Promise<T | null>;
|
|
612
613
|
read<T>(action: MulticastPayload<T>, options: MulticastOptions): Promise<T | null>;
|
|
614
|
+
/**
|
|
615
|
+
* Returns the latest broadcast or multicast value immediately without
|
|
616
|
+
* waiting for annotations to settle. Use this when you need the current
|
|
617
|
+
* cached value and do not need to wait for pending operations to complete.
|
|
618
|
+
*
|
|
619
|
+
* @param action - The broadcast or multicast action to peek at.
|
|
620
|
+
* @param options - For multicast actions, must include `{ scope: "ScopeName" }`.
|
|
621
|
+
* @returns The cached value, or `null` if no value has been dispatched.
|
|
622
|
+
*
|
|
623
|
+
* @example
|
|
624
|
+
* ```ts
|
|
625
|
+
* actions.useAction(Actions.Check, (context) => {
|
|
626
|
+
* const user = context.actions.peek(Actions.Broadcast.User);
|
|
627
|
+
* if (!user) return;
|
|
628
|
+
* console.log(user.name);
|
|
629
|
+
* });
|
|
630
|
+
* ```
|
|
631
|
+
*/
|
|
632
|
+
peek<T>(action: BroadcastPayload<T>): T | null;
|
|
633
|
+
peek<T>(action: MulticastPayload<T>, options: MulticastOptions): T | null;
|
|
613
634
|
};
|
|
614
635
|
};
|
|
615
636
|
/**
|
|
@@ -694,11 +715,6 @@ type OwnKeys<AC> = Exclude<keyof AC & string, "prototype">;
|
|
|
694
715
|
export type Handlers<M extends Model | void, AC extends Actions | void, D extends Props = Props> = {
|
|
695
716
|
[K in OwnKeys<AC>]: OwnKeys<AC[K]> extends never ? (context: HandlerContext<M, AC, D>, ...args: [Payload<AC[K] & HandlerPayload<unknown>>] extends [never] ? [] : [payload: Payload<AC[K] & HandlerPayload<unknown>>]) => void | Promise<void> | AsyncGenerator | Generator : Handlers<M, AC[K] & Actions, D>;
|
|
696
717
|
};
|
|
697
|
-
/**
|
|
698
|
-
* Union of action types accepted by `derive` configuration entries.
|
|
699
|
-
* @internal
|
|
700
|
-
*/
|
|
701
|
-
type DerivedAction = HandlerPayload<any> | ChanneledAction<any, any>;
|
|
702
718
|
export type UseActions<M extends Model | void, AC extends Actions | void, D extends Props = Props> = [
|
|
703
719
|
Readonly<M>,
|
|
704
720
|
{
|
|
@@ -765,6 +781,29 @@ export type UseActions<M extends Model | void, AC extends Actions | void, D exte
|
|
|
765
781
|
* ```
|
|
766
782
|
*/
|
|
767
783
|
node<K extends keyof Nodes<M>>(name: K, node: Nodes<M>[K] | null): void;
|
|
784
|
+
/**
|
|
785
|
+
* Streams broadcast values declaratively in JSX using a render-prop pattern.
|
|
786
|
+
*
|
|
787
|
+
* Subscribes to the given broadcast action and re-renders when a new value
|
|
788
|
+
* is dispatched. Returns `null` until the first dispatch. The renderer
|
|
789
|
+
* receives the value and an inspect proxy for annotation tracking.
|
|
790
|
+
*
|
|
791
|
+
* @param action - The broadcast action to subscribe to.
|
|
792
|
+
* @param renderer - Callback that receives value and inspect, returns React nodes.
|
|
793
|
+
* @returns React nodes from the renderer, or null if no value has been dispatched.
|
|
794
|
+
*
|
|
795
|
+
* @example
|
|
796
|
+
* ```tsx
|
|
797
|
+
* return (
|
|
798
|
+
* <div>
|
|
799
|
+
* {actions.stream(Actions.Broadcast.User, (user, inspect) => (
|
|
800
|
+
* <span>{user.name}</span>
|
|
801
|
+
* ))}
|
|
802
|
+
* </div>
|
|
803
|
+
* );
|
|
804
|
+
* ```
|
|
805
|
+
*/
|
|
806
|
+
stream<T extends object>(action: BroadcastPayload<T>, renderer: (value: T, inspect: Inspect<T>) => React.ReactNode): React.ReactNode;
|
|
768
807
|
}
|
|
769
808
|
] & {
|
|
770
809
|
/**
|
|
@@ -794,37 +833,4 @@ export type UseActions<M extends Model | void, AC extends Actions | void, D exte
|
|
|
794
833
|
* ```
|
|
795
834
|
*/
|
|
796
835
|
useAction<A extends ActionId | HandlerPayload | ChanneledAction>(action: A, handler: (context: HandlerContext<M, AC, D>, ...args: [Payload<A>] extends [never] ? [] : [payload: Payload<A>]) => void | Promise<void> | AsyncGenerator | Generator): void;
|
|
797
|
-
/**
|
|
798
|
-
* Derives a model property from the current model state. The selector
|
|
799
|
-
* evaluates synchronously on every render and always has a value.
|
|
800
|
-
*
|
|
801
|
-
* @param key - The property name to add to the model
|
|
802
|
-
* @param selector - A function receiving the current model, returning the derived value
|
|
803
|
-
* @returns A new UseActions tuple with the model extended by the derived property
|
|
804
|
-
*
|
|
805
|
-
* @example
|
|
806
|
-
* ```ts
|
|
807
|
-
* actions.derive('greeting', (model) => `Hey ${model.name}`);
|
|
808
|
-
* ```
|
|
809
|
-
*/
|
|
810
|
-
derive<K extends string, R>(key: M extends void ? never : K, selector: (model: Readonly<M>) => R): UseActions<M & Record<K, R>, AC, D>;
|
|
811
|
-
/**
|
|
812
|
-
* Derives a model property from an action's payload. When the action fires,
|
|
813
|
-
* the callback runs and the return value is applied to the model under the
|
|
814
|
-
* given key. Before the action fires the value is `null`.
|
|
815
|
-
*
|
|
816
|
-
* Works with unicast, broadcast, multicast, and channeled actions.
|
|
817
|
-
* For broadcast actions, cached values are replayed on mount.
|
|
818
|
-
*
|
|
819
|
-
* @param key - The property name to add to the model
|
|
820
|
-
* @param action - The action to subscribe to
|
|
821
|
-
* @param callback - Receives the action payload, returns the derived value
|
|
822
|
-
* @returns A new UseActions tuple with the model extended by the derived property
|
|
823
|
-
*
|
|
824
|
-
* @example
|
|
825
|
-
* ```ts
|
|
826
|
-
* actions.derive('doubled', Actions.Broadcast.Counter, (counter) => counter * 2);
|
|
827
|
-
* ```
|
|
828
|
-
*/
|
|
829
|
-
derive<K extends string, A extends DerivedAction, R>(key: M extends void ? never : K, action: A, callback: [Payload<A>] extends [never] ? () => R : (payload: Payload<A>) => R): UseActions<M & Record<K, R | null>, AC, D>;
|
|
830
836
|
};
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -16,16 +16,30 @@ export declare const config: {
|
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
18
|
* Returns a promise that resolves after the specified number of milliseconds.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* The sleep will reject with an AbortError when the signal is aborted,
|
|
20
|
+
* allowing cleanup of pending operations.
|
|
21
21
|
*
|
|
22
22
|
* @param ms The number of milliseconds to sleep.
|
|
23
|
-
* @param signal
|
|
23
|
+
* @param signal AbortSignal to cancel the sleep early.
|
|
24
24
|
* @returns A promise that resolves after the delay or rejects if aborted.
|
|
25
25
|
*/
|
|
26
|
-
export declare function sleep(ms: number, signal
|
|
26
|
+
export declare function sleep(ms: number, signal: AbortSignal | undefined): Promise<void>;
|
|
27
27
|
/** Shorthand alias for {@link sleep}. */
|
|
28
28
|
export declare const ζ: typeof sleep;
|
|
29
|
+
/**
|
|
30
|
+
* Repeatedly calls a function at a fixed interval until it returns `true` or
|
|
31
|
+
* the signal is aborted. The function is invoked immediately on the first
|
|
32
|
+
* iteration, then after each interval.
|
|
33
|
+
*
|
|
34
|
+
* @param ms The interval in milliseconds between invocations.
|
|
35
|
+
* @param signal Optional AbortSignal to cancel polling early.
|
|
36
|
+
* @param fn Callback invoked each iteration. Return `true` to stop polling.
|
|
37
|
+
* @returns A promise that resolves when `fn` returns `true`, or rejects with
|
|
38
|
+
* an AbortError if the signal is aborted.
|
|
39
|
+
*/
|
|
40
|
+
export declare function poll(ms: number, signal: AbortSignal | undefined, fn: () => boolean | Promise<boolean>): Promise<void>;
|
|
41
|
+
/** Shorthand alias for {@link poll}. */
|
|
42
|
+
export declare const π: typeof poll;
|
|
29
43
|
/**
|
|
30
44
|
* Generates a unique primary key.
|
|
31
45
|
* @returns A new unique symbol representing the primary key.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chizu",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.67",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"packageManager": "yarn@1.22.22",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"eventemitter3": "^5.0.
|
|
17
|
+
"eventemitter3": "^5.0.4",
|
|
18
18
|
"immertation": "^0.1.26"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
@@ -34,62 +34,62 @@
|
|
|
34
34
|
"prepare": "husky"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@babel/plugin-proposal-decorators": "^7.
|
|
38
|
-
"@babel/preset-env": "^7.
|
|
37
|
+
"@babel/plugin-proposal-decorators": "^7.29.0",
|
|
38
|
+
"@babel/preset-env": "^7.29.0",
|
|
39
39
|
"@babel/preset-react": "^7.28.5",
|
|
40
40
|
"@babel/preset-typescript": "^7.28.5",
|
|
41
41
|
"@emotion/css": "^11.13.5",
|
|
42
|
-
"@eslint/js": "^9.39.
|
|
43
|
-
"@faker-js/faker": "^10.
|
|
42
|
+
"@eslint/js": "^9.39.3",
|
|
43
|
+
"@faker-js/faker": "^10.3.0",
|
|
44
44
|
"@jest/globals": "^30.2.0",
|
|
45
45
|
"@mobily/ts-belt": "4.0.0-rc.5",
|
|
46
|
-
"@playwright/test": "^1.
|
|
46
|
+
"@playwright/test": "^1.58.2",
|
|
47
47
|
"@testing-library/dom": "^10.4.1",
|
|
48
48
|
"@testing-library/jest-dom": "^6.9.1",
|
|
49
|
-
"@testing-library/react": "^16.3.
|
|
49
|
+
"@testing-library/react": "^16.3.2",
|
|
50
50
|
"@types/lodash": "^4.17.23",
|
|
51
51
|
"@types/ramda": "^0.31.1",
|
|
52
|
-
"@types/react": "^19.2.
|
|
52
|
+
"@types/react": "^19.2.14",
|
|
53
53
|
"@types/react-dom": "^19.2.3",
|
|
54
54
|
"@types/traverse": "^0.6.37",
|
|
55
|
-
"@vitejs/plugin-react": "^5.1.
|
|
56
|
-
"antd": "^6.
|
|
55
|
+
"@vitejs/plugin-react": "^5.1.4",
|
|
56
|
+
"antd": "^6.3.0",
|
|
57
57
|
"commit-and-tag-version": "^12.6.1",
|
|
58
58
|
"dayjs": "^1.11.19",
|
|
59
|
-
"dexie": "^4.
|
|
60
|
-
"eslint": "^9.39.
|
|
59
|
+
"dexie": "^4.3.0",
|
|
60
|
+
"eslint": "^9.39.3",
|
|
61
61
|
"eslint-plugin-fp": "^2.3.0",
|
|
62
62
|
"eslint-plugin-import": "^2.32.0",
|
|
63
63
|
"eslint-plugin-react": "^7.37.5",
|
|
64
64
|
"fslint": "^1.1.0",
|
|
65
65
|
"get-port-cli": "^3.0.0",
|
|
66
|
-
"globals": "^17.
|
|
67
|
-
"happy-dom": "^20.
|
|
66
|
+
"globals": "^17.3.0",
|
|
67
|
+
"happy-dom": "^20.6.1",
|
|
68
68
|
"husky": "^9.1.7",
|
|
69
|
-
"immer": "^11.1.
|
|
69
|
+
"immer": "^11.1.4",
|
|
70
70
|
"jest": "^30.2.0",
|
|
71
71
|
"jest-environment-jsdom": "^30.2.0",
|
|
72
|
-
"jsdom": "^
|
|
72
|
+
"jsdom": "^28.1.0",
|
|
73
73
|
"lodash": "^4.17.23",
|
|
74
|
-
"lucide-react": "^0.
|
|
74
|
+
"lucide-react": "^0.564.0",
|
|
75
75
|
"madge": "^8.0.0",
|
|
76
|
-
"prettier": "^3.
|
|
76
|
+
"prettier": "^3.8.1",
|
|
77
77
|
"ramda": "^0.32.0",
|
|
78
|
-
"react": "^19.2.
|
|
79
|
-
"react-dom": "^19.2.
|
|
78
|
+
"react": "^19.2.4",
|
|
79
|
+
"react-dom": "^19.2.4",
|
|
80
80
|
"react-flip-numbers": "^3.0.9",
|
|
81
|
-
"react-router-dom": "^7.
|
|
82
|
-
"react-test-renderer": "^19.2.
|
|
81
|
+
"react-router-dom": "^7.13.0",
|
|
82
|
+
"react-test-renderer": "^19.2.4",
|
|
83
83
|
"rollup-plugin-visualizer": "^6.0.5",
|
|
84
84
|
"terser": "^5.46.0",
|
|
85
85
|
"traverse": "^0.6.11",
|
|
86
86
|
"ts-jest": "^29.4.6",
|
|
87
87
|
"ts-node": "^10.9.2",
|
|
88
88
|
"typescript": "^5.9.3",
|
|
89
|
-
"typescript-eslint": "^8.
|
|
89
|
+
"typescript-eslint": "^8.55.0",
|
|
90
90
|
"vite": "^7.3.1",
|
|
91
91
|
"vite-plugin-dts": "^4.5.4",
|
|
92
|
-
"vitest": "^4.0.
|
|
93
|
-
"wait-on": "^9.0.
|
|
92
|
+
"vitest": "^4.0.18",
|
|
93
|
+
"wait-on": "^9.0.4"
|
|
94
94
|
}
|
|
95
95
|
}
|