chizu 0.2.46 → 0.2.49
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 +54 -8
- package/dist/action/index.d.ts +7 -65
- package/dist/action/utils.d.ts +68 -0
- package/dist/boundary/components/scope/index.d.ts +55 -0
- package/dist/boundary/components/scope/partition.d.ts +32 -0
- package/dist/boundary/components/scope/types.d.ts +34 -0
- package/dist/boundary/components/scope/utils.d.ts +22 -0
- package/dist/chizu.js +7 -6
- package/dist/chizu.umd.cjs +1 -1
- package/dist/error/types.d.ts +22 -0
- package/dist/hooks/types.d.ts +18 -2
- package/dist/hooks/utils.d.ts +83 -33
- package/dist/index.d.ts +2 -1
- package/dist/types/index.d.ts +250 -90
- package/dist/utils/index.d.ts +4 -2
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ For advanced topics, see the [recipes directory](./recipes/).
|
|
|
24
24
|
- No stale closures – `context.data` stays current after `await`.
|
|
25
25
|
- No need to lift state – siblings communicate via events.
|
|
26
26
|
- Reduces context proliferation – events replace many contexts.
|
|
27
|
-
- No need to memoize callbacks – handlers are stable
|
|
27
|
+
- No need to memoize callbacks – handlers are stable references with fresh closure access.
|
|
28
28
|
- Clear separation between business logic and markup.
|
|
29
29
|
- Complements [Feature Slice Design](https://feature-sliced.design/) architecture.
|
|
30
30
|
- Strongly typed dispatches, models, payloads, etc.
|
|
@@ -113,14 +113,15 @@ actions.useAction(Actions.Search, async (context) => {
|
|
|
113
113
|
|
|
114
114
|
For more details, see the [referential equality recipe](./recipes/referential-equality.md).
|
|
115
115
|
|
|
116
|
-
Each action should be responsible for managing its own data – in this case our `Profile` action handles fetching the user but other components may want to consume it – for that we should use a
|
|
116
|
+
Each action should be responsible for managing its own data – in this case our `Profile` action handles fetching the user but other components may want to consume it – for that we should use a broadcast action:
|
|
117
117
|
|
|
118
118
|
```tsx
|
|
119
|
-
class
|
|
119
|
+
class BroadcastActions {
|
|
120
120
|
static Name = Action<string>("Name", Distribution.Broadcast);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
class Actions
|
|
123
|
+
class Actions {
|
|
124
|
+
static Broadcast = BroadcastActions;
|
|
124
125
|
static Profile = Action<string>("Profile");
|
|
125
126
|
}
|
|
126
127
|
```
|
|
@@ -137,18 +138,18 @@ actions.useAction(Actions.Profile, async (context) => {
|
|
|
137
138
|
draft.model.name = name;
|
|
138
139
|
});
|
|
139
140
|
|
|
140
|
-
context.actions.dispatch(Actions.Name, name);
|
|
141
|
+
context.actions.dispatch(Actions.Broadcast.Name, name);
|
|
141
142
|
});
|
|
142
143
|
```
|
|
143
144
|
|
|
144
|
-
Once we have the
|
|
145
|
+
Once we have the broadcast action if we simply want to read the `name` when it's updated we can use consume:
|
|
145
146
|
|
|
146
147
|
```tsx
|
|
147
148
|
export default function Subscriptions(): React.ReactElement {
|
|
148
149
|
return (
|
|
149
150
|
<>
|
|
150
151
|
Manage your subscriptions for your{" "}
|
|
151
|
-
{actions.consume(Actions.Name, (name) => name.value)} account.
|
|
152
|
+
{actions.consume(Actions.Broadcast.Name, (name) => name.value)} account.
|
|
152
153
|
</>
|
|
153
154
|
);
|
|
154
155
|
}
|
|
@@ -157,7 +158,7 @@ export default function Subscriptions(): React.ReactElement {
|
|
|
157
158
|
However if we want to listen for it and perform another operation in our local component we can do that via `useAction`:
|
|
158
159
|
|
|
159
160
|
```tsx
|
|
160
|
-
actions.useAction(Actions.Name, async (context, name) => {
|
|
161
|
+
actions.useAction(Actions.Broadcast.Name, async (context, name) => {
|
|
161
162
|
const friends = await fetch(api.friends(name));
|
|
162
163
|
|
|
163
164
|
context.actions.produce((draft) => {
|
|
@@ -201,3 +202,48 @@ actions.dispatch(Actions.UserUpdated, user);
|
|
|
201
202
|
```
|
|
202
203
|
|
|
203
204
|
Channel values support non-nullable primitives: `string`, `number`, `boolean`, or `symbol`. By convention, use uppercase keys like `{UserId: 4}` to distinguish channel keys from payload properties.
|
|
205
|
+
|
|
206
|
+
For scoped communication between component groups, use multicast actions with the `<Scope>` component:
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
import { Action, Distribution, Scope } from "chizu";
|
|
210
|
+
|
|
211
|
+
// Shared multicast actions
|
|
212
|
+
class MulticastActions {
|
|
213
|
+
static Update = Action<number>("Update", Distribution.Multicast);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Component-level actions reference shared multicast
|
|
217
|
+
class Actions {
|
|
218
|
+
static Multicast = MulticastActions;
|
|
219
|
+
static Increment = Action("Increment");
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function App() {
|
|
223
|
+
return (
|
|
224
|
+
<>
|
|
225
|
+
<Scope name="TeamA">
|
|
226
|
+
<ScoreBoard />
|
|
227
|
+
<PlayerList />
|
|
228
|
+
</Scope>
|
|
229
|
+
|
|
230
|
+
<Scope name="TeamB">
|
|
231
|
+
<ScoreBoard />
|
|
232
|
+
<PlayerList />
|
|
233
|
+
</Scope>
|
|
234
|
+
</>
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Dispatch to all components within "TeamA" scope
|
|
239
|
+
actions.dispatch(Actions.Multicast.Update, 42, { scope: "TeamA" });
|
|
240
|
+
|
|
241
|
+
// Consume with scope
|
|
242
|
+
{
|
|
243
|
+
actions.consume(Actions.Multicast.Update, (box) => box.value, {
|
|
244
|
+
scope: "TeamA",
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Unlike broadcast which reaches all components, multicast is scoped to the named boundary – perfect for isolated widget groups, form sections, or distinct UI regions. See the [multicast recipe](./recipes/multicast-actions.md) for more details.
|
package/dist/action/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { HandlerPayload,
|
|
2
|
-
|
|
1
|
+
import { HandlerPayload, BroadcastPayload, MulticastPayload, Distribution, Filter } from '../types/index.ts';
|
|
2
|
+
export { getActionSymbol, isBroadcastAction, isMulticastAction, getName, isChanneledAction, } from './utils.ts';
|
|
3
3
|
/**
|
|
4
4
|
* Interface for the Action factory function.
|
|
5
5
|
*/
|
|
@@ -17,12 +17,13 @@ type ActionFactory = {
|
|
|
17
17
|
* @template P The payload type for the action.
|
|
18
18
|
* @template C The channel type for channeled dispatches (defaults to never).
|
|
19
19
|
* @param name The action name, used for debugging purposes.
|
|
20
|
-
* @param distribution The distribution mode (Unicast or
|
|
21
|
-
* @returns A typed action object (
|
|
20
|
+
* @param distribution The distribution mode (Unicast, Broadcast, or Multicast).
|
|
21
|
+
* @returns A typed action object (BroadcastPayload if Broadcast, MulticastPayload if Multicast).
|
|
22
22
|
*/
|
|
23
|
-
<P = never, C extends Filter = never>(name: string, distribution: Distribution.Broadcast):
|
|
23
|
+
<P = never, C extends Filter = never>(name: string, distribution: Distribution.Broadcast): BroadcastPayload<P, C>;
|
|
24
|
+
<P = never, C extends Filter = never>(name: string, distribution: Distribution.Multicast): MulticastPayload<P, C>;
|
|
24
25
|
<P = never, C extends Filter = never>(name: string, distribution: Distribution.Unicast): HandlerPayload<P, C>;
|
|
25
|
-
<P = never, C extends Filter = never>(name: string, distribution: Distribution): HandlerPayload<P, C> |
|
|
26
|
+
<P = never, C extends Filter = never>(name: string, distribution: Distribution): HandlerPayload<P, C> | BroadcastPayload<P, C> | MulticastPayload<P, C>;
|
|
26
27
|
};
|
|
27
28
|
/**
|
|
28
29
|
* Creates a new action with a given payload type, optional channel type, and optional distribution mode.
|
|
@@ -63,62 +64,3 @@ type ActionFactory = {
|
|
|
63
64
|
* ```
|
|
64
65
|
*/
|
|
65
66
|
export declare const Action: ActionFactory;
|
|
66
|
-
/**
|
|
67
|
-
* Extracts the underlying symbol from an action or channeled action.
|
|
68
|
-
* This symbol is used as the event emitter key for dispatching.
|
|
69
|
-
*
|
|
70
|
-
* @param action The action or channeled action to extract the symbol from.
|
|
71
|
-
* @returns The underlying symbol, or the action itself if it's already a symbol/string.
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```typescript
|
|
75
|
-
* const Increment = Action<number>("Increment");
|
|
76
|
-
* getActionSymbol(Increment); // Symbol(chizu.action/Increment)
|
|
77
|
-
* getActionSymbol(Increment({ UserId: 5 })); // Symbol(chizu.action/Increment)
|
|
78
|
-
* ```
|
|
79
|
-
*/
|
|
80
|
-
export declare function getActionSymbol(action: ActionId | object): ActionId;
|
|
81
|
-
/**
|
|
82
|
-
* Checks whether an action is a distributed action.
|
|
83
|
-
* Distributed actions are broadcast to all mounted components that have defined a handler for them.
|
|
84
|
-
*
|
|
85
|
-
* @param action The action to check.
|
|
86
|
-
* @returns True if the action is a distributed action, false otherwise.
|
|
87
|
-
*/
|
|
88
|
-
export declare function isDistributedAction(action: ActionId | object): boolean;
|
|
89
|
-
/**
|
|
90
|
-
* Extracts the action name from an action.
|
|
91
|
-
*
|
|
92
|
-
* Parses both regular actions (`chizu.action/Name`) and
|
|
93
|
-
* distributed actions (`chizu.action/distributed/Name`)
|
|
94
|
-
* to extract just the name portion.
|
|
95
|
-
*
|
|
96
|
-
* @param action The action to extract the name from.
|
|
97
|
-
* @returns The extracted action name, or "unknown" if parsing fails.
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* ```typescript
|
|
101
|
-
* const Increment = Action("Increment");
|
|
102
|
-
* getName(Increment); // "Increment"
|
|
103
|
-
*
|
|
104
|
-
* const SignedOut = Action("SignedOut", Distribution.Broadcast);
|
|
105
|
-
* getName(SignedOut); // "SignedOut"
|
|
106
|
-
* ```
|
|
107
|
-
*/
|
|
108
|
-
export declare function getName(action: ActionId | object): string;
|
|
109
|
-
/**
|
|
110
|
-
* Checks if the given action is a channeled action (result of calling `Action(channel)`).
|
|
111
|
-
*
|
|
112
|
-
* @param action - The action to check
|
|
113
|
-
* @returns `true` if the action is a channeled action with a channel property, `false` otherwise
|
|
114
|
-
*
|
|
115
|
-
* @example
|
|
116
|
-
* ```ts
|
|
117
|
-
* const UserUpdated = Action<User, { UserId: number }>("UserUpdated");
|
|
118
|
-
*
|
|
119
|
-
* isChanneledAction(UserUpdated); // false
|
|
120
|
-
* isChanneledAction(UserUpdated({ UserId: 1 })); // true
|
|
121
|
-
* ```
|
|
122
|
-
*/
|
|
123
|
-
export declare function isChanneledAction(action: ActionId | ChanneledAction | object): action is ChanneledAction;
|
|
124
|
-
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ChanneledAction, AnyAction } from '../types/index.ts';
|
|
2
|
+
import { ActionId } from '../boundary/components/tasks/types.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Extracts the underlying symbol from an action or channeled action.
|
|
5
|
+
* This symbol is used as the event emitter key for dispatching.
|
|
6
|
+
*
|
|
7
|
+
* @param action The action or channeled action to extract the symbol from.
|
|
8
|
+
* @returns The underlying symbol, or the action itself if it's already a symbol/string.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const Increment = Action<number>("Increment");
|
|
13
|
+
* getActionSymbol(Increment); // Symbol(chizu.action/Increment)
|
|
14
|
+
* getActionSymbol(Increment({ UserId: 5 })); // Symbol(chizu.action/Increment)
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function getActionSymbol(action: AnyAction): ActionId;
|
|
18
|
+
/**
|
|
19
|
+
* Checks whether an action is a broadcast action.
|
|
20
|
+
* Broadcast actions are sent to all mounted components that have defined a handler for them.
|
|
21
|
+
*
|
|
22
|
+
* @param action The action to check.
|
|
23
|
+
* @returns True if the action is a broadcast action, false otherwise.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isBroadcastAction(action: AnyAction): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Extracts the action name from an action.
|
|
28
|
+
*
|
|
29
|
+
* Parses both regular actions (`chizu.action/Name`) and
|
|
30
|
+
* distributed actions (`chizu.action/distributed/Name`)
|
|
31
|
+
* to extract just the name portion.
|
|
32
|
+
*
|
|
33
|
+
* @param action The action to extract the name from.
|
|
34
|
+
* @returns The extracted action name, or "unknown" if parsing fails.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const Increment = Action("Increment");
|
|
39
|
+
* getName(Increment); // "Increment"
|
|
40
|
+
*
|
|
41
|
+
* const SignedOut = Action("SignedOut", Distribution.Broadcast);
|
|
42
|
+
* getName(SignedOut); // "SignedOut"
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function getName(action: AnyAction): string;
|
|
46
|
+
/**
|
|
47
|
+
* Checks if the given action is a channeled action (result of calling `Action(channel)`).
|
|
48
|
+
*
|
|
49
|
+
* @param action - The action to check
|
|
50
|
+
* @returns `true` if the action is a channeled action with a channel property, `false` otherwise
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* const UserUpdated = Action<User, { UserId: number }>("UserUpdated");
|
|
55
|
+
*
|
|
56
|
+
* isChanneledAction(UserUpdated); // false
|
|
57
|
+
* isChanneledAction(UserUpdated({ UserId: 1 })); // true
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function isChanneledAction(action: AnyAction): action is ChanneledAction;
|
|
61
|
+
/**
|
|
62
|
+
* Checks whether an action is a multicast action.
|
|
63
|
+
* Multicast actions are dispatched to all components within a named scope boundary.
|
|
64
|
+
*
|
|
65
|
+
* @param action The action to check.
|
|
66
|
+
* @returns True if the action is a multicast action, false otherwise.
|
|
67
|
+
*/
|
|
68
|
+
export declare function isMulticastAction(action: AnyAction): boolean;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Props } from './types.ts';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export { useScope, getScope } from './utils.ts';
|
|
4
|
+
export type { ScopeEntry, ScopeContext } from './types.ts';
|
|
5
|
+
export { MulticastPartition } from './partition.tsx';
|
|
6
|
+
/**
|
|
7
|
+
* Creates a named scope boundary for multicast actions.
|
|
8
|
+
*
|
|
9
|
+
* Components within a `<Scope>` can dispatch multicast actions to all other
|
|
10
|
+
* components within the same scope boundary. This is useful for creating
|
|
11
|
+
* isolated groups of components that need to communicate without affecting
|
|
12
|
+
* other parts of the application.
|
|
13
|
+
*
|
|
14
|
+
* Multiple scopes can be nested, and each scope name creates its own
|
|
15
|
+
* communication channel. When dispatching, the nearest ancestor scope
|
|
16
|
+
* with the matching name receives the event.
|
|
17
|
+
*
|
|
18
|
+
* Like Broadcast, multicast supports `consume()` for declarative rendering
|
|
19
|
+
* and provides late-mounted components with the most recent dispatched value.
|
|
20
|
+
*
|
|
21
|
+
* @param props.name - The unique name for this scope
|
|
22
|
+
* @param props.children - Components within the scope boundary
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* // Create a scoped boundary
|
|
27
|
+
* <Scope name="UserList">
|
|
28
|
+
* <UserFilter />
|
|
29
|
+
* <UserTable />
|
|
30
|
+
* </Scope>
|
|
31
|
+
*
|
|
32
|
+
* // In UserFilter - dispatch to all components in "UserList" scope
|
|
33
|
+
* actions.dispatch(Actions.Multicast.FilterChanged, filter, { scope: "UserList" });
|
|
34
|
+
*
|
|
35
|
+
* // UserTable receives the event, other components outside don't
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```tsx
|
|
40
|
+
* // Nested scopes - each creates its own boundary
|
|
41
|
+
* <Scope name="App">
|
|
42
|
+
* <Header />
|
|
43
|
+
* <Scope name="Sidebar">
|
|
44
|
+
* <SidebarItem />
|
|
45
|
+
* </Scope>
|
|
46
|
+
* <Scope name="Content">
|
|
47
|
+
* <ContentItem />
|
|
48
|
+
* </Scope>
|
|
49
|
+
* </Scope>
|
|
50
|
+
*
|
|
51
|
+
* // Dispatch to "Sidebar" only reaches SidebarItem
|
|
52
|
+
* // Dispatch to "App" reaches all components
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function Scope({ name, children }: Props): React.ReactNode;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ConsumerRenderer } from '../consumer/types.ts';
|
|
2
|
+
import { ActionId } from '../tasks/types.ts';
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
/**
|
|
5
|
+
* Props for the MulticastPartition component.
|
|
6
|
+
*/
|
|
7
|
+
export type Props<T> = {
|
|
8
|
+
/** The multicast action symbol to subscribe to */
|
|
9
|
+
action: ActionId;
|
|
10
|
+
/** The scope name to subscribe to */
|
|
11
|
+
scopeName: string;
|
|
12
|
+
/** Callback that receives a Box and returns React nodes */
|
|
13
|
+
renderer: ConsumerRenderer<T>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Renders output for multicast `consume()` by subscribing to scope action events.
|
|
17
|
+
*
|
|
18
|
+
* Similar to the broadcast Partition component, but subscribes to a named scope's
|
|
19
|
+
* EventEmitter instead of the global broadcast emitter.
|
|
20
|
+
*
|
|
21
|
+
* On mount, if a value was previously dispatched for this action within the scope,
|
|
22
|
+
* it renders immediately with that cached value. If no value exists yet, it renders
|
|
23
|
+
* `null` until the first dispatch.
|
|
24
|
+
*
|
|
25
|
+
* @template T - The payload type for the action
|
|
26
|
+
* @param props.action - The multicast action symbol to subscribe to
|
|
27
|
+
* @param props.scopeName - The scope name to subscribe to
|
|
28
|
+
* @param props.renderer - Callback that receives a Box and returns React nodes
|
|
29
|
+
* @returns The result of calling renderer with the Box, or null if no value/scope exists
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export declare function MulticastPartition<T extends object>({ action, scopeName, renderer, }: Props<T>): React.ReactNode;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { default as EventEmitter } from 'eventemitter3';
|
|
2
|
+
import { Entry } from '../consumer/types.ts';
|
|
3
|
+
import { ActionId } from '../tasks/types.ts';
|
|
4
|
+
import type * as React from "react";
|
|
5
|
+
/**
|
|
6
|
+
* Props for the Scope component.
|
|
7
|
+
*/
|
|
8
|
+
export type Props = {
|
|
9
|
+
/** The unique name for this scope. Used when dispatching multicast actions. */
|
|
10
|
+
name: string;
|
|
11
|
+
/** Children to render within the scope boundary. */
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Represents a single scope in the ancestor chain.
|
|
16
|
+
* Each scope has its own EventEmitter and consumer store.
|
|
17
|
+
*/
|
|
18
|
+
export type ScopeEntry = {
|
|
19
|
+
/** The name of this scope */
|
|
20
|
+
name: string;
|
|
21
|
+
/** EventEmitter for multicast events within this scope */
|
|
22
|
+
emitter: EventEmitter;
|
|
23
|
+
/** Consumer store for late-mounting components (like Broadcast) */
|
|
24
|
+
store: Map<ActionId, Entry>;
|
|
25
|
+
/** Listeners for store changes (for consume() re-renders) */
|
|
26
|
+
listeners: Map<ActionId, Set<() => void>>;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* The scope context is a flattened map of all ancestor scopes by name.
|
|
30
|
+
* Each <Scope> merges its entry with the parent's map, building up a
|
|
31
|
+
* complete lookup table for O(1) retrieval.
|
|
32
|
+
* null indicates no scope ancestor.
|
|
33
|
+
*/
|
|
34
|
+
export type ScopeContext = Map<string, ScopeEntry> | null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ScopeContext, ScopeEntry } from './types.ts';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* React context for the scope chain.
|
|
5
|
+
* Starts as null (no scopes).
|
|
6
|
+
*/
|
|
7
|
+
export declare const Context: React.Context<ScopeContext>;
|
|
8
|
+
/**
|
|
9
|
+
* Hook to access the scope context from the nearest ancestor.
|
|
10
|
+
*
|
|
11
|
+
* @returns The scope context chain, or null if not inside any scope.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useScope(): ScopeContext;
|
|
14
|
+
/**
|
|
15
|
+
* Gets the scope with the given name.
|
|
16
|
+
* O(1) lookup from the flattened scope map.
|
|
17
|
+
*
|
|
18
|
+
* @param context - The current scope context (map of all ancestor scopes)
|
|
19
|
+
* @param name - The scope name to find
|
|
20
|
+
* @returns The matching ScopeEntry, or null if not found
|
|
21
|
+
*/
|
|
22
|
+
export declare function getScope(context: ScopeContext, name: string): ScopeEntry | null;
|
package/dist/chizu.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import{G as e,A as t}from"@mobily/ts-belt";import{jsx as n}from"react/jsx-runtime";import*as r from"react";import{createContext as o,useContext as
|
|
2
|
-
return n(
|
|
3
|
-
return n(
|
|
4
|
-
return n(
|
|
5
|
-
return n(
|
|
6
|
-
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 s}from"react";import{immerable as i,enablePatches as c,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")}class l{static Mount=/* @__PURE__ */Symbol("chizu.action.lifecycle/Mount");static Unmount=/* @__PURE__ */Symbol("chizu.action.lifecycle/Unmount");static Error=/* @__PURE__ */Symbol("chizu.action.lifecycle/Error");static Update=/* @__PURE__ */Symbol("chizu.action.lifecycle/Update");static Node=(()=>{const e=u.Node,t=function(t){return{[u.Action]:e,[u.Payload]:void 0,[u.Channel]:t,channel:t}};return Object.defineProperty(t,u.Action,{value:e,enumerable:!1}),Object.defineProperty(t,u.Payload,{value:void 0,enumerable:!1}),t})()}var f=/* @__PURE__ */(e=>(e.Unicast="unicast",e.Broadcast="broadcast",e.Multicast="multicast",e))(f||{}),d=/* @__PURE__ */(e=>(e.Mounting="mounting",e.Mounted="mounted",e.Unmounting="unmounting",e.Unmounted="unmounted",e))(d||{}),p=/* @__PURE__ */(e=>(e[e.Timedout=0]="Timedout",e[e.Supplanted=1]="Supplanted",e[e.Disallowed=2]="Disallowed",e[e.Errored=3]="Errored",e[e.Unmounted=4]="Unmounted",e))(p||{});class h extends Error{name="AbortError";constructor(e="Aborted"){super(e)}}const m={actionPrefix:"chizu.action/",broadcastActionPrefix:"chizu.action/broadcast/",multicastActionPrefix:"chizu.action/multicast/",channelPrefix:"chizu.channel/"};function y(e,t){return new Promise((n,r)=>{if(t?.aborted)return void r(new h);const o=setTimeout(n,e);t?.addEventListener("abort",()=>{clearTimeout(o),r(new h)},{once:!0})})}function b(e){return e?Boolean(e&&"symbol"!=typeof e):/* @__PURE__ */Symbol(`pk.${Date.now()}.${crypto.randomUUID()}`)}const v=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,config:m,pk:b,sleep:y,"ζ":y,"κ":b},Symbol.toStringTag,{value:"Module"})),g=e=>"symbol"==typeof e;function w(t){return e.isString(t)||g(t)?t:(e.isObject(t)||e.isFunction(t))&&u.Action in t?t[u.Action]:t}function E(t){if(e.isString(t))return t.startsWith(m.broadcastActionPrefix);if(g(t))return t.description?.startsWith(m.broadcastActionPrefix)??!1;if(e.isObject(t)||e.isFunction(t)){if(u.Broadcast in t&&t[u.Broadcast])return!0;if(u.Action in t){const e=t[u.Action];return e.description?.startsWith(m.broadcastActionPrefix)??!1}}return!1}function P(t){const n=w(t),r=e.isString(n)?n:n.description??"";return r.startsWith(m.actionPrefix)&&r.slice(r.lastIndexOf("/")+1)||"unknown"}function x(t){return e.isObject(t)&&u.Channel in t&&"channel"in t}function S(t){if(e.isString(t))return t.startsWith(m.multicastActionPrefix);if(g(t))return t.description?.startsWith(m.multicastActionPrefix)??!1;if(e.isObject(t)||e.isFunction(t)){if(u.Multicast in t&&t[u.Multicast])return!0;if(u.Action in t){const e=t[u.Action];return e.description?.startsWith(m.multicastActionPrefix)??!1}}return!1}const O=(e,t=f.Unicast)=>{const n=t===f.Broadcast?/* @__PURE__ */Symbol(`${m.broadcastActionPrefix}${e}`):t===f.Multicast?/* @__PURE__ */Symbol(`${m.multicastActionPrefix}${e}`):/* @__PURE__ */Symbol(`${m.actionPrefix}${e}`),r=function(e){return{[u.Action]:n,[u.Payload]:void 0,[u.Channel]:e,channel:e}};return Object.defineProperty(r,u.Action,{value:n,enumerable:!1}),Object.defineProperty(r,u.Payload,{value:void 0,enumerable:!1}),t===f.Broadcast&&Object.defineProperty(r,u.Broadcast,{value:!0,enumerable:!1}),t===f.Multicast&&Object.defineProperty(r,u.Multicast,{value:!0,enumerable:!1}),r};function A(e){if(e instanceof Error){if("TimeoutError"===e.name)return p.Timedout;if("AbortError"===e.name)return p.Supplanted}return p.Errored}function M(e){return e instanceof Error?e:new Error(String(e))}const j=o(void 0);function _({handler:e,children:t}){/* @__PURE__ */
|
|
2
|
+
return n(j.Provider,{value:e,children:t})}let N=(e=21)=>{let t="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)t+="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"[63&n[e]];return t};var C=/* @__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))(C||{}),k=/* @__PURE__ */(e=>(e[e.Produce=0]="Produce",e[e.Hydrate=1]="Hydrate",e))(k||{}),R=/* @__PURE__ */(e=>(e.Property="property",e.Process="process",e.Value="value",e.Operation="operation",e))(R||{});class z{[i]=!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 z(this.value,this.operation);return n.property=e,n.process=t,n}}class U{static immer=(()=>{c();const e=new a;return e.setAutoFreeze(!1),e})();static tag="κ";static id=N}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 B(t){if(e.isNullable(t)||W(t))return t;if(e.isArray(t))return t.map(e=>B(e));if(e.isObject(t)){const e=Object.entries(t).map(([e,t])=>[e,B(t)]);return{...Object.fromEntries(e),[U.tag]:t[U.tag]??U.id()}}return t}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 W(t){return e.isNullable(t)||e.isString(t)||e.isNumber(t)||e.isBoolean(t)||"symbol"==typeof t||"bigint"==typeof t}function $(t,n,r,o,s,i){return function c(a,u=n.path){if(a instanceof z){const n=L(r,u.join("."));if(Object.entries(a).filter(([e,t])=>!z.keys.has(e)&&t instanceof z).forEach(([e,t])=>c(t,u.concat(e))),W(a.value)){if(t===k.Hydrate)return a.value;const c=u.slice(0,-1),l=c.length>0?L(r,c.join(".")):r;return e.isNullable(l)||F(l,a,u.at(-1),o,s,i),n??a.value}if(t===k.Hydrate){const e=B(c(a.value,u));return F(e,a,null,o,s,i),e}const l=n??B(a.value);return F(l,a,null,o,s,i),e.isNullable(n)?l:(c(a.value,u),n)}if(e.isArray(a))return a.map((e,t)=>c(e,u.concat(t)));if(e.isObject(a)){const e=Object.entries(a).map(([e,t])=>[e,c(t,u.concat(e))]),n=Object.fromEntries(e);if(t===k.Hydrate){const e=B(n);return Object.entries(a).forEach(([t,n])=>{n instanceof z&&W(n.value)&&F(e,n,t,o,s,i)}),e}return n}return a}(n.value)}function F(e,t,n,r,o,s){const i=s(e),c=o.get(i)??[];o.set(i,[t.assign(n,r),...c])}class H{#e={};#t;#n=/* @__PURE__ */new Map;#r=/* @__PURE__ */new Set;#o=!1;constructor(e=T){this.#t=e}static pk(){return N()}static"κ"=H.pk;annotate(e,t){return new z(t,e)}"δ"=this.annotate;get model(){return this.#e}get inspect(){return function(n,r,o,s,i){function c(s){const i=s.at(-1),c=L(n(),s),a=s.slice(0,-1),u=t.isNotEmpty(a)?L(n(),a):n();return[...e.isObject(c)||e.isArray(c)?r.get(o(c))?.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(c(r)):"remaining"===a?()=>t.length(c(r)):"box"===a?()=>({value:L(n(),r),inspect:e(r)}):"is"===a?e=>c(r).some(t=>0!==(t.operation&e)):"draft"===a?()=>t.head(c(r))?.value??L(n(),r):"settled"===a?()=>new Promise(e=>{if(t.isEmpty(c(r)))return e(L(n(),r));const o=()=>{t.isEmpty(c(r))&&(i(o),e(L(n(),r)))};s(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.#s(k.Hydrate,t=>Object.assign(t,e))}produce(e){if(!this.#o)throw new Error("State must be hydrated using hydrate() before calling produce()");return this.#s(k.Produce,e)}#s(e,t){const n=/* @__PURE__ */Symbol("process"),[,r]=U.immer.produceWithPatches(this.#e,t);return this.#e=r.reduce((t,r)=>U.immer.applyPatches(t,[{...r,value:$(e,r,t,n,this.#n,this.#t)}]),this.#e),this.#e=B(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)}}function D(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var G,I={exports:{}};const V=/* @__PURE__ */D((G||(G=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 s(e,t,r,s,i){if("function"!=typeof r)throw new TypeError("The listener must be a function");var c=new o(r,s||e,i),a=n?n+t:t;return e._events[a]?e._events[a].fn?e._events[a]=[e._events[a],c]:e._events[a].push(c):(e._events[a]=c,e._eventsCount++),e}function i(e,t){0===--e._eventsCount?e._events=new r:delete e._events[t]}function c(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=/* @__PURE__ */Object.create(null),(new r).__proto__||(n=!1)),c.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},c.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,s=new Array(o);r<o;r++)s[r]=t[r].fn;return s},c.prototype.listenerCount=function(e){var t=this._events[n?n+e:e];return t?t.fn?1:t.length:0},c.prototype.emit=function(e,t,r,o,s,i){var c=n?n+e:e;if(!this._events[c])return!1;var a,u,l=this._events[c],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,s),!0;case 6:return l.fn.call(l.context,t,r,o,s,i),!0}for(u=1,a=new Array(f-1);u<f;u++)a[u-1]=arguments[u];l.fn.apply(l.context,a)}else{var d,p=l.length;for(u=0;u<p;u++)switch(l[u].once&&this.removeListener(e,l[u].fn,void 0,!0),f){case 1:l[u].fn.call(l[u].context);break;case 2:l[u].fn.call(l[u].context,t);break;case 3:l[u].fn.call(l[u].context,t,r);break;case 4:l[u].fn.call(l[u].context,t,r,o);break;default:if(!a)for(d=1,a=new Array(f-1);d<f;d++)a[d-1]=arguments[d];l[u].fn.apply(l[u].context,a)}}return!0},c.prototype.on=function(e,t,n){return s(this,e,t,n,!1)},c.prototype.once=function(e,t,n){return s(this,e,t,n,!0)},c.prototype.removeListener=function(e,t,r,o){var s=n?n+e:e;if(!this._events[s])return this;if(!t)return i(this,s),this;var c=this._events[s];if(c.fn)c.fn!==t||o&&!c.once||r&&c.context!==r||i(this,s);else{for(var a=0,u=[],l=c.length;a<l;a++)(c[a].fn!==t||o&&!c[a].once||r&&c[a].context!==r)&&u.push(c[a]);u.length?this._events[s]=1===u.length?u[0]:u:i(this,s)}return this},c.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},c.prototype.off=c.prototype.removeListener,c.prototype.addListener=c.prototype.on,c.prefixed=n,c.EventEmitter=c,e.exports=c}(I)),I.exports)),J=r.createContext(new V);function q(){return r.useContext(J)}function K({children:e}){const t=r.useMemo(()=>new V,[]);/* @__PURE__ */
|
|
3
|
+
return n(J.Provider,{value:t,children:e})}const Q=r.createContext(/* @__PURE__ */new Map);function X(){return r.useContext(Q)}function Y(){const[,e]=r.useReducer(e=>e+1,0);return e}function Z({action:t,renderer:n}){const o=q(),s=X(),i=Y(),c=r.useMemo(()=>{const e=s.get(t);if(e)return e;const n={state:new H,listeners:/* @__PURE__ */new Set};return s.set(t,n),n},[t,s]);r.useLayoutEffect(()=>{function e(e){c.state.hydrate({value:e}),c.listeners.forEach(e=>e())}return c.listeners.add(i),o.on(t,e),()=>{c.listeners.delete(i),o.off(t,e)}},[t,o,c]);const a=c.state.model?.value;return e.isNullable(a)?null:n({value:a,inspect:c.state.inspect.value})}function ee({children:e}){const t=r.useMemo(()=>/* @__PURE__ */new Map,[]);/* @__PURE__ */
|
|
4
|
+
return n(Q.Provider,{value:t,children:e})}const te=r.createContext(/* @__PURE__ */new Set);function ne({children:e}){const t=r.useMemo(()=>/* @__PURE__ */new Set,[]);/* @__PURE__ */
|
|
5
|
+
return n(te.Provider,{value:t,children:e})}function re({children:e}){/* @__PURE__ */
|
|
6
|
+
return n(K,{children:/* @__PURE__ */n(ee,{children:/* @__PURE__ */n(ne,{children:e})})})}const oe=r.createContext(null);function se(){return r.useContext(oe)}function ie(e,t){return e?.get(t)??null}function ce({action:t,scopeName:n,renderer:o}){const s=se(),i=Y(),c=r.useMemo(()=>ie(s,n),[s,n]),a=r.useMemo(()=>c?function(e,t){const n=e.store.get(t);if(n)return n;const r={state:new H,listeners:/* @__PURE__ */new Set};return e.store.set(t,r),r}(c,t):null,[t,c]);if(r.useLayoutEffect(()=>{if(c&&a)return a.listeners.add(i),c.emitter.on(t,e),()=>{a.listeners.delete(i),c.emitter.off(t,e)};function e(e){a&&(a.state.hydrate({value:e}),a.listeners.forEach(e=>e()))}},[t,c,a,i]),!a)return null;const u=a.state.model?.value;return e.isNullable(u)?null:o({value:u,inspect:a.state.inspect.value})}function ae({name:e,children:t}){const o=se(),s=r.useMemo(()=>({name:e,emitter:new V,store:/* @__PURE__ */new Map,listeners:/* @__PURE__ */new Map}),[]),i=r.useMemo(()=>{const t=new Map(o??[]);return t.set(e,s),t},[o,e,s]);/* @__PURE__ */
|
|
7
|
+
return n(oe.Provider,{value:i,children:t})}function ue(e){return(t,n)=>{t.actions.produce(t=>{t.model[e]=n})}}function le(n,o=()=>({})){const i=q(),c=se(),a=s(j),f=r.useContext(te),[p,h]=r.useState(n),m=Y(),y=r.useRef(null),b=r.useRef((()=>{const e=new H;return y.current=e.hydrate(n),e})()),v=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])}(o()),g=r.useMemo(()=>new V,[]),O=r.useRef({handlers:/* @__PURE__ */new Map}),_=function(){const e=r.useRef(/* @__PURE__ */new Set),t=r.useRef(/* @__PURE__ */new Set);return r.useMemo(()=>({broadcast:e.current,multicast:t.current}),[])}(),N=r.useRef(d.Mounting),C=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}),[])}(),k=r.useCallback((e,t,n)=>{const r=new AbortController,o={controller:r,action:e,payload:t};return f.add(o),{model:p,get phase(){return N.current},task:o,data:v,tasks:f,nodes:C.refs.current,actions:{produce(e){if(r.signal.aborted)return;const t=b.current.produce(t=>e({model:t,inspect:b.current.inspect}));h(b.current.model),n.processes.add(t),y.current&&(n.processes.add(y.current),y.current=null)},dispatch(e,t,n){if(r.signal.aborted)return;const o=w(e),s=x(e)?e.channel:void 0;if(S(e)&&n?.scope){const e=ie(c,n.scope);return void(e&&e.emitter.emit(o,t,s))}(E(e)?i:g).emit(o,t,s)},annotate:(e,t)=>b.current.annotate(e,t)}}},[p]);r.useLayoutEffect(()=>{function t(t,n,r){return async function(o,s){const i=r();if(e.isNotNullable(s)&&e.isNotNullable(i)&&!function(e,t){for(const n of Object.keys(e))if(t[n]!==e[n])return!1;return!0}(s,i))return;const c={processes:/* @__PURE__ */new Set},u=Promise.withResolvers(),d=k(t,o,c);try{await n(d,o)}catch(p){const e=O.current.handlers.has(l.Error),n={reason:A(p),error:M(p),action:P(t),handled:e,tasks:f};a?.(n),e&&g.emit(l.Error,n)}finally{for(const e of f)if(e===d.task){f.delete(e);break}c.processes.forEach(e=>b.current.prune(e)),c.processes.size>0&&m(),u.resolve()}}}const n=/* @__PURE__ */new Set;return O.current.handlers.forEach((e,r)=>{for(const{getChannel:o,handler:s}of e){const e=t(r,s,o);if(S(r)){if(c)for(const t of c.values()){const o=t.emitter;o.on(r,e),n.add(()=>o.off(r,e))}g.on(r,e),_.multicast.add(r),n.add(()=>g.off(r,e))}else E(r)?(i.on(r,e),g.on(r,e),_.broadcast.add(r),n.add(()=>{i.off(r,e),g.off(r,e)})):(g.on(r,e),n.add(()=>g.off(r,e)))}}),()=>{N.current=d.Unmounting,g.emit(l.Unmount),N.current=d.Unmounted;for(const e of n)e()}},[g]),r.useLayoutEffect(()=>{for(const[e,t]of C.pending.current)C.emitted.current.get(e)!==t&&(C.emitted.current.set(e,t),g.emit(u.Node,t,{Name:e}));C.pending.current.clear()}),function({unicast:n,broadcastActions:o,phase:s,data:i}){const c=X(),a=r.useRef(null);r.useLayoutEffect(()=>{n.emit(l.Mount),o.forEach(t=>{const r=c.get(t),o=r?.state.model?.value;e.isNullable(o)||n.emit(t,o)}),s.current=d.Mounted},[]),r.useLayoutEffect(()=>{if(e.isNotNullable(a.current)){const e=function(e,t){return Object.keys(t).reduce((n,r)=>e[r]!==t[r]?{...n,[r]:t[r]}:n,{})}(a.current,i);t.isNotEmpty(Object.keys(e))&&n.emit(l.Update,e)}a.current=i},[i,n])}({unicast:g,broadcastActions:_.broadcast,phase:N,data:o()});const R=r.useMemo(()=>[p,{dispatch(e,t,n){const r=w(e),o=x(e)?e.channel:void 0;if(S(e)&&n?.scope){const e=ie(c,n.scope);return void(e&&e.emitter.emit(r,t,o))}(E(e)?i:g).emit(r,t,o)},consume:(e,t,n)=>S(e)&&n?.scope?r.createElement(ce,{action:w(e),scopeName:n.scope,renderer:t}):r.createElement(Z,{action:w(e),renderer:t}),get inspect(){return b.current.inspect},get nodes(){return C.refs.current},node(e,t){C.refs.current[e]=t,C.pending.current.set(e,t)}}],[p,g]);return R.useAction=(e,t)=>{!function(e,t,n){const o=r.useRef(n);r.useLayoutEffect(()=>{o.current=n});const s=r.useRef(t);r.useLayoutEffect(()=>{s.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)},[]),c=r.useCallback(()=>x(s.current)?s.current.channel:void 0,[]),a=w(t),u=e.current.handlers.get(a)??/* @__PURE__ */new Set;0===u.size&&e.current.handlers.set(a,u),u.add({getChannel:c,handler:i})}(O,e,t)},R}export{O as Action,re as Boundary,f as Distribution,_ as Error,l as Lifecycle,C as Op,C as Operation,p as Reason,ae as Scope,H as State,ue as With,le as useActions,v as utils};
|
package/dist/chizu.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var global,factory;global=this,factory=function(e,t,n,r,o){"use strict";function i(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 s=i(r);class c{static Mount=Symbol("chizu.action.lifecycle/Mount");static Node=Symbol("chizu.action.lifecycle/Node");static Unmount=Symbol("chizu.action.lifecycle/Unmount");static Error=Symbol("chizu.action.lifecycle/Error");static Update=Symbol("chizu.action.lifecycle/Update")}var u=(e=>(e.Unicast="unicast",e.Broadcast="broadcast",e))(u||{}),a=(e=>(e.Mounting="mounting",e.Mounted="mounted",e.Unmounting="unmounting",e.Unmounted="unmounted",e))(a||{});const l=Symbol("payload"),f=Symbol("distributed"),d=Symbol("actionSymbol"),p=Symbol("channel");var h=(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))(h||{});class y extends Error{name="AbortError";constructor(e="Aborted"){super(e)}}const m={actionPrefix:"chizu.action/",distributedActionPrefix:"chizu.action/distributed/",channelPrefix:"chizu.channel/"};function b(e,t){return new Promise((n,r)=>{if(t?.aborted)return void r(new y);const o=setTimeout(n,e);t?.addEventListener("abort",()=>{clearTimeout(o),r(new y)},{once:!0})})}function v(e){return e?Boolean(e&&"symbol"!=typeof e):Symbol(`pk.${Date.now()}.${crypto.randomUUID()}`)}const g=Object.freeze(Object.defineProperty({__proto__:null,config:m,pk:v,sleep:b,"ζ":b,"κ":v},Symbol.toStringTag,{value:"Module"}));function w(e){return t.G.isString(e)||"symbol"==typeof e?e:(t.G.isObject(e)||"function"==typeof e)&&d in e?e[d]:e}function x(e){if(t.G.isString(e))return e.startsWith(m.distributedActionPrefix);if("symbol"==typeof e)return e.description?.startsWith(m.distributedActionPrefix)??!1;if(t.G.isObject(e)||"function"==typeof e){if(f in e&&e[f])return!0;if(d in e){const t=e[d];return t.description?.startsWith(m.distributedActionPrefix)??!1}}return!1}function j(e){const n=w(e),r=t.G.isString(n)?n:n.description??"";return r.startsWith(m.actionPrefix)&&r.slice(r.lastIndexOf("/")+1)||"unknown"}function E(e){return t.G.isObject(e)&&p in e&&"channel"in e}function O(e){if(e instanceof Error){if("TimeoutError"===e.name)return h.Timedout;if("AbortError"===e.name)return h.Supplanted}return h.Errored}function S(e){return e instanceof Error?e:new Error(String(e))}const P=r.createContext(void 0);let A=(e=21)=>{let t="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)t+="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"[63&n[e]];return t};var _=(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))(_||{}),G=(e=>(e[e.Produce=0]="Produce",e[e.Hydrate=1]="Hydrate",e))(G||{}),M=(e=>(e.Property="property",e.Process="process",e.Value="value",e.Operation="operation",e))(M||{});class N{[o.immerable]=!0;static keys=new Set(Object.values(M));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 k{static immer=(()=>{o.enablePatches();const e=new o.Immer;return e.setAutoFreeze(!1),e})();static tag="κ";static id=A}function C(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 U(e){if(t.G.isNullable(e)||z(e))return e;if(t.G.isArray(e))return e.map(e=>U(e));if(t.G.isObject(e)){const t=Object.entries(e).map(([e,t])=>[e,U(t)]);return{...Object.fromEntries(t),[k.tag]:e[k.tag]??k.id()}}return e}function R(e){if(Array.isArray(e))return e.filter(e=>k.tag in e).map(e=>e[k.tag]??"").join(",");const t=e[k.tag];if(t)return t;try{return JSON.stringify(e)}catch{return`[unserializable:${typeof e}]`}}function z(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,i,s){return function c(u,a=n.path){if(u instanceof N){const n=C(r,a.join("."));if(Object.entries(u).filter(([e,t])=>!N.keys.has(e)&&t instanceof N).forEach(([e,t])=>c(t,a.concat(e))),z(u.value)){if(e===G.Hydrate)return u.value;const c=a.slice(0,-1),l=c.length>0?C(r,c.join(".")):r;return t.G.isNullable(l)||L(l,u,a.at(-1),o,i,s),n??u.value}if(e===G.Hydrate){const e=U(c(u.value,a));return L(e,u,null,o,i,s),e}const l=n??U(u.value);return L(l,u,null,o,i,s),t.G.isNullable(n)?l:(c(u.value,a),n)}if(t.G.isArray(u))return u.map((e,t)=>c(e,a.concat(t)));if(t.G.isObject(u)){const t=Object.entries(u).map(([e,t])=>[e,c(t,a.concat(e))]),n=Object.fromEntries(t);if(e===G.Hydrate){const e=U(n);return Object.entries(u).forEach(([t,n])=>{n instanceof N&&z(n.value)&&L(e,n,t,o,i,s)}),e}return n}return u}(n.value)}function L(e,t,n,r,o,i){const s=i(e),c=o.get(s)??[];o.set(s,[t.assign(n,r),...c])}class B{#e={};#t;#n=new Map;#r=new Set;#o=!1;constructor(e=R){this.#t=e}static pk(){return A()}static"κ"=B.pk;annotate(e,t){return new N(t,e)}"δ"=this.annotate;get model(){return this.#e}get inspect(){return function(e,n,r,o,i){function s(o){const i=o.at(-1),s=C(e(),o),c=o.slice(0,-1),u=t.A.isNotEmpty(c)?C(e(),c):e();return[...t.G.isObject(s)||t.G.isArray(s)?n.get(r(s))?.filter(e=>t.G.isNullable(e.property))??[]:[],...t.G.isObject(u)?n.get(r(u))?.filter(e=>e.property===i)??[]:[]]}return function n(r){return new Proxy(()=>{},{get:(c,u)=>"pending"===u?()=>!t.A.isEmpty(s(r)):"remaining"===u?()=>t.A.length(s(r)):"box"===u?()=>({value:C(e(),r),inspect:n(r)}):"is"===u?e=>s(r).some(t=>0!==(t.operation&e)):"draft"===u?()=>t.A.head(s(r))?.value??C(e(),r):"settled"===u?()=>new Promise(n=>{if(t.A.isEmpty(s(r)))return n(C(e(),r));const c=()=>{t.A.isEmpty(s(r))&&(i(c),n(C(e(),r)))};o(c)}):n([...r,String(u)])})}([])}(()=>this.#e,this.#n,this.#t,e=>this.#r.add(e),e=>this.#r.delete(e))}hydrate(e){return this.#o=!0,this.#i(G.Hydrate,t=>Object.assign(t,e))}produce(e){if(!this.#o)throw new Error("State must be hydrated using hydrate() before calling produce()");return this.#i(G.Produce,e)}#i(e,t){const n=Symbol("process"),[,r]=k.immer.produceWithPatches(this.#e,t);return this.#e=r.reduce((t,r)=>k.immer.applyPatches(t,[{...r,value:T(e,r,t,n,this.#n,this.#t)}]),this.#e),this.#e=U(this.#e),this.#s(),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.#s()}#s(){this.#r.forEach(e=>e())}observe(e){const t=()=>e(this.#e);return this.#r.add(t),()=>this.#r.delete(t)}}function D(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var H,W={exports:{}},$=(H||(H=1,function(e){var t=Object.prototype.hasOwnProperty,n="~";function r(){}function o(e,t,n){this.fn=e,this.context=t,this.once=n||!1}function i(e,t,r,i,s){if("function"!=typeof r)throw new TypeError("The listener must be a function");var c=new o(r,i||e,s),u=n?n+t:t;return e._events[u]?e._events[u].fn?e._events[u]=[e._events[u],c]:e._events[u].push(c):(e._events[u]=c,e._eventsCount++),e}function s(e,t){0===--e._eventsCount?e._events=new r:delete e._events[t]}function c(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=Object.create(null),(new r).__proto__||(n=!1)),c.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},c.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,i=new Array(o);r<o;r++)i[r]=t[r].fn;return i},c.prototype.listenerCount=function(e){var t=this._events[n?n+e:e];return t?t.fn?1:t.length:0},c.prototype.emit=function(e,t,r,o,i,s){var c=n?n+e:e;if(!this._events[c])return!1;var u,a,l=this._events[c],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,i),!0;case 6:return l.fn.call(l.context,t,r,o,i,s),!0}for(a=1,u=new Array(f-1);a<f;a++)u[a-1]=arguments[a];l.fn.apply(l.context,u)}else{var d,p=l.length;for(a=0;a<p;a++)switch(l[a].once&&this.removeListener(e,l[a].fn,void 0,!0),f){case 1:l[a].fn.call(l[a].context);break;case 2:l[a].fn.call(l[a].context,t);break;case 3:l[a].fn.call(l[a].context,t,r);break;case 4:l[a].fn.call(l[a].context,t,r,o);break;default:if(!u)for(d=1,u=new Array(f-1);d<f;d++)u[d-1]=arguments[d];l[a].fn.apply(l[a].context,u)}}return!0},c.prototype.on=function(e,t,n){return i(this,e,t,n,!1)},c.prototype.once=function(e,t,n){return i(this,e,t,n,!0)},c.prototype.removeListener=function(e,t,r,o){var i=n?n+e:e;if(!this._events[i])return this;if(!t)return s(this,i),this;var c=this._events[i];if(c.fn)c.fn!==t||o&&!c.once||r&&c.context!==r||s(this,i);else{for(var u=0,a=[],l=c.length;u<l;u++)(c[u].fn!==t||o&&!c[u].once||r&&c[u].context!==r)&&a.push(c[u]);a.length?this._events[i]=1===a.length?a[0]:a:s(this,i)}return this},c.prototype.removeAllListeners=function(e){var t;return e?this._events[t=n?n+e:e]&&s(this,t):(this._events=new r,this._eventsCount=0),this},c.prototype.off=c.prototype.removeListener,c.prototype.addListener=c.prototype.on,c.prefixed=n,c.EventEmitter=c,e.exports=c}(W)),W.exports);const q=D($),I=s.createContext(new q);function F(){return s.useContext(I)}function V({children:e}){const t=s.useMemo(()=>new q,[]);return n.jsx(I.Provider,{value:t,children:e})}const J=s.createContext(new Map);function K(){return s.useContext(J)}function Q(){const[,e]=s.useReducer(e=>e+1,0);return e}function X({action:e,renderer:n}){const r=F(),o=K(),i=Q(),c=s.useMemo(()=>{const t=o.get(e);if(t)return t;const n={state:new B,listeners:new Set};return o.set(e,n),n},[e,o]);s.useLayoutEffect(()=>{function t(e){c.state.hydrate({value:e}),c.listeners.forEach(e=>e())}return c.listeners.add(i),r.on(e,t),()=>{c.listeners.delete(i),r.off(e,t)}},[e,r,c]);const u=c.state.model?.value;return t.G.isNullable(u)?null:n({value:u,inspect:c.state.inspect.value})}function Y({children:e}){const t=s.useMemo(()=>new Map,[]);return n.jsx(J.Provider,{value:t,children:e})}const Z=s.createContext(new Set);function ee({children:e}){const t=s.useMemo(()=>new Set,[]);return n.jsx(Z.Provider,{value:t,children:e})}const te=s.useEffectEvent??s.experimental_useEffectEvent;e.Action=(e,t=u.Unicast)=>{const n=t===u.Broadcast?Symbol(`${m.distributedActionPrefix}${e}`):Symbol(`${m.actionPrefix}${e}`),r=function(e){return{[d]:n,[l]:void 0,[p]:e,channel:e}};return Object.defineProperty(r,d,{value:n,enumerable:!1}),Object.defineProperty(r,l,{value:void 0,enumerable:!1}),t===u.Broadcast&&Object.defineProperty(r,f,{value:!0,enumerable:!1}),r},e.Boundary=function({children:e}){return n.jsx(V,{children:n.jsx(Y,{children:n.jsx(ee,{children:e})})})},e.Distribution=u,e.Error=function({handler:e,children:t}){return n.jsx(P.Provider,{value:e,children:t})},e.Lifecycle=c,e.Op=_,e.Operation=_,e.Reason=h,e.State=B,e.With=function(e){return(t,n)=>{t.actions.produce(t=>{t.model[e]=n})}},e.useActions=function(e,n=()=>({})){const o=F(),i=r.useContext(P),u=s.useContext(Z),[l,f]=s.useState(e),d=Q(),p=s.useRef(null),h=s.useRef((()=>{const t=new B;return p.current=t.hydrate(e),t})()),y=function(e){const t=s.useRef(e);return s.useLayoutEffect(()=>{t.current=e},[e]),s.useMemo(()=>{return n=t,Object.keys(e).reduce((e,t)=>(Object.defineProperty(e,t,{get:()=>n.current[t],enumerable:!0}),e),{});var n},[e])}(n()),m=s.useMemo(()=>new q,[]),b=s.useRef({handlers:new Map}),v=s.useRef(new Set),g=s.useRef(a.Mounting),A=s.useCallback((e,t,n)=>{const r=new AbortController,i={controller:r,action:e,payload:t};return u.add(i),{model:l,get phase(){return g.current},task:i,data:y,tasks:u,actions:{produce(e){if(r.signal.aborted)return;const t=h.current.produce(t=>e({model:t,inspect:h.current.inspect}));f(h.current.model),n.processes.add(t),p.current&&(n.processes.add(p.current),p.current=null)},dispatch(e,t){if(r.signal.aborted)return;const n=w(e),i=E(e)?e.channel:void 0;(x(e)?o:m).emit(n,t,i)},annotate:(e,t)=>h.current.annotate(e,t)}}},[l]);s.useLayoutEffect(()=>{function e(e,n,r){return async function(o,s){const a=r();if(t.G.isNotNullable(s)&&t.G.isNotNullable(a)&&!function(e,t){for(const n of Object.keys(e))if(t[n]!==e[n])return!1;return!0}(s,a))return;const l={processes:new Set},f=Promise.withResolvers(),p=A(e,o,l);try{await n(p,o)}catch(y){const t=b.current.handlers.has(c.Error),n={reason:O(y),error:S(y),action:j(e),handled:t};i?.(n),t&&m.emit(c.Error,n)}finally{for(const e of u)if(e===p.task){u.delete(e);break}l.processes.forEach(e=>h.current.prune(e)),d(),f.resolve()}}}b.current.handlers.forEach((t,n)=>{for(const{getChannel:r,handler:i}of t){const t=e(n,i,r);x(n)?(o.on(n,t),m.on(n,t),v.current.add(n)):m.on(n,t)}})},[m]),function({unicast:e,distributedActions:n,phase:r,data:o}){const i=K(),u=s.useRef(null);s.useLayoutEffect(()=>(e.emit(c.Mount),n.forEach(n=>{const r=i.get(n),o=r?.state.model?.value;t.G.isNullable(o)||e.emit(n,o)}),r.current=a.Mounted,()=>{r.current=a.Unmounting,e.emit(c.Unmount),r.current=a.Unmounted}),[]),s.useEffect(()=>{e.emit(c.Node)},[]),s.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,o);t.A.isNotEmpty(Object.keys(n))&&e.emit(c.Update,n)}u.current=o},[o,e])}({unicast:m,distributedActions:v.current,phase:g,data:n()});const _=s.useMemo(()=>[l,{dispatch(e,t){const n=w(e),r=E(e)?e.channel:void 0;(x(e)?o:m).emit(n,t,r)},consume:(e,t)=>s.createElement(X,{action:w(e),renderer:t}),get inspect(){return h.current.inspect}}],[l,m]);return _.useAction=(e,t)=>{!function(e,t,n){const r=te(async(e,t)=>{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)}),o=te(()=>E(t)?t.channel:void 0),i=w(t),s=e.current.handlers.get(i)??new Set;0===s.size&&e.current.handlers.set(i,s),s.add({getChannel:o,handler:r})}(b,e,t)},_},e.utils=g,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 i(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 s=i(r);class c{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")}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=c.Node,t=function(t){return{[c.Action]:e,[c.Payload]:void 0,[c.Channel]:t,channel:t}};return Object.defineProperty(t,c.Action,{value:e,enumerable:!1}),Object.defineProperty(t,c.Payload,{value:void 0,enumerable:!1}),t})()}var u=(e=>(e.Unicast="unicast",e.Broadcast="broadcast",e.Multicast="multicast",e))(u||{}),l=(e=>(e.Mounting="mounting",e.Mounted="mounted",e.Unmounting="unmounting",e.Unmounted="unmounted",e))(l||{}),f=(e=>(e[e.Timedout=0]="Timedout",e[e.Supplanted=1]="Supplanted",e[e.Disallowed=2]="Disallowed",e[e.Errored=3]="Errored",e[e.Unmounted=4]="Unmounted",e))(f||{});class d extends Error{name="AbortError";constructor(e="Aborted"){super(e)}}const p={actionPrefix:"chizu.action/",broadcastActionPrefix:"chizu.action/broadcast/",multicastActionPrefix:"chizu.action/multicast/",channelPrefix:"chizu.channel/"};function h(e,t){return new Promise((n,r)=>{if(t?.aborted)return void r(new d);const o=setTimeout(n,e);t?.addEventListener("abort",()=>{clearTimeout(o),r(new d)},{once:!0})})}function m(e){return e?Boolean(e&&"symbol"!=typeof e):Symbol(`pk.${Date.now()}.${crypto.randomUUID()}`)}const y=Object.freeze(Object.defineProperty({__proto__:null,config:p,pk:m,sleep:h,"ζ":h,"κ":m},Symbol.toStringTag,{value:"Module"})),b=e=>"symbol"==typeof e;function v(e){return t.G.isString(e)||b(e)?e:(t.G.isObject(e)||t.G.isFunction(e))&&c.Action in e?e[c.Action]:e}function g(e){if(t.G.isString(e))return e.startsWith(p.broadcastActionPrefix);if(b(e))return e.description?.startsWith(p.broadcastActionPrefix)??!1;if(t.G.isObject(e)||t.G.isFunction(e)){if(c.Broadcast in e&&e[c.Broadcast])return!0;if(c.Action in e){const t=e[c.Action];return t.description?.startsWith(p.broadcastActionPrefix)??!1}}return!1}function w(e){const n=v(e),r=t.G.isString(n)?n:n.description??"";return r.startsWith(p.actionPrefix)&&r.slice(r.lastIndexOf("/")+1)||"unknown"}function x(e){return t.G.isObject(e)&&c.Channel in e&&"channel"in e}function j(e){if(t.G.isString(e))return e.startsWith(p.multicastActionPrefix);if(b(e))return e.description?.startsWith(p.multicastActionPrefix)??!1;if(t.G.isObject(e)||t.G.isFunction(e)){if(c.Multicast in e&&e[c.Multicast])return!0;if(c.Action in e){const t=e[c.Action];return t.description?.startsWith(p.multicastActionPrefix)??!1}}return!1}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 S=r.createContext(void 0);let O=(e=21)=>{let t="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)t+="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"[63&n[e]];return t};var E=(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||{}),M=(e=>(e[e.Produce=0]="Produce",e[e.Hydrate=1]="Hydrate",e))(M||{}),G=(e=>(e.Property="property",e.Process="process",e.Value="value",e.Operation="operation",e))(G||{});class _{[o.immerable]=!0;static keys=new Set(Object.values(G));property=null;process=null;value;operation;constructor(e,t){this.value=e,this.operation=t}assign(e,t){const n=new _(this.value,this.operation);return n.property=e,n.process=t,n}}class C{static immer=(()=>{o.enablePatches();const e=new o.Immer;return e.setAutoFreeze(!1),e})();static tag="κ";static id=O}function N(e,t){const n="string"==typeof t?""===t?[]:t.split("."):t;let r=e;for(const o of n){if(null==r)return;r=r[o]}return r}function k(e){if(t.G.isNullable(e)||z(e))return e;if(t.G.isArray(e))return e.map(e=>k(e));if(t.G.isObject(e)){const t=Object.entries(e).map(([e,t])=>[e,k(t)]);return{...Object.fromEntries(t),[C.tag]:e[C.tag]??C.id()}}return e}function R(e){if(Array.isArray(e))return e.filter(e=>C.tag in e).map(e=>e[C.tag]??"").join(",");const t=e[C.tag];if(t)return t;try{return JSON.stringify(e)}catch{return`[unserializable:${typeof e}]`}}function z(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 U(e,n,r,o,i,s){return function c(a,u=n.path){if(a instanceof _){const n=N(r,u.join("."));if(Object.entries(a).filter(([e,t])=>!_.keys.has(e)&&t instanceof _).forEach(([e,t])=>c(t,u.concat(e))),z(a.value)){if(e===M.Hydrate)return a.value;const c=u.slice(0,-1),l=c.length>0?N(r,c.join(".")):r;return t.G.isNullable(l)||L(l,a,u.at(-1),o,i,s),n??a.value}if(e===M.Hydrate){const e=k(c(a.value,u));return L(e,a,null,o,i,s),e}const l=n??k(a.value);return L(l,a,null,o,i,s),t.G.isNullable(n)?l:(c(a.value,u),n)}if(t.G.isArray(a))return a.map((e,t)=>c(e,u.concat(t)));if(t.G.isObject(a)){const t=Object.entries(a).map(([e,t])=>[e,c(t,u.concat(e))]),n=Object.fromEntries(t);if(e===M.Hydrate){const e=k(n);return Object.entries(a).forEach(([t,n])=>{n instanceof _&&z(n.value)&&L(e,n,t,o,i,s)}),e}return n}return a}(n.value)}function L(e,t,n,r,o,i){const s=i(e),c=o.get(s)??[];o.set(s,[t.assign(n,r),...c])}class T{#e={};#t;#n=new Map;#r=new Set;#o=!1;constructor(e=R){this.#t=e}static pk(){return O()}static"κ"=T.pk;annotate(e,t){return new _(t,e)}"δ"=this.annotate;get model(){return this.#e}get inspect(){return function(e,n,r,o,i){function s(o){const i=o.at(-1),s=N(e(),o),c=o.slice(0,-1),a=t.A.isNotEmpty(c)?N(e(),c):e();return[...t.G.isObject(s)||t.G.isArray(s)?n.get(r(s))?.filter(e=>t.G.isNullable(e.property))??[]:[],...t.G.isObject(a)?n.get(r(a))?.filter(e=>e.property===i)??[]:[]]}return function n(r){return new Proxy(()=>{},{get:(c,a)=>"pending"===a?()=>!t.A.isEmpty(s(r)):"remaining"===a?()=>t.A.length(s(r)):"box"===a?()=>({value:N(e(),r),inspect:n(r)}):"is"===a?e=>s(r).some(t=>0!==(t.operation&e)):"draft"===a?()=>t.A.head(s(r))?.value??N(e(),r):"settled"===a?()=>new Promise(n=>{if(t.A.isEmpty(s(r)))return n(N(e(),r));const c=()=>{t.A.isEmpty(s(r))&&(i(c),n(N(e(),r)))};o(c)}):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.#i(M.Hydrate,t=>Object.assign(t,e))}produce(e){if(!this.#o)throw new Error("State must be hydrated using hydrate() before calling produce()");return this.#i(M.Produce,e)}#i(e,t){const n=Symbol("process"),[,r]=C.immer.produceWithPatches(this.#e,t);return this.#e=r.reduce((t,r)=>C.immer.applyPatches(t,[{...r,value:U(e,r,t,n,this.#n,this.#t)}]),this.#e),this.#e=k(this.#e),this.#s(),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.#s()}#s(){this.#r.forEach(e=>e())}observe(e){const t=()=>e(this.#e);return this.#r.add(t),()=>this.#r.delete(t)}}function B(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var W,$={exports:{}},D=(W||(W=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 i(e,t,r,i,s){if("function"!=typeof r)throw new TypeError("The listener must be a function");var c=new o(r,i||e,s),a=n?n+t:t;return e._events[a]?e._events[a].fn?e._events[a]=[e._events[a],c]:e._events[a].push(c):(e._events[a]=c,e._eventsCount++),e}function s(e,t){0===--e._eventsCount?e._events=new r:delete e._events[t]}function c(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=Object.create(null),(new r).__proto__||(n=!1)),c.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},c.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,i=new Array(o);r<o;r++)i[r]=t[r].fn;return i},c.prototype.listenerCount=function(e){var t=this._events[n?n+e:e];return t?t.fn?1:t.length:0},c.prototype.emit=function(e,t,r,o,i,s){var c=n?n+e:e;if(!this._events[c])return!1;var a,u,l=this._events[c],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,i),!0;case 6:return l.fn.call(l.context,t,r,o,i,s),!0}for(u=1,a=new Array(f-1);u<f;u++)a[u-1]=arguments[u];l.fn.apply(l.context,a)}else{var d,p=l.length;for(u=0;u<p;u++)switch(l[u].once&&this.removeListener(e,l[u].fn,void 0,!0),f){case 1:l[u].fn.call(l[u].context);break;case 2:l[u].fn.call(l[u].context,t);break;case 3:l[u].fn.call(l[u].context,t,r);break;case 4:l[u].fn.call(l[u].context,t,r,o);break;default:if(!a)for(d=1,a=new Array(f-1);d<f;d++)a[d-1]=arguments[d];l[u].fn.apply(l[u].context,a)}}return!0},c.prototype.on=function(e,t,n){return i(this,e,t,n,!1)},c.prototype.once=function(e,t,n){return i(this,e,t,n,!0)},c.prototype.removeListener=function(e,t,r,o){var i=n?n+e:e;if(!this._events[i])return this;if(!t)return s(this,i),this;var c=this._events[i];if(c.fn)c.fn!==t||o&&!c.once||r&&c.context!==r||s(this,i);else{for(var a=0,u=[],l=c.length;a<l;a++)(c[a].fn!==t||o&&!c[a].once||r&&c[a].context!==r)&&u.push(c[a]);u.length?this._events[i]=1===u.length?u[0]:u:s(this,i)}return this},c.prototype.removeAllListeners=function(e){var t;return e?this._events[t=n?n+e:e]&&s(this,t):(this._events=new r,this._eventsCount=0),this},c.prototype.off=c.prototype.removeListener,c.prototype.addListener=c.prototype.on,c.prefixed=n,c.EventEmitter=c,e.exports=c}($)),$.exports);const F=B(D),H=s.createContext(new F);function q(){return s.useContext(H)}function I({children:e}){const t=s.useMemo(()=>new F,[]);return n.jsx(H.Provider,{value:t,children:e})}const V=s.createContext(new Map);function J(){return s.useContext(V)}function K(){const[,e]=s.useReducer(e=>e+1,0);return e}function Q({action:e,renderer:n}){const r=q(),o=J(),i=K(),c=s.useMemo(()=>{const t=o.get(e);if(t)return t;const n={state:new T,listeners:new Set};return o.set(e,n),n},[e,o]);s.useLayoutEffect(()=>{function t(e){c.state.hydrate({value:e}),c.listeners.forEach(e=>e())}return c.listeners.add(i),r.on(e,t),()=>{c.listeners.delete(i),r.off(e,t)}},[e,r,c]);const a=c.state.model?.value;return t.G.isNullable(a)?null:n({value:a,inspect:c.state.inspect.value})}function X({children:e}){const t=s.useMemo(()=>new Map,[]);return n.jsx(V.Provider,{value:t,children:e})}const Y=s.createContext(new Set);function Z({children:e}){const t=s.useMemo(()=>new Set,[]);return n.jsx(Y.Provider,{value:t,children:e})}const ee=s.createContext(null);function te(){return s.useContext(ee)}function ne(e,t){return e?.get(t)??null}function re({action:e,scopeName:n,renderer:r}){const o=te(),i=K(),c=s.useMemo(()=>ne(o,n),[o,n]),a=s.useMemo(()=>c?function(e,t){const n=e.store.get(t);if(n)return n;const r={state:new T,listeners:new Set};return e.store.set(t,r),r}(c,e):null,[e,c]);if(s.useLayoutEffect(()=>{if(c&&a)return a.listeners.add(i),c.emitter.on(e,t),()=>{a.listeners.delete(i),c.emitter.off(e,t)};function t(e){a&&(a.state.hydrate({value:e}),a.listeners.forEach(e=>e()))}},[e,c,a,i]),!a)return null;const u=a.state.model?.value;return t.G.isNullable(u)?null:r({value:u,inspect:a.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{[c.Action]:n,[c.Payload]:void 0,[c.Channel]:e,channel:e}};return Object.defineProperty(r,c.Action,{value:n,enumerable:!1}),Object.defineProperty(r,c.Payload,{value:void 0,enumerable:!1}),t===u.Broadcast&&Object.defineProperty(r,c.Broadcast,{value:!0,enumerable:!1}),t===u.Multicast&&Object.defineProperty(r,c.Multicast,{value:!0,enumerable:!1}),r},e.Boundary=function({children:e}){return n.jsx(I,{children:n.jsx(X,{children:n.jsx(Z,{children:e})})})},e.Distribution=u,e.Error=function({handler:e,children:t}){return n.jsx(S.Provider,{value:e,children:t})},e.Lifecycle=a,e.Op=E,e.Operation=E,e.Reason=f,e.Scope=function({name:e,children:t}){const r=te(),o=s.useMemo(()=>({name:e,emitter:new F,store:new Map,listeners:new Map}),[]),i=s.useMemo(()=>{const t=new Map(r??[]);return t.set(e,o),t},[r,e,o]);return n.jsx(ee.Provider,{value:i,children:t})},e.State=T,e.With=function(e){return(t,n)=>{t.actions.produce(t=>{t.model[e]=n})}},e.useActions=function(e,n=()=>({})){const o=q(),i=te(),u=r.useContext(S),f=s.useContext(Y),[d,p]=s.useState(e),h=K(),m=s.useRef(null),y=s.useRef((()=>{const t=new T;return m.current=t.hydrate(e),t})()),b=function(e){const t=s.useRef(e);return s.useLayoutEffect(()=>{t.current=e},[e]),s.useMemo(()=>{return n=t,Object.keys(e).reduce((e,t)=>(Object.defineProperty(e,t,{get:()=>n.current[t],enumerable:!0}),e),{});var n},[e])}(n()),O=s.useMemo(()=>new F,[]),E=s.useRef({handlers:new Map}),M=function(){const e=s.useRef(new Set),t=s.useRef(new Set);return s.useMemo(()=>({broadcast:e.current,multicast:t.current}),[])}(),G=s.useRef(l.Mounting),_=function(){const e=s.useRef({}),t=s.useRef(new Map),n=s.useRef(new Map);return s.useMemo(()=>({refs:e,pending:t,emitted:n}),[])}(),C=s.useCallback((e,t,n)=>{const r=new AbortController,s={controller:r,action:e,payload:t};return f.add(s),{model:d,get phase(){return G.current},task:s,data:b,tasks:f,nodes:_.refs.current,actions:{produce(e){if(r.signal.aborted)return;const t=y.current.produce(t=>e({model:t,inspect:y.current.inspect}));p(y.current.model),n.processes.add(t),m.current&&(n.processes.add(m.current),m.current=null)},dispatch(e,t,n){if(r.signal.aborted)return;const s=v(e),c=x(e)?e.channel:void 0;if(j(e)&&n?.scope){const e=ne(i,n.scope);return void(e&&e.emitter.emit(s,t,c))}(g(e)?o:O).emit(s,t,c)},annotate:(e,t)=>y.current.annotate(e,t)}}},[d]);s.useLayoutEffect(()=>{function e(e,n,r){return async function(o,i){const s=r();if(t.G.isNotNullable(i)&&t.G.isNotNullable(s)&&!function(e,t){for(const n of Object.keys(e))if(t[n]!==e[n])return!1;return!0}(i,s))return;const c={processes:new Set},l=Promise.withResolvers(),d=C(e,o,c);try{await n(d,o)}catch(p){const t=E.current.handlers.has(a.Error),n={reason:A(p),error:P(p),action:w(e),handled:t,tasks:f};u?.(n),t&&O.emit(a.Error,n)}finally{for(const e of f)if(e===d.task){f.delete(e);break}c.processes.forEach(e=>y.current.prune(e)),c.processes.size>0&&h(),l.resolve()}}}const n=new Set;return E.current.handlers.forEach((t,r)=>{for(const{getChannel:s,handler:c}of t){const t=e(r,c,s);if(j(r)){if(i)for(const e of i.values()){const o=e.emitter;o.on(r,t),n.add(()=>o.off(r,t))}O.on(r,t),M.multicast.add(r),n.add(()=>O.off(r,t))}else g(r)?(o.on(r,t),O.on(r,t),M.broadcast.add(r),n.add(()=>{o.off(r,t),O.off(r,t)})):(O.on(r,t),n.add(()=>O.off(r,t)))}}),()=>{G.current=l.Unmounting,O.emit(a.Unmount),G.current=l.Unmounted;for(const e of n)e()}},[O]),s.useLayoutEffect(()=>{for(const[e,t]of _.pending.current)_.emitted.current.get(e)!==t&&(_.emitted.current.set(e,t),O.emit(c.Node,t,{Name:e}));_.pending.current.clear()}),function({unicast:e,broadcastActions:n,phase:r,data:o}){const i=J(),c=s.useRef(null);s.useLayoutEffect(()=>{e.emit(a.Mount),n.forEach(n=>{const r=i.get(n),o=r?.state.model?.value;t.G.isNullable(o)||e.emit(n,o)}),r.current=l.Mounted},[]),s.useLayoutEffect(()=>{if(t.G.isNotNullable(c.current)){const n=function(e,t){return Object.keys(t).reduce((n,r)=>e[r]!==t[r]?{...n,[r]:t[r]}:n,{})}(c.current,o);t.A.isNotEmpty(Object.keys(n))&&e.emit(a.Update,n)}c.current=o},[o,e])}({unicast:O,broadcastActions:M.broadcast,phase:G,data:n()});const N=s.useMemo(()=>[d,{dispatch(e,t,n){const r=v(e),s=x(e)?e.channel:void 0;if(j(e)&&n?.scope){const e=ne(i,n.scope);return void(e&&e.emitter.emit(r,t,s))}(g(e)?o:O).emit(r,t,s)},consume:(e,t,n)=>j(e)&&n?.scope?s.createElement(re,{action:v(e),scopeName:n.scope,renderer:t}):s.createElement(Q,{action:v(e),renderer:t}),get inspect(){return y.current.inspect},get nodes(){return _.refs.current},node(e,t){_.refs.current[e]=t,_.pending.current.set(e,t)}}],[d,O]);return N.useAction=(e,t)=>{!function(e,t,n){const r=s.useRef(n);s.useLayoutEffect(()=>{r.current=n});const o=s.useRef(t);s.useLayoutEffect(()=>{o.current=t});const i=s.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)},[]),c=s.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:c,handler:i})}(E,e,t)},N},e.utils=y,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/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
+
import { Task } from '../boundary/components/tasks/types.ts';
|
|
2
3
|
/**
|
|
3
4
|
* Reasons why an action error occurred.
|
|
4
5
|
*/
|
|
@@ -54,6 +55,27 @@ export type Fault<E extends Error = never> = {
|
|
|
54
55
|
action: string;
|
|
55
56
|
/** Whether the component has a `Lifecycle.Error` handler registered. */
|
|
56
57
|
handled: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* All currently running tasks across the application.
|
|
60
|
+
* Use this to programmatically abort in-flight actions during error recovery
|
|
61
|
+
* (e.g., on 403/500 responses to prevent cascading failures).
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* <Error handler={({ reason, tasks }) => {
|
|
66
|
+
* if (reason === Reason.Errored) {
|
|
67
|
+
* // Abort all in-flight tasks to prevent cascading errors
|
|
68
|
+
* for (const task of tasks) {
|
|
69
|
+
* task.controller.abort();
|
|
70
|
+
* }
|
|
71
|
+
* // Trigger re-authentication flow
|
|
72
|
+
* }
|
|
73
|
+
* }}>
|
|
74
|
+
* {children}
|
|
75
|
+
* </Error>
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
tasks: ReadonlySet<Task>;
|
|
57
79
|
};
|
|
58
80
|
/**
|
|
59
81
|
* Catcher function called when an action error occurs.
|