chizu 0.2.65 → 0.2.70
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 +50 -25
- package/dist/action/index.d.ts +3 -3
- package/dist/action/utils.d.ts +21 -0
- 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/boundary/components/regulators/index.d.ts +14 -0
- package/dist/boundary/components/regulators/types.d.ts +52 -0
- package/dist/boundary/components/regulators/utils.d.ts +21 -0
- package/dist/chizu.js +8 -7
- package/dist/chizu.umd.cjs +1 -1
- package/dist/error/index.d.ts +1 -1
- package/dist/error/types.d.ts +14 -1
- package/dist/hooks/types.d.ts +21 -1
- package/dist/hooks/utils.d.ts +20 -12
- package/dist/index.d.ts +3 -1
- package/dist/types/index.d.ts +101 -63
- package/dist/utils/index.d.ts +20 -4
- package/package.json +26 -26
package/README.md
CHANGED
|
@@ -118,9 +118,13 @@ Both the model and actions type parameters default to `void`, so you can call `u
|
|
|
118
118
|
```tsx
|
|
119
119
|
import { useActions, Lifecycle } from "chizu";
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
class Actions {
|
|
122
|
+
static Mount = Lifecycle.Mount();
|
|
123
|
+
}
|
|
122
124
|
|
|
123
|
-
actions
|
|
125
|
+
const actions = useActions<void, typeof Actions>();
|
|
126
|
+
|
|
127
|
+
actions.useAction(Actions.Mount, () => {
|
|
124
128
|
console.log("Mounted!");
|
|
125
129
|
});
|
|
126
130
|
```
|
|
@@ -176,15 +180,7 @@ actions.useAction(Actions.Profile, async (context) => {
|
|
|
176
180
|
});
|
|
177
181
|
```
|
|
178
182
|
|
|
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`:
|
|
183
|
+
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
184
|
|
|
189
185
|
```tsx
|
|
190
186
|
actions.useAction(Actions.Broadcast.Name, async (context, name) => {
|
|
@@ -196,7 +192,7 @@ actions.useAction(Actions.Broadcast.Name, async (context, name) => {
|
|
|
196
192
|
});
|
|
197
193
|
```
|
|
198
194
|
|
|
199
|
-
|
|
195
|
+
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
196
|
|
|
201
197
|
```tsx
|
|
202
198
|
actions.useAction(Actions.FetchFriends, async (context) => {
|
|
@@ -209,6 +205,34 @@ actions.useAction(Actions.FetchFriends, async (context) => {
|
|
|
209
205
|
});
|
|
210
206
|
```
|
|
211
207
|
|
|
208
|
+
`peek` is useful for guard checks or synchronous reads where you don't need to wait for settled state:
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
actions.useAction(Actions.Check, (context) => {
|
|
212
|
+
const name = context.actions.peek(Actions.Broadcast.Name);
|
|
213
|
+
if (!name) return;
|
|
214
|
+
console.log(name);
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
You can also render broadcast values declaratively in JSX with `actions.stream`. The renderer callback receives `(value, inspect)` and returns React nodes:
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
function Dashboard() {
|
|
222
|
+
const [model, actions] = useDashboardActions();
|
|
223
|
+
|
|
224
|
+
return (
|
|
225
|
+
<div>
|
|
226
|
+
{actions.stream(Actions.Broadcast.User, (user, inspect) => (
|
|
227
|
+
<span>Welcome, {user.name}</span>
|
|
228
|
+
))}
|
|
229
|
+
</div>
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
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.
|
|
235
|
+
|
|
212
236
|
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
237
|
|
|
214
238
|
```tsx
|
|
@@ -279,12 +303,9 @@ function App() {
|
|
|
279
303
|
|
|
280
304
|
// Dispatch to all components within "TeamA" scope
|
|
281
305
|
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
306
|
```
|
|
286
307
|
|
|
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.
|
|
308
|
+
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
309
|
|
|
289
310
|
For components that always render inside a scope, use the `withScope` HOC to eliminate the manual `<Scope>` wrapper:
|
|
290
311
|
|
|
@@ -360,15 +381,19 @@ context.actions.invalidate(CacheStore.User({ UserId: 5 }));
|
|
|
360
381
|
|
|
361
382
|
The cache is scoped to the nearest `<Boundary>`. See the [caching recipe](./recipes/caching.md) for more details.
|
|
362
383
|
|
|
363
|
-
|
|
384
|
+
The action regulator lets handlers control which actions may be dispatched across all components within a `<Boundary>`. Use `context.regulator` to block or allow actions:
|
|
364
385
|
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
.
|
|
369
|
-
|
|
386
|
+
```ts
|
|
387
|
+
actions.useAction(Actions.Checkout, async (context) => {
|
|
388
|
+
// Allow only the cancel action during checkout
|
|
389
|
+
context.regulator.allow(Actions.Cancel);
|
|
390
|
+
|
|
391
|
+
try {
|
|
392
|
+
await processPayment(context.task.controller.signal);
|
|
393
|
+
} finally {
|
|
394
|
+
context.regulator.allow();
|
|
395
|
+
}
|
|
396
|
+
});
|
|
370
397
|
```
|
|
371
398
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
See the [derived values recipe](./recipes/derived-values.md) for more details.
|
|
399
|
+
`disallow()` blocks all, `disallow(A, B)` blocks specific actions, `allow()` allows all (reset), and `allow(A, B)` allows only those actions. Each call replaces the previous policy (last-write-wins). Blocked actions fire `Reason.Disallowed` through the error system without allocating resources. See the [action regulator recipe](./recipes/action-regulator.md) for more details.
|
package/dist/action/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HandlerPayload, BroadcastPayload, MulticastPayload, Distribution, Filter } from '../types/index.ts';
|
|
2
|
-
export { getActionSymbol, isBroadcastAction, isMulticastAction, getName, isChanneledAction, } from './utils.ts';
|
|
2
|
+
export { getActionSymbol, getLifecycleType, isBroadcastAction, isMulticastAction, getName, isChanneledAction, } from './utils.ts';
|
|
3
3
|
/**
|
|
4
4
|
* Interface for the Action factory function.
|
|
5
5
|
*/
|
|
@@ -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;
|
package/dist/action/utils.d.ts
CHANGED
|
@@ -58,6 +58,27 @@ export declare function getName(action: AnyAction): string;
|
|
|
58
58
|
* ```
|
|
59
59
|
*/
|
|
60
60
|
export declare function isChanneledAction(action: AnyAction): action is ChanneledAction;
|
|
61
|
+
/**
|
|
62
|
+
* Extracts the lifecycle type from an action's symbol description.
|
|
63
|
+
*
|
|
64
|
+
* Returns the lifecycle name (`"Mount"`, `"Unmount"`, `"Error"`, `"Update"`,
|
|
65
|
+
* `"Node"`) when the action symbol's description starts with the lifecycle
|
|
66
|
+
* prefix, or `null` for non-lifecycle actions.
|
|
67
|
+
*
|
|
68
|
+
* @param action The action to inspect.
|
|
69
|
+
* @returns The lifecycle name, or `null` if not a lifecycle action.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* class Actions {
|
|
74
|
+
* static Mount = Lifecycle.Mount();
|
|
75
|
+
* }
|
|
76
|
+
*
|
|
77
|
+
* getLifecycleType(Actions.Mount); // "Mount"
|
|
78
|
+
* getLifecycleType(Action("Increment")); // null
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export declare function getLifecycleType(action: AnyAction): string | null;
|
|
61
82
|
/**
|
|
62
83
|
* Checks whether an action is a multicast action.
|
|
63
84
|
* Multicast actions are dispatched to all components within a named scope boundary.
|
|
@@ -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.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Props } from './types.ts';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export { useRegulators, isAllowed } from './utils.ts';
|
|
4
|
+
export type { Regulator, RegulatorPolicy } from './types.ts';
|
|
5
|
+
/**
|
|
6
|
+
* Provides a shared regulator policy to all descendant components.
|
|
7
|
+
*
|
|
8
|
+
* Wrap this around your component tree (or use `<Boundary>` which includes it)
|
|
9
|
+
* to enable action regulation via `context.regulator`.
|
|
10
|
+
*
|
|
11
|
+
* @param props.children - The children to render within the regulator context.
|
|
12
|
+
* @returns The children wrapped in a regulator context provider.
|
|
13
|
+
*/
|
|
14
|
+
export declare function Regulators({ children }: Props): React.ReactNode;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ActionId } from '../tasks/types.ts';
|
|
2
|
+
import type * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* The four policy modes that the regulator supports.
|
|
5
|
+
*
|
|
6
|
+
* - `allow-all` (default) – every action is permitted (`allow()` with no args).
|
|
7
|
+
* - `disallow-all` – every action is blocked (`disallow()` with no args).
|
|
8
|
+
* - `disallow-matching` – only the listed actions are blocked (`disallow(A, B)`).
|
|
9
|
+
* - `allow-matching` – only the listed actions are permitted (`allow(A, B)`).
|
|
10
|
+
*
|
|
11
|
+
* For "except" patterns, compose two calls:
|
|
12
|
+
* - Block all except X: `disallow()` then `allow(X)`.
|
|
13
|
+
* - Allow all except X: `allow()` then `disallow(X)`.
|
|
14
|
+
*/
|
|
15
|
+
export type RegulatorMode = "allow-all" | "disallow-all" | "disallow-matching" | "allow-matching";
|
|
16
|
+
/**
|
|
17
|
+
* Mutable policy object shared across all components in a `<Boundary>`.
|
|
18
|
+
* Mutated in-place by the `context.regulator` API – last write wins.
|
|
19
|
+
*/
|
|
20
|
+
export type RegulatorPolicy = {
|
|
21
|
+
mode: RegulatorMode;
|
|
22
|
+
actions: Set<ActionId>;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The `context.regulator` API shape exposed to action handlers.
|
|
26
|
+
*
|
|
27
|
+
* - `disallow()` – block all actions.
|
|
28
|
+
* - `disallow(A, B)` – block only the listed actions.
|
|
29
|
+
* - `allow()` – allow all actions (reset to default).
|
|
30
|
+
* - `allow(A, B)` – allow only the listed actions.
|
|
31
|
+
*
|
|
32
|
+
* Each call replaces the previous policy entirely (last-write-wins).
|
|
33
|
+
*/
|
|
34
|
+
export type Regulator = {
|
|
35
|
+
/**
|
|
36
|
+
* Block actions. Called with no arguments, blocks everything.
|
|
37
|
+
* Called with specific actions, blocks only those actions.
|
|
38
|
+
*/
|
|
39
|
+
disallow(...actions: ReadonlyArray<{
|
|
40
|
+
readonly [x: symbol]: unknown;
|
|
41
|
+
}>): void;
|
|
42
|
+
/**
|
|
43
|
+
* Allow actions. Called with no arguments, allows everything (reset).
|
|
44
|
+
* Called with specific actions, allows only those actions.
|
|
45
|
+
*/
|
|
46
|
+
allow(...actions: ReadonlyArray<{
|
|
47
|
+
readonly [x: symbol]: unknown;
|
|
48
|
+
}>): void;
|
|
49
|
+
};
|
|
50
|
+
export type Props = {
|
|
51
|
+
children: React.ReactNode;
|
|
52
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ActionId } from '../tasks/types.ts';
|
|
2
|
+
import { RegulatorPolicy } from './types.ts';
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
/**
|
|
5
|
+
* React context holding the shared, mutable regulator policy.
|
|
6
|
+
*/
|
|
7
|
+
export declare const Context: React.Context<RegulatorPolicy>;
|
|
8
|
+
/**
|
|
9
|
+
* Hook to access the regulator policy from the nearest `<Regulators>` provider.
|
|
10
|
+
*
|
|
11
|
+
* @returns The mutable `RegulatorPolicy` object from context.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useRegulators(): RegulatorPolicy;
|
|
14
|
+
/**
|
|
15
|
+
* Determines whether a given action is allowed under the current policy.
|
|
16
|
+
*
|
|
17
|
+
* @param action - The action identifier (symbol) to check.
|
|
18
|
+
* @param policy - The current regulator policy.
|
|
19
|
+
* @returns `true` if the action may proceed, `false` if it should be blocked.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isAllowed(action: ActionId, policy: RegulatorPolicy): boolean;
|
package/dist/chizu.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
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")}
|
|
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")}function l(e){const t=/* @__PURE__ */Symbol(`chizu.action.lifecycle/${e}`),n=function(e){return{[u.Action]:t,[u.Payload]:void 0,[u.Channel]:e,channel:e}};return Object.defineProperty(n,u.Action,{value:t,enumerable:!1}),Object.defineProperty(n,u.Payload,{value:void 0,enumerable:!1}),n}class f{static Mount(){return l("Mount")}static Unmount(){return l("Unmount")}static Error(){return l("Error")}static Update(){return l("Update")}static Node(){return l("Node")}}var d=/* @__PURE__ */(e=>(e.Unicast="unicast",e.Broadcast="broadcast",e.Multicast="multicast",e))(d||{}),h=/* @__PURE__ */(e=>(e.Mounting="mounting",e.Mounted="mounted",e.Unmounting="unmounting",e.Unmounted="unmounted",e))(h||{}),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 m extends Error{name="AbortError";constructor(e="Aborted"){super(e)}}class y extends Error{name="DisallowedError";constructor(e="Disallowed"){super(e)}}const b={actionPrefix:"chizu.action/",broadcastActionPrefix:"chizu.action/broadcast/",multicastActionPrefix:"chizu.action/multicast/",channelPrefix:"chizu.channel/",cachePrefix:"chizu.cache/",lifecyclePrefix:"chizu.action.lifecycle/"};function v(e,t){return new Promise((n,r)=>{if(t?.aborted)return void r(new m);const o=setTimeout(n,e);t?.addEventListener("abort",()=>{clearTimeout(o),r(new m)},{once:!0})})}async function w(e,t,n){if(t?.aborted)throw new m;for(;;){if(await n())return;await v(e,t)}}function g(e){return e?Boolean(e&&"symbol"!=typeof e):/* @__PURE__ */Symbol(`pk.${Date.now()}.${crypto.randomUUID()}`)}const x=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,config:b,pk:g,poll:w,sleep:v,"ζ":v,"κ":g,"π":w},Symbol.toStringTag,{value:"Module"})),P=e=>"symbol"==typeof e;function E(t){return e.isString(t)||P(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(b.broadcastActionPrefix);if(P(t))return t.description?.startsWith(b.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(b.broadcastActionPrefix)??!1}}return!1}function O(t){const n=E(t),r=e.isString(n)?n:n.description??"";return r.startsWith(b.actionPrefix)&&r.slice(r.lastIndexOf("/")+1)||"unknown"}function C(t){return e.isObject(t)&&u.Channel in t&&"channel"in t}function j(e){const t=E(e),n=P(t)?t.description??"":t;return n.startsWith(b.lifecyclePrefix)&&n.slice(b.lifecyclePrefix.length)||null}function A(t){if(e.isString(t))return t.startsWith(b.multicastActionPrefix);if(P(t))return t.description?.startsWith(b.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(b.multicastActionPrefix)??!1}}return!1}const M=(e,t=d.Unicast)=>{const n=t===d.Broadcast?/* @__PURE__ */Symbol(`${b.broadcastActionPrefix}${e}`):t===d.Multicast?/* @__PURE__ */Symbol(`${b.multicastActionPrefix}${e}`):/* @__PURE__ */Symbol(`${b.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===d.Broadcast&&Object.defineProperty(r,u.Broadcast,{value:!0,enumerable:!1}),t===d.Multicast&&Object.defineProperty(r,u.Multicast,{value:!0,enumerable:!1}),r};function k(){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 _(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 R(e){if(e instanceof Error){if("TimeoutError"===e.name)return p.Timedout;if("AbortError"===e.name)return p.Supplanted;if("DisallowedError"===e.name)return p.Disallowed}return p.Errored}function N(e){return e instanceof Error?e:new Error(String(e))}const U=o(void 0);function L({handler:e,children:t}){/* @__PURE__ */
|
|
2
|
+
return n(U.Provider,{value:e,children:t})}let z=(e=21)=>{let t="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)t+="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"[63&n[e]];return t};var $=/* @__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))($||{}),T=/* @__PURE__ */(e=>(e[e.Produce=0]="Produce",e[e.Hydrate=1]="Hydrate",e))(T||{}),D=/* @__PURE__ */(e=>(e.Property="property",e.Process="process",e.Value="value",e.Operation="operation",e))(D||{});class B{[i]=!0;static keys=new Set(Object.values(D));property=null;process=null;value;operation;constructor(e,t){this.value=e,this.operation=t}assign(e,t){const n=new B(this.value,this.operation);return n.property=e,n.process=t,n}}class F{static immer=(()=>{s();const e=new a;return e.setAutoFreeze(!1),e})();static tag="κ";static id=z}function W(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 H(t){if(e.isNullable(t)||V(t))return t;if(e.isArray(t))return t.map(e=>H(e));if(e.isObject(t)&&I(t)){const e=Object.entries(t).map(([e,t])=>[e,H(t)]);return{...Object.fromEntries(e),[F.tag]:t[F.tag]??F.id()}}return t}function G(e){if(Array.isArray(e))return e.filter(e=>F.tag in e).map(e=>e[F.tag]??"").join(",");const t=e[F.tag];if(t)return t;try{return JSON.stringify(e)}catch{return`[unserializable:${typeof e}]`}}function I(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}function V(t){return e.isNullable(t)||e.isString(t)||e.isNumber(t)||e.isBoolean(t)||"symbol"==typeof t||"bigint"==typeof t}function q(t,n,r,o,c,i){return function s(a,u=n.path){if(a instanceof B){const n=W(r,u.join("."));if(Object.entries(a).filter(([e,t])=>!B.keys.has(e)&&t instanceof B).forEach(([e,t])=>s(t,u.concat(e))),V(a.value)){if(t===T.Hydrate)return a.value;const s=u.slice(0,-1),l=s.length>0?W(r,s.join(".")):r;return e.isNullable(l)||J(l,a,u.at(-1),o,c,i),n??a.value}if(t===T.Hydrate){const e=H(s(a.value,u));return J(e,a,null,o,c,i),e}const l=n??H(a.value);return J(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)&&!I(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===T.Hydrate){const e=H(n);return Object.entries(a).forEach(([t,n])=>{n instanceof B&&V(n.value)&&J(e,n,t,o,c,i)}),e}return n}return a}(n.value)}function J(e,t,n,r,o,c){const i=c(e),s=o.get(i)??[];o.set(i,[t.assign(n,r),...s])}class K{#e={};#t;#n=/* @__PURE__ */new Map;#r=/* @__PURE__ */new Set;#o=!1;constructor(e=G){this.#t=e}static pk(){return z()}static"κ"=K.pk;annotate(e,t){return new B(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=W(n(),c),a=c.slice(0,-1),u=t.isNotEmpty(a)?W(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:W(n(),r),inspect:e(r)}):"is"===a?e=>s(r).some(t=>0!==(t.operation&e)):"draft"===a?()=>t.head(s(r))?.value??W(n(),r):"settled"===a?()=>new Promise(e=>{if(t.isEmpty(s(r)))return e(W(n(),r));const o=()=>{t.isEmpty(s(r))&&(i(o),e(W(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(T.Hydrate,()=>e)}produce(e){if(!this.#o)throw new Error("State must be hydrated using hydrate() before calling produce()");return this.#c(T.Produce,e)}#c(e,t){const n=/* @__PURE__ */Symbol("process"),[,r]=F.immer.produceWithPatches(this.#e,t);return this.#e=r.reduce((t,r)=>F.immer.applyPatches(t,[{...r,value:q(e,r,t,n,this.#n,this.#t)}]),this.#e),this.#e=H(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 K;function X(e,t){return Q.annotate(e,t)}function Y(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Z,ee={exports:{}};const te=/* @__PURE__ */Y((Z||(Z=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,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}(ee)),ee.exports));class ne extends te{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 re=r.createContext(new ne);function oe(){return r.useContext(re)}function ce({children:e}){const t=r.useMemo(()=>new ne,[]);/* @__PURE__ */
|
|
3
|
+
return n(re.Provider,{value:t,children:e})}const ie=r.createContext(/* @__PURE__ */new Map);function se({children:e}){const t=r.useMemo(()=>/* @__PURE__ */new Map,[]);/* @__PURE__ */
|
|
4
|
+
return n(ie.Provider,{value:t,children:e})}const ae=r.createContext(/* @__PURE__ */new Set);function ue({children:e}){const t=r.useMemo(()=>/* @__PURE__ */new Set,[]);/* @__PURE__ */
|
|
5
|
+
return n(ae.Provider,{value:t,children:e})}const le=r.createContext({mode:"allow-all",actions:/* @__PURE__ */new Set});function fe({children:e}){const t=r.useMemo(()=>({mode:"allow-all",actions:/* @__PURE__ */new Set}),[]);/* @__PURE__ */
|
|
6
|
+
return n(le.Provider,{value:t,children:e})}function de({children:e}){/* @__PURE__ */
|
|
7
|
+
return n(ce,{children:/* @__PURE__ */n(se,{children:/* @__PURE__ */n(fe,{children:/* @__PURE__ */n(ue,{children:e})})})})}const he=r.createContext(null);function pe(){return r.useContext(he)}function me(e,t){return e?.get(t)??null}function ye({name:e,children:t}){const o=pe(),c=r.useMemo(()=>({name:e,emitter:new ne}),[]),i=r.useMemo(()=>{const t=new Map(o??[]);return t.set(e,c),t},[o,e,c]);/* @__PURE__ */
|
|
8
|
+
return n(he.Provider,{value:i,children:t})}function be(e,t){const r=`Scoped${t.displayName||t.name||"Component"}`;return{[r]:r=>/* @__PURE__ */n(ye,{name:e,children:/* @__PURE__ */n(t,{...r})})}[r]}function ve(e){return(t,n)=>{t.actions.produce(t=>{t.model[e]=n})}}function we(e,t){for(const n of e.keys())if(j(n)===t)return n;return null}function ge(){const[,e]=r.useReducer(e=>e+1,0);return e}const xe=r.createContext(/* @__PURE__ */new Map);function Pe({action:t,renderer:n}){const o=oe(),c=r.useContext(xe),i=ge(),s=r.useMemo(()=>{const e=c.get(t);if(e)return e;const n={state:new K,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 Ee(...n){const o=e.isUndefined(n[0])||e.isFunction(n[0])?{}:n[0],i=e.isFunction(n[0])?n[0]:n[1]??(()=>({})),s=oe(),a=pe(),u=c(U),l=r.useContext(ae),f=r.useContext(ie),d=r.useContext(le),m=ge(),b=r.useRef(!1),v=r.useRef(null),w=r.useRef(new K);b.current||(b.current=!0,v.current=w.current.hydrate(o));const[g,x]=r.useState(()=>w.current.model),P=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()),j=r.useMemo(()=>new te,[]),M=r.useRef({handlers:/* @__PURE__ */new Map});M.current.handlers=/* @__PURE__ */new Map;const k=function(){const e=r.useRef(/* @__PURE__ */new Set),t=r.useRef(/* @__PURE__ */new Set);return r.useMemo(()=>({broadcast:e.current,multicast:t.current}),[])}(),L=r.useRef(h.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}),[])}(),$=r.useRef(/* @__PURE__ */new Set),T=r.useRef(0),D=r.useCallback((e,t,n)=>{const r=new AbortController,o={controller:r,action:e,payload:t};return l.add(o),$.current.add(o),{model:w.current.model,get phase(){return L.current},task:o,data:P,tasks:l,nodes:z.refs.current,regulator:{disallow(...e){if(d.actions.clear(),0===e.length)d.mode="disallow-all";else{d.mode="disallow-matching";for(const t of e)d.actions.add(E(t))}},allow(...e){if(d.actions.clear(),0===e.length)d.mode="allow-all";else{d.mode="allow-matching";for(const t of e)d.actions.add(E(t))}}},actions:{produce(e){if(r.signal.aborted)return;const t=w.current.produce(t=>e({model:t,inspect:w.current.inspect}));x(w.current.model),n.processes.add(t),v.current&&(n.processes.add(v.current),v.current=null)},dispatch(e,t,n){if(r.signal.aborted)return;const o=E(e),c=C(e)?e.channel:void 0;if(A(e)&&n?.scope){const e=me(a,n.scope);return void(e&&e.emitter.emit(o,t,c))}(S(e)?s:j).emit(o,t,c)},annotate:(e,t)=>w.current.annotate(e,t),async cacheable(e,t,n){if(r.signal.aborted)return{data:null};const o=_(e),c=f.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?(f.set(o,{value:i.value,expiry:Date.now()+t}),{data:i.value}):{data:null}},invalidate(e){f.delete(_(e))},async read(e,t){if(r.signal.aborted)return null;const n=E(e),o=A(e)&&t?.scope?me(a,t.scope)?.emitter??null:s;if(!o)return null;if(void 0===o.getCached(n))return null;const c=O(e),i="unknown"!==c?c[0].toLowerCase()+c.slice(1):null;if(i){const e=w.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=E(e),o=A(e)&&t?.scope?me(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){if(!function(e,t){switch(t.mode){case"allow-all":return!0;case"disallow-all":return!1;case"disallow-matching":return!t.actions.has(e);case"allow-matching":return t.actions.has(e)}}(t,d)){const e=we(M.current.handlers,"Error"),n=null!==e,r={reason:p.Disallowed,error:new y,action:O(t),handled:n,tasks:l};return u?.(r),void(n&&e&&j.emit(e,r))}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(),f=D(t,o,s);try{await n(f,o)}catch(h){const e=we(M.current.handlers,"Error"),n=null!==e,r={reason:R(h),error:N(h),action:O(t),handled:n,tasks:l};u?.(r),n&&e&&j.emit(e,r)}finally{for(const e of l)if(e===f.task){l.delete(e),$.current.delete(e);break}s.processes.forEach(e=>w.current.prune(e)),s.processes.size>0&&m(),a.resolve()}}}T.current++;const n=/* @__PURE__ */new Set;return M.current.handlers.forEach((e,r)=>{for(const{getChannel:o,handler:c}of e){const e=t(r,c,o);if(A(r)){if(a)for(const t of a.values()){const o=t.emitter;o.on(r,e),n.add(()=>o.off(r,e))}j.on(r,e),k.multicast.add(r),n.add(()=>j.off(r,e))}else S(r)?(s.on(r,e),j.on(r,e),k.broadcast.add(r),n.add(()=>{s.off(r,e),j.off(r,e)})):(j.on(r,e),n.add(()=>j.off(r,e)))}}),()=>{const e=++T.current,t=new Set(n);queueMicrotask(()=>{if(T.current!==e){for(const e of t)e();return}for(const e of $.current)e.controller.abort(),l.delete(e);$.current.clear(),L.current=h.Unmounting;const n=we(M.current.handlers,"Unmount");n&&j.emit(n),L.current=h.Unmounted;for(const e of t)e()})}},[j]),r.useLayoutEffect(()=>{const e=we(M.current.handlers,"Node");for(const[t,n]of z.pending.current)z.emitted.current.get(t)!==n&&(z.emitted.current.set(t,n),e&&j.emit(e,n,{Name:t}));z.pending.current.clear()}),function({unicast:n,broadcast:o,dispatchers:c,scope:i,phase:s,data:a,handlers:u}){const l=r.useRef(null);r.useLayoutEffect(()=>{if(s.current!==h.Mounting)return;const t=we(u,"Mount");t&&n.emit(t),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=h.Mounted},[]),r.useLayoutEffect(()=>{if(e.isNotNullable(l.current)){const e=function(e,t){return Object.keys(t).reduce((n,r)=>e[r]!==t[r]?{...n,[r]:t[r]}:n,{})}(l.current,a);if(t.isNotEmpty(Object.keys(e))){const t=we(u,"Update");t&&n.emit(t,e)}}l.current=a},[a,n])}({unicast:j,broadcast:s,dispatchers:k,scope:a,phase:L,data:i(),handlers:M.current.handlers});const B=r.useMemo(()=>[g,{dispatch(e,t,n){const r=E(e),o=C(e)?e.channel:void 0;if(A(e)&&n?.scope){const e=me(a,n.scope);return void(e&&e.emitter.emit(r,t,o))}(S(e)?s:j).emit(r,t,o)},get inspect(){return w.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(Pe,{action:E(e),renderer:t})}],[g,j]);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(()=>C(c.current)?c.current.channel:void 0,[]),a=E(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})}(M,e,t)},B}export{M as Action,de as Boundary,y as DisallowedError,d as Distribution,k as Entry,L as Error,f as Lifecycle,$ as Op,$ as Operation,p as Reason,fe as Regulators,ye as Scope,K as State,ve as With,X as annotate,Ee as useActions,x as utils,be 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")}function a(e){const t=Symbol(`chizu.action.lifecycle/${e}`),n=function(e){return{[s.Action]:t,[s.Payload]:void 0,[s.Channel]:e,channel:e}};return Object.defineProperty(n,s.Action,{value:t,enumerable:!1}),Object.defineProperty(n,s.Payload,{value:void 0,enumerable:!1}),n}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)}}class h extends Error{name="DisallowedError";constructor(e="Disallowed"){super(e)}}const p={actionPrefix:"chizu.action/",broadcastActionPrefix:"chizu.action/broadcast/",multicastActionPrefix:"chizu.action/multicast/",channelPrefix:"chizu.channel/",cachePrefix:"chizu.cache/",lifecyclePrefix:"chizu.action.lifecycle/"};function m(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 y(e,t,n){if(t?.aborted)throw new d;for(;;){if(await n())return;await m(e,t)}}function b(e){return e?Boolean(e&&"symbol"!=typeof e):Symbol(`pk.${Date.now()}.${crypto.randomUUID()}`)}const v=Object.freeze(Object.defineProperty({__proto__:null,config:p,pk:b,poll:y,sleep:m,"ζ":m,"κ":b,"π":y},Symbol.toStringTag,{value:"Module"})),g=e=>"symbol"==typeof e;function w(e){return t.G.isString(e)||g(e)?e:(t.G.isObject(e)||t.G.isFunction(e))&&s.Action in e?e[s.Action]:e}function x(e){if(t.G.isString(e))return e.startsWith(p.broadcastActionPrefix);if(g(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 j(e){const n=w(e),r=t.G.isString(n)?n:n.description??"";return r.startsWith(p.actionPrefix)&&r.slice(r.lastIndexOf("/")+1)||"unknown"}function P(e){return t.G.isObject(e)&&s.Channel in e&&"channel"in e}function S(e){const t=w(e),n=g(t)?t.description??"":t;return n.startsWith(p.lifecyclePrefix)&&n.slice(p.lifecyclePrefix.length)||null}function E(e){if(t.G.isString(e))return e.startsWith(p.multicastActionPrefix);if(g(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 A(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 O(e){if(e instanceof Error){if("TimeoutError"===e.name)return f.Timedout;if("AbortError"===e.name)return f.Supplanted;if("DisallowedError"===e.name)return f.Disallowed}return f.Errored}function C(e){return e instanceof Error?e:new Error(String(e))}const M=r.createContext(void 0);let k=(e=21)=>{let t="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)t+="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"[63&n[e]];return t};var G=(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))(G||{}),_=(e=>(e[e.Produce=0]="Produce",e[e.Hydrate=1]="Hydrate",e))(_||{}),R=(e=>(e.Property="property",e.Process="process",e.Value="value",e.Operation="operation",e))(R||{});class N{[o.immerable]=!0;static keys=new Set(Object.values(R));property=null;process=null;value;operation;constructor(e,t){this.value=e,this.operation=t}assign(e,t){const n=new N(this.value,this.operation);return n.property=e,n.process=t,n}}class U{static immer=(()=>{o.enablePatches();const e=new o.Immer;return e.setAutoFreeze(!1),e})();static tag="κ";static id=k}function L(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)||$(e))return e;if(t.G.isArray(e))return e.map(e=>z(e));if(t.G.isObject(e)&&D(e)){const t=Object.entries(e).map(([e,t])=>[e,z(t)]);return{...Object.fromEntries(t),[U.tag]:e[U.tag]??U.id()}}return e}function T(e){if(Array.isArray(e))return e.filter(e=>U.tag in e).map(e=>e[U.tag]??"").join(",");const t=e[U.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 $(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 B(e,n,r,o,c,i){return function s(a,u=n.path){if(a instanceof N){const n=L(r,u.join("."));if(Object.entries(a).filter(([e,t])=>!N.keys.has(e)&&t instanceof N).forEach(([e,t])=>s(t,u.concat(e))),$(a.value)){if(e===_.Hydrate)return a.value;const s=u.slice(0,-1),l=s.length>0?L(r,s.join(".")):r;return t.G.isNullable(l)||F(l,a,u.at(-1),o,c,i),n??a.value}if(e===_.Hydrate){const e=z(s(a.value,u));return F(e,a,null,o,c,i),e}const l=n??z(a.value);return F(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)&&!D(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===_.Hydrate){const e=z(n);return Object.entries(a).forEach(([t,n])=>{n instanceof N&&$(n.value)&&F(e,n,t,o,c,i)}),e}return n}return a}(n.value)}function F(e,t,n,r,o,c){const i=c(e),s=o.get(i)??[];o.set(i,[t.assign(n,r),...s])}class W{#e={};#t;#n=new Map;#r=new Set;#o=!1;constructor(e=T){this.#t=e}static pk(){return k()}static"κ"=W.pk;annotate(e,t){return new N(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=L(e(),o),s=o.slice(0,-1),a=t.A.isNotEmpty(s)?L(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:L(e(),r),inspect:n(r)}):"is"===a?e=>i(r).some(t=>0!==(t.operation&e)):"draft"===a?()=>t.A.head(i(r))?.value??L(e(),r):"settled"===a?()=>new Promise(n=>{if(t.A.isEmpty(i(r)))return n(L(e(),r));const s=()=>{t.A.isEmpty(i(r))&&(c(s),n(L(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(_.Hydrate,()=>e)}produce(e){if(!this.#o)throw new Error("State must be hydrated using hydrate() before calling produce()");return this.#c(_.Produce,e)}#c(e,t){const n=Symbol("process"),[,r]=U.immer.produceWithPatches(this.#e,t);return this.#e=r.reduce((t,r)=>U.immer.applyPatches(t,[{...r,value:B(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 H=new W;function I(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var q,V={exports:{}},J=(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=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}(V)),V.exports);const K=I(J);class Q extends K{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 X=i.createContext(new Q);function Y(){return i.useContext(X)}function Z({children:e}){const t=i.useMemo(()=>new Q,[]);return n.jsx(X.Provider,{value:t,children:e})}const ee=i.createContext(new Map);function te({children:e}){const t=i.useMemo(()=>new Map,[]);return n.jsx(ee.Provider,{value:t,children:e})}const ne=i.createContext(new Set);function re({children:e}){const t=i.useMemo(()=>new Set,[]);return n.jsx(ne.Provider,{value:t,children:e})}const oe=i.createContext({mode:"allow-all",actions:new Set});function ce({children:e}){const t=i.useMemo(()=>({mode:"allow-all",actions:new Set}),[]);return n.jsx(oe.Provider,{value:t,children:e})}const ie=i.createContext(null);function se(){return i.useContext(ie)}function ae(e,t){return e?.get(t)??null}function ue({name:e,children:t}){const r=se(),o=i.useMemo(()=>({name:e,emitter:new Q}),[]),c=i.useMemo(()=>{const t=new Map(r??[]);return t.set(e,o),t},[r,e,o]);return n.jsx(ie.Provider,{value:c,children:t})}function le(e,t){for(const n of e.keys())if(S(n)===t)return n;return null}function fe(){const[,e]=i.useReducer(e=>e+1,0);return e}const de=i.createContext(new Map);function he({action:e,renderer:n}){const r=Y(),o=i.useContext(de),c=fe(),s=i.useMemo(()=>{const t=o.get(e);if(t)return t;const n={state:new W,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(Z,{children:n.jsx(te,{children:n.jsx(ce,{children:n.jsx(re,{children:e})})})})},e.DisallowedError=h,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(M.Provider,{value:e,children:t})},e.Lifecycle=class{static Mount(){return a("Mount")}static Unmount(){return a("Unmount")}static Error(){return a("Error")}static Update(){return a("Update")}static Node(){return a("Node")}},e.Op=G,e.Operation=G,e.Reason=f,e.Regulators=ce,e.Scope=ue,e.State=W,e.With=function(e){return(t,n)=>{t.actions.produce(t=>{t.model[e]=n})}},e.annotate=function(e,t){return H.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=Y(),s=se(),a=r.useContext(M),u=i.useContext(ne),d=i.useContext(ee),p=i.useContext(oe),m=fe(),y=i.useRef(!1),b=i.useRef(null),v=i.useRef(new W);y.current||(y.current=!0,b.current=v.current.hydrate(n));const[g,S]=i.useState(()=>v.current.model),k=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()),G=i.useMemo(()=>new K,[]),_=i.useRef({handlers:new Map});_.current.handlers=new Map;const R=function(){const e=i.useRef(new Set),t=i.useRef(new Set);return i.useMemo(()=>({broadcast:e.current,multicast:t.current}),[])}(),N=i.useRef(l.Mounting),U=function(){const e=i.useRef({}),t=i.useRef(new Map),n=i.useRef(new Map);return i.useMemo(()=>({refs:e,pending:t,emitted:n}),[])}(),L=i.useRef(new Set),z=i.useRef(0),T=i.useCallback((e,t,n)=>{const r=new AbortController,o={controller:r,action:e,payload:t};return u.add(o),L.current.add(o),{model:v.current.model,get phase(){return N.current},task:o,data:k,tasks:u,nodes:U.refs.current,regulator:{disallow(...e){if(p.actions.clear(),0===e.length)p.mode="disallow-all";else{p.mode="disallow-matching";for(const t of e)p.actions.add(w(t))}},allow(...e){if(p.actions.clear(),0===e.length)p.mode="allow-all";else{p.mode="allow-matching";for(const t of e)p.actions.add(w(t))}}},actions:{produce(e){if(r.signal.aborted)return;const t=v.current.produce(t=>e({model:t,inspect:v.current.inspect}));S(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=w(e),i=P(e)?e.channel:void 0;if(E(e)&&n?.scope){const e=ae(s,n.scope);return void(e&&e.emitter.emit(o,t,i))}(x(e)?c:G).emit(o,t,i)},annotate:(e,t)=>v.current.annotate(e,t),async cacheable(e,t,n){if(r.signal.aborted)return{data:null};const o=A(e),c=d.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?(d.set(o,{value:i.value,expiry:Date.now()+t}),{data:i.value}):{data:null}},invalidate(e){d.delete(A(e))},async read(e,t){if(r.signal.aborted)return null;const n=w(e),o=E(e)&&t?.scope?ae(s,t.scope)?.emitter??null:c;if(!o)return null;if(void 0===o.getCached(n))return null;const i=j(e),a="unknown"!==i?i[0].toLowerCase()+i.slice(1):null;if(a){const e=v.current.inspect[a];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=w(e),o=E(e)&&t?.scope?ae(s,t.scope)?.emitter??null:c;return o?o.getCached(n)??null:null}}}},[g]);i.useLayoutEffect(()=>{function e(e,n,r){return async function(o,c){if(!function(e,t){switch(t.mode){case"allow-all":return!0;case"disallow-all":return!1;case"disallow-matching":return!t.actions.has(e);case"allow-matching":return t.actions.has(e)}}(e,p)){const t=le(_.current.handlers,"Error"),n=null!==t,r={reason:f.Disallowed,error:new h,action:j(e),handled:n,tasks:u};return a?.(r),void(n&&t&&G.emit(t,r))}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},l=Promise.withResolvers(),d=T(e,o,s);try{await n(d,o)}catch(y){const t=le(_.current.handlers,"Error"),n=null!==t,r={reason:O(y),error:C(y),action:j(e),handled:n,tasks:u};a?.(r),n&&t&&G.emit(t,r)}finally{for(const e of u)if(e===d.task){u.delete(e),L.current.delete(e);break}s.processes.forEach(e=>v.current.prune(e)),s.processes.size>0&&m(),l.resolve()}}}z.current++;const n=new Set;return _.current.handlers.forEach((t,r)=>{for(const{getChannel:o,handler:i}of t){const t=e(r,i,o);if(E(r)){if(s)for(const e of s.values()){const o=e.emitter;o.on(r,t),n.add(()=>o.off(r,t))}G.on(r,t),R.multicast.add(r),n.add(()=>G.off(r,t))}else x(r)?(c.on(r,t),G.on(r,t),R.broadcast.add(r),n.add(()=>{c.off(r,t),G.off(r,t)})):(G.on(r,t),n.add(()=>G.off(r,t)))}}),()=>{const e=++z.current,t=new Set(n);queueMicrotask(()=>{if(z.current!==e){for(const e of t)e();return}for(const e of L.current)e.controller.abort(),u.delete(e);L.current.clear(),N.current=l.Unmounting;const n=le(_.current.handlers,"Unmount");n&&G.emit(n),N.current=l.Unmounted;for(const e of t)e()})}},[G]),i.useLayoutEffect(()=>{const e=le(_.current.handlers,"Node");for(const[t,n]of U.pending.current)U.emitted.current.get(t)!==n&&(U.emitted.current.set(t,n),e&&G.emit(e,n,{Name:t}));U.pending.current.clear()}),function({unicast:e,broadcast:n,dispatchers:r,scope:o,phase:c,data:s,handlers:a}){const u=i.useRef(null);i.useLayoutEffect(()=>{if(c.current!==l.Mounting)return;const i=le(a,"Mount");i&&e.emit(i),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);if(t.A.isNotEmpty(Object.keys(n))){const t=le(a,"Update");t&&e.emit(t,n)}}u.current=s},[s,e])}({unicast:G,broadcast:c,dispatchers:R,scope:s,phase:N,data:o(),handlers:_.current.handlers});const D=i.useMemo(()=>[g,{dispatch(e,t,n){const r=w(e),o=P(e)?e.channel:void 0;if(E(e)&&n?.scope){const e=ae(s,n.scope);return void(e&&e.emitter.emit(r,t,o))}(x(e)?c:G).emit(r,t,o)},get inspect(){return v.current.inspect},get nodes(){return U.refs.current},node(e,t){U.refs.current[e]=t,U.pending.current.set(e,t)},stream:(e,t)=>i.createElement(he,{action:w(e),renderer:t})}],[g,G]);return D.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(()=>P(o.current)?o.current.channel:void 0,[]),a=w(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,t)},D},e.utils=v,e.withScope=function(e,t){const r=`Scoped${t.displayName||t.name||"Component"}`;return{[r]:r=>n.jsx(ue,{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/error/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Props } from './types';
|
|
2
2
|
export { useError } from './utils';
|
|
3
|
-
export { Reason, AbortError, TimeoutError } from './types';
|
|
3
|
+
export { Reason, AbortError, TimeoutError, DisallowedError } from './types';
|
|
4
4
|
export type { Fault, Catcher } from './types';
|
|
5
5
|
/**
|
|
6
6
|
* Error boundary component for catching and handling errors from actions.
|
package/dist/error/types.d.ts
CHANGED
|
@@ -42,6 +42,19 @@ export declare class TimeoutError extends Error {
|
|
|
42
42
|
name: string;
|
|
43
43
|
constructor(message?: string);
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Error thrown when an action is blocked by the regulator policy.
|
|
47
|
+
* Works across all platforms including React Native where `DOMException` is unavailable.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* throw new DisallowedError("Action blocked by regulator");
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare class DisallowedError extends Error {
|
|
55
|
+
name: string;
|
|
56
|
+
constructor(message?: string);
|
|
57
|
+
}
|
|
45
58
|
/**
|
|
46
59
|
* Details about an error that occurred during action execution.
|
|
47
60
|
* @template E Custom error types to include in the union with Error.
|
|
@@ -53,7 +66,7 @@ export type Fault<E extends Error = never> = {
|
|
|
53
66
|
error: Error | E;
|
|
54
67
|
/** The name of the action that caused the error (e.g., "Increment"). */
|
|
55
68
|
action: string;
|
|
56
|
-
/** Whether the component has a `Lifecycle.Error` handler registered. */
|
|
69
|
+
/** Whether the component has a `Lifecycle.Error()` handler registered. */
|
|
57
70
|
handled: boolean;
|
|
58
71
|
/**
|
|
59
72
|
* All currently running tasks across the application.
|
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,33 @@ 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;
|
|
86
|
+
/** Handler registry for lifecycle action discovery */
|
|
87
|
+
handlers: Map<ActionId, Set<unknown>>;
|
|
68
88
|
};
|
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, handlers, }: 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,
|
|
@@ -69,16 +69,24 @@ export declare function useData<P extends Props>(props: P): P;
|
|
|
69
69
|
* ```
|
|
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
|
-
export { isChanneledAction, getActionSymbol };
|
|
73
72
|
/**
|
|
74
|
-
*
|
|
73
|
+
* Scans a handler registry for a lifecycle action of the given type.
|
|
74
|
+
*
|
|
75
|
+
* When lifecycle actions become per-class instances (via `Lifecycle.Mount()`),
|
|
76
|
+
* each Actions class has its own unique symbol. Emission sites can no longer
|
|
77
|
+
* emit to a shared singleton — they must discover the component's lifecycle
|
|
78
|
+
* action by scanning the registry keys for matching lifecycle prefixes.
|
|
79
|
+
*
|
|
80
|
+
* Handler maps typically contain 5–15 entries, so the O(n) scan is trivial.
|
|
81
|
+
*
|
|
82
|
+
* @param handlers The handler map from a component's scope.
|
|
83
|
+
* @param type The lifecycle type to find (e.g. `"Mount"`, `"Unmount"`, `"Error"`).
|
|
84
|
+
* @returns The matching ActionId, or `null` if no lifecycle action of that type is registered.
|
|
85
|
+
*
|
|
86
|
+
* @internal
|
|
75
87
|
*/
|
|
76
|
-
export type
|
|
77
|
-
|
|
78
|
-
broadcast: Set<ActionId>;
|
|
79
|
-
/** Set of registered multicast action IDs */
|
|
80
|
-
multicast: Set<ActionId>;
|
|
81
|
-
};
|
|
88
|
+
export declare function findLifecycleAction(handlers: Map<ActionId, Set<unknown>>, type: string): ActionId | null;
|
|
89
|
+
export { isChanneledAction, getActionSymbol };
|
|
82
90
|
/**
|
|
83
91
|
* Manages sets of broadcast and multicast action IDs.
|
|
84
92
|
*
|
|
@@ -91,7 +99,7 @@ export type ActionSets = {
|
|
|
91
99
|
*
|
|
92
100
|
* @example
|
|
93
101
|
* ```ts
|
|
94
|
-
* const actions =
|
|
102
|
+
* const actions = useDispatchers();
|
|
95
103
|
*
|
|
96
104
|
* // Register a broadcast action
|
|
97
105
|
* actions.broadcast.add(getActionSymbol(MyBroadcastAction));
|
|
@@ -104,7 +112,7 @@ export type ActionSets = {
|
|
|
104
112
|
*
|
|
105
113
|
* @internal
|
|
106
114
|
*/
|
|
107
|
-
export declare function
|
|
115
|
+
export declare function useDispatchers(): Dispatchers;
|
|
108
116
|
/**
|
|
109
117
|
* Registers an action handler within a component's scope.
|
|
110
118
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
export { Action } from './action/index.ts';
|
|
2
2
|
export { Entry } from './cache/index.ts';
|
|
3
3
|
export { Distribution, Lifecycle } from './types/index.ts';
|
|
4
|
-
export { Error, Reason } from './error/index.tsx';
|
|
4
|
+
export { Error, Reason, DisallowedError } from './error/index.tsx';
|
|
5
5
|
export { Operation, Op, State } from 'immertation';
|
|
6
6
|
export { annotate } from './annotate/index.ts';
|
|
7
7
|
export { Boundary } from './boundary/index.tsx';
|
|
8
|
+
export { Regulators } from './boundary/components/regulators/index.tsx';
|
|
8
9
|
export { Scope, withScope } from './boundary/components/scope/index.tsx';
|
|
9
10
|
export { useActions, With } from './hooks/index.ts';
|
|
10
11
|
export * as utils from './utils/index.ts';
|
|
11
12
|
export type { Box } from 'immertation';
|
|
12
13
|
export type { Fault, Catcher } from './error/index.tsx';
|
|
13
14
|
export type { Pk, Task, Tasks, Handlers } from './types/index.ts';
|
|
15
|
+
export type { Regulator } from './boundary/components/regulators/index.tsx';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ 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 { Regulator } from '../boundary/components/regulators/types.ts';
|
|
6
|
+
import { Fault } from '../error/types.ts';
|
|
7
|
+
import * as React from "react";
|
|
5
8
|
export type { ActionId, Box, Task, Tasks };
|
|
6
9
|
/**
|
|
7
10
|
* Type for objects with a Brand.Action symbol property.
|
|
@@ -93,49 +96,59 @@ export type ChanneledCacheId<T = unknown, C = unknown> = {
|
|
|
93
96
|
readonly channel: C;
|
|
94
97
|
};
|
|
95
98
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
99
|
+
* Factory functions for lifecycle actions.
|
|
100
|
+
*
|
|
101
|
+
* Each call returns a **unique** action symbol, enabling per-component
|
|
102
|
+
* regulation. Assign the result as a static property in your Actions class:
|
|
98
103
|
*
|
|
99
104
|
* @example
|
|
100
105
|
* ```ts
|
|
101
|
-
* class {
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
106
|
+
* export class Actions {
|
|
107
|
+
* static Mount = Lifecycle.Mount();
|
|
108
|
+
* static Unmount = Lifecycle.Unmount();
|
|
109
|
+
* static Error = Lifecycle.Error();
|
|
110
|
+
* static Update = Lifecycle.Update();
|
|
111
|
+
* static Node = Lifecycle.Node();
|
|
112
|
+
*
|
|
113
|
+
* static Increment = Action("Increment");
|
|
105
114
|
* }
|
|
115
|
+
*
|
|
116
|
+
* // Now regulating Lifecycle.Mount only blocks THIS component's mount:
|
|
117
|
+
* context.regulator.disallow(Actions.Mount);
|
|
106
118
|
* ```
|
|
107
119
|
*/
|
|
108
120
|
export declare class Lifecycle {
|
|
109
|
-
/** Triggered once
|
|
110
|
-
static
|
|
111
|
-
/** Triggered when the component unmounts. */
|
|
112
|
-
static
|
|
113
|
-
/** Triggered when an action throws
|
|
114
|
-
static
|
|
115
|
-
/** Triggered when `context.data`
|
|
116
|
-
static
|
|
121
|
+
/** Creates a Mount lifecycle action. Triggered once on component mount (`useLayoutEffect`). */
|
|
122
|
+
static Mount(): HandlerPayload<never>;
|
|
123
|
+
/** Creates an Unmount lifecycle action. Triggered when the component unmounts. */
|
|
124
|
+
static Unmount(): HandlerPayload<never>;
|
|
125
|
+
/** Creates an Error lifecycle action. Triggered when an action throws. Receives `Fault` as payload. */
|
|
126
|
+
static Error(): HandlerPayload<Fault>;
|
|
127
|
+
/** Creates an Update lifecycle action. Triggered when `context.data` changes (not on initial mount). */
|
|
128
|
+
static Update(): HandlerPayload<Record<string, unknown>>;
|
|
117
129
|
/**
|
|
118
|
-
* Triggered when a node is captured
|
|
119
|
-
* Supports channeled subscriptions by
|
|
120
|
-
*
|
|
121
|
-
* The payload is the captured node (or `null` when released).
|
|
130
|
+
* Creates a Node lifecycle action. Triggered when a DOM node is captured
|
|
131
|
+
* or released via `actions.node()`. Supports channeled subscriptions by
|
|
132
|
+
* node name.
|
|
122
133
|
*
|
|
123
134
|
* @example
|
|
124
135
|
* ```ts
|
|
136
|
+
* export class Actions {
|
|
137
|
+
* static Node = Lifecycle.Node();
|
|
138
|
+
* }
|
|
139
|
+
*
|
|
125
140
|
* // Subscribe to ALL node changes
|
|
126
|
-
* actions.useAction(
|
|
141
|
+
* actions.useAction(Actions.Node, (context, node) => {
|
|
127
142
|
* console.log("Node changed:", node);
|
|
128
143
|
* });
|
|
129
144
|
*
|
|
130
145
|
* // Subscribe to a specific node by name (channeled)
|
|
131
|
-
* actions.useAction(
|
|
132
|
-
* if (node)
|
|
133
|
-
* node.focus();
|
|
134
|
-
* }
|
|
146
|
+
* actions.useAction(Actions.Node({ Name: "input" }), (context, node) => {
|
|
147
|
+
* if (node) node.focus();
|
|
135
148
|
* });
|
|
136
149
|
* ```
|
|
137
150
|
*/
|
|
138
|
-
static Node: HandlerPayload<unknown, {
|
|
151
|
+
static Node(): HandlerPayload<unknown, {
|
|
139
152
|
Name: string;
|
|
140
153
|
}>;
|
|
141
154
|
}
|
|
@@ -539,6 +552,26 @@ export type HandlerContext<M extends Model | void, _AC extends Actions | void, D
|
|
|
539
552
|
readonly nodes: {
|
|
540
553
|
[K in keyof Nodes<M>]: Nodes<M>[K] | null;
|
|
541
554
|
};
|
|
555
|
+
/**
|
|
556
|
+
* The regulator API for controlling which actions may be dispatched.
|
|
557
|
+
*
|
|
558
|
+
* Each call replaces the previous policy entirely (last-write-wins).
|
|
559
|
+
* The policy is shared across all components within the same `<Boundary>`.
|
|
560
|
+
*
|
|
561
|
+
* @example
|
|
562
|
+
* ```ts
|
|
563
|
+
* actions.useAction(Actions.Mount, (context) => {
|
|
564
|
+
* // Block all actions except Critical
|
|
565
|
+
* context.regulator.allow(Actions.Critical);
|
|
566
|
+
* });
|
|
567
|
+
*
|
|
568
|
+
* actions.useAction(Actions.Unlock, (context) => {
|
|
569
|
+
* // Re-allow all actions
|
|
570
|
+
* context.regulator.allow();
|
|
571
|
+
* });
|
|
572
|
+
* ```
|
|
573
|
+
*/
|
|
574
|
+
readonly regulator: Regulator;
|
|
542
575
|
readonly actions: {
|
|
543
576
|
produce<F extends (draft: {
|
|
544
577
|
model: M;
|
|
@@ -586,7 +619,7 @@ export type HandlerContext<M extends Model | void, _AC extends Actions | void, D
|
|
|
586
619
|
*/
|
|
587
620
|
invalidate(entry: CacheId<unknown> | ChanneledCacheId<unknown>): void;
|
|
588
621
|
/**
|
|
589
|
-
* Reads the latest broadcast or multicast value, waiting for
|
|
622
|
+
* Reads the latest broadcast or multicast value, waiting for annotations to settle.
|
|
590
623
|
*
|
|
591
624
|
* If a value has already been dispatched it resolves immediately.
|
|
592
625
|
* Otherwise it waits until the next dispatch of the action.
|
|
@@ -610,6 +643,26 @@ export type HandlerContext<M extends Model | void, _AC extends Actions | void, D
|
|
|
610
643
|
*/
|
|
611
644
|
read<T>(action: BroadcastPayload<T>): Promise<T | null>;
|
|
612
645
|
read<T>(action: MulticastPayload<T>, options: MulticastOptions): Promise<T | null>;
|
|
646
|
+
/**
|
|
647
|
+
* Returns the latest broadcast or multicast value immediately without
|
|
648
|
+
* waiting for annotations to settle. Use this when you need the current
|
|
649
|
+
* cached value and do not need to wait for pending operations to complete.
|
|
650
|
+
*
|
|
651
|
+
* @param action - The broadcast or multicast action to peek at.
|
|
652
|
+
* @param options - For multicast actions, must include `{ scope: "ScopeName" }`.
|
|
653
|
+
* @returns The cached value, or `null` if no value has been dispatched.
|
|
654
|
+
*
|
|
655
|
+
* @example
|
|
656
|
+
* ```ts
|
|
657
|
+
* actions.useAction(Actions.Check, (context) => {
|
|
658
|
+
* const user = context.actions.peek(Actions.Broadcast.User);
|
|
659
|
+
* if (!user) return;
|
|
660
|
+
* console.log(user.name);
|
|
661
|
+
* });
|
|
662
|
+
* ```
|
|
663
|
+
*/
|
|
664
|
+
peek<T>(action: BroadcastPayload<T>): T | null;
|
|
665
|
+
peek<T>(action: MulticastPayload<T>, options: MulticastOptions): T | null;
|
|
613
666
|
};
|
|
614
667
|
};
|
|
615
668
|
/**
|
|
@@ -694,11 +747,6 @@ type OwnKeys<AC> = Exclude<keyof AC & string, "prototype">;
|
|
|
694
747
|
export type Handlers<M extends Model | void, AC extends Actions | void, D extends Props = Props> = {
|
|
695
748
|
[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
749
|
};
|
|
697
|
-
/**
|
|
698
|
-
* Union of action types accepted by `derive` configuration entries.
|
|
699
|
-
* @internal
|
|
700
|
-
*/
|
|
701
|
-
type DerivedAction = HandlerPayload<any> | ChanneledAction<any, any>;
|
|
702
750
|
export type UseActions<M extends Model | void, AC extends Actions | void, D extends Props = Props> = [
|
|
703
751
|
Readonly<M>,
|
|
704
752
|
{
|
|
@@ -765,6 +813,29 @@ export type UseActions<M extends Model | void, AC extends Actions | void, D exte
|
|
|
765
813
|
* ```
|
|
766
814
|
*/
|
|
767
815
|
node<K extends keyof Nodes<M>>(name: K, node: Nodes<M>[K] | null): void;
|
|
816
|
+
/**
|
|
817
|
+
* Streams broadcast values declaratively in JSX using a render-prop pattern.
|
|
818
|
+
*
|
|
819
|
+
* Subscribes to the given broadcast action and re-renders when a new value
|
|
820
|
+
* is dispatched. Returns `null` until the first dispatch. The renderer
|
|
821
|
+
* receives the value and an inspect proxy for annotation tracking.
|
|
822
|
+
*
|
|
823
|
+
* @param action - The broadcast action to subscribe to.
|
|
824
|
+
* @param renderer - Callback that receives value and inspect, returns React nodes.
|
|
825
|
+
* @returns React nodes from the renderer, or null if no value has been dispatched.
|
|
826
|
+
*
|
|
827
|
+
* @example
|
|
828
|
+
* ```tsx
|
|
829
|
+
* return (
|
|
830
|
+
* <div>
|
|
831
|
+
* {actions.stream(Actions.Broadcast.User, (user, inspect) => (
|
|
832
|
+
* <span>{user.name}</span>
|
|
833
|
+
* ))}
|
|
834
|
+
* </div>
|
|
835
|
+
* );
|
|
836
|
+
* ```
|
|
837
|
+
*/
|
|
838
|
+
stream<T extends object>(action: BroadcastPayload<T>, renderer: (value: T, inspect: Inspect<T>) => React.ReactNode): React.ReactNode;
|
|
768
839
|
}
|
|
769
840
|
] & {
|
|
770
841
|
/**
|
|
@@ -794,37 +865,4 @@ export type UseActions<M extends Model | void, AC extends Actions | void, D exte
|
|
|
794
865
|
* ```
|
|
795
866
|
*/
|
|
796
867
|
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
868
|
};
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -13,19 +13,35 @@ export declare const config: {
|
|
|
13
13
|
channelPrefix: string;
|
|
14
14
|
/** Prefix for cache operation symbols. */
|
|
15
15
|
cachePrefix: string;
|
|
16
|
+
/** Prefix for lifecycle action symbols. */
|
|
17
|
+
lifecyclePrefix: string;
|
|
16
18
|
};
|
|
17
19
|
/**
|
|
18
20
|
* Returns a promise that resolves after the specified number of milliseconds.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
+
* The sleep will reject with an AbortError when the signal is aborted,
|
|
22
|
+
* allowing cleanup of pending operations.
|
|
21
23
|
*
|
|
22
24
|
* @param ms The number of milliseconds to sleep.
|
|
23
|
-
* @param signal
|
|
25
|
+
* @param signal AbortSignal to cancel the sleep early.
|
|
24
26
|
* @returns A promise that resolves after the delay or rejects if aborted.
|
|
25
27
|
*/
|
|
26
|
-
export declare function sleep(ms: number, signal
|
|
28
|
+
export declare function sleep(ms: number, signal: AbortSignal | undefined): Promise<void>;
|
|
27
29
|
/** Shorthand alias for {@link sleep}. */
|
|
28
30
|
export declare const ζ: typeof sleep;
|
|
31
|
+
/**
|
|
32
|
+
* Repeatedly calls a function at a fixed interval until it returns `true` or
|
|
33
|
+
* the signal is aborted. The function is invoked immediately on the first
|
|
34
|
+
* iteration, then after each interval.
|
|
35
|
+
*
|
|
36
|
+
* @param ms The interval in milliseconds between invocations.
|
|
37
|
+
* @param signal Optional AbortSignal to cancel polling early.
|
|
38
|
+
* @param fn Callback invoked each iteration. Return `true` to stop polling.
|
|
39
|
+
* @returns A promise that resolves when `fn` returns `true`, or rejects with
|
|
40
|
+
* an AbortError if the signal is aborted.
|
|
41
|
+
*/
|
|
42
|
+
export declare function poll(ms: number, signal: AbortSignal | undefined, fn: () => boolean | Promise<boolean>): Promise<void>;
|
|
43
|
+
/** Shorthand alias for {@link poll}. */
|
|
44
|
+
export declare const π: typeof poll;
|
|
29
45
|
/**
|
|
30
46
|
* Generates a unique primary key.
|
|
31
47
|
* @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.70",
|
|
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
|
}
|