chizu 0.2.71 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -85
- package/dist/boundary/components/broadcast/utils.d.ts +7 -1
- package/dist/boundary/components/scope/index.d.ts +26 -21
- package/dist/boundary/components/scope/types.d.ts +3 -2
- package/dist/boundary/index.d.ts +1 -1
- package/dist/chizu.js +6 -8
- package/dist/chizu.umd.cjs +1 -1
- package/dist/error/index.d.ts +1 -23
- package/dist/error/types.d.ts +12 -28
- package/dist/error/utils.d.ts +1 -11
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/types.d.ts +4 -4
- package/dist/hooks/utils.d.ts +6 -3
- package/dist/index.d.ts +6 -5
- package/dist/resource/index.d.ts +78 -0
- package/dist/types/index.d.ts +217 -166
- package/dist/utils/index.d.ts +0 -17
- package/dist/utils.d.ts +26 -0
- package/package.json +4 -1
- package/dist/boundary/components/cache/index.d.ts +0 -13
- package/dist/boundary/components/cache/types.d.ts +0 -19
- package/dist/boundary/components/cache/utils.d.ts +0 -12
- package/dist/cache/index.d.ts +0 -77
package/dist/types/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { Operation, Process, Inspect, Box } from 'immertation';
|
|
2
2
|
import { ActionId, Task, Tasks } from '../boundary/components/tasks/types.ts';
|
|
3
|
-
import { Option } from '@mobily/ts-belt/Option';
|
|
4
|
-
import { Result as TsBeltResult } from '@mobily/ts-belt/Result';
|
|
5
3
|
import { Regulator } from '../boundary/components/regulators/types.ts';
|
|
6
4
|
import { Fault } from '../error/types.ts';
|
|
7
5
|
import * as React from "react";
|
|
@@ -58,43 +56,15 @@ export declare class Brand {
|
|
|
58
56
|
static readonly Channel: unique symbol;
|
|
59
57
|
/** Node capture events used by Lifecycle.Node */
|
|
60
58
|
static readonly Node: unique symbol;
|
|
61
|
-
/** Identifies cache entry identifiers created with Entry() */
|
|
62
|
-
static readonly Cache: unique symbol;
|
|
63
59
|
}
|
|
64
60
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* @internal
|
|
69
|
-
*/
|
|
70
|
-
declare const CacheValueBrand: unique symbol;
|
|
71
|
-
/**
|
|
72
|
-
* A branded cache entry identifier.
|
|
73
|
-
*
|
|
74
|
-
* When the second type parameter `C` is provided, the entry becomes callable
|
|
75
|
-
* to produce channeled identifiers for independent cache slots per channel.
|
|
76
|
-
*
|
|
77
|
-
* @template T - The cached value type.
|
|
78
|
-
* @template C - The channel type for channeled entries (defaults to never).
|
|
79
|
-
*/
|
|
80
|
-
export type CacheId<T = unknown, C extends Filter = never> = {
|
|
81
|
-
readonly [Brand.Cache]: symbol;
|
|
82
|
-
readonly [CacheValueBrand]?: (t: T) => T;
|
|
83
|
-
} & ([C] extends [never] ? unknown : {
|
|
84
|
-
(channel: C): ChanneledCacheId<T, C>;
|
|
85
|
-
});
|
|
86
|
-
/**
|
|
87
|
-
* Result of calling a channeled cache entry with a channel argument.
|
|
88
|
-
* Contains the entry identity and the channel data for scoped cache access.
|
|
61
|
+
* Internal symbol for the global `Lifecycle.Fault` broadcast. Exposed so the
|
|
62
|
+
* dispatch pipeline can fire faults and short-circuit the regulator policy
|
|
63
|
+
* without depending on the `Lifecycle` class at runtime.
|
|
89
64
|
*
|
|
90
|
-
* @
|
|
91
|
-
* @template C - The channel type.
|
|
65
|
+
* @internal
|
|
92
66
|
*/
|
|
93
|
-
export
|
|
94
|
-
readonly [Brand.Cache]: symbol;
|
|
95
|
-
readonly [CacheValueBrand]?: (t: T) => T;
|
|
96
|
-
readonly channel: C;
|
|
97
|
-
};
|
|
67
|
+
export declare const FaultSymbol: unique symbol;
|
|
98
68
|
/**
|
|
99
69
|
* Factory functions for lifecycle actions.
|
|
100
70
|
*
|
|
@@ -116,6 +86,9 @@ export type ChanneledCacheId<T = unknown, C = unknown> = {
|
|
|
116
86
|
* // Now regulating Lifecycle.Mount only blocks THIS component's mount:
|
|
117
87
|
* context.regulator.disallow(Actions.Mount);
|
|
118
88
|
* ```
|
|
89
|
+
*
|
|
90
|
+
* `Lifecycle.Fault` is a singleton broadcast (not a factory). All components
|
|
91
|
+
* subscribe to the same shared symbol to receive global fault notifications.
|
|
119
92
|
*/
|
|
120
93
|
export declare class Lifecycle {
|
|
121
94
|
/** Creates a Mount lifecycle action. Triggered once on component mount (`useLayoutEffect`). */
|
|
@@ -151,6 +124,28 @@ export declare class Lifecycle {
|
|
|
151
124
|
static Node(): HandlerPayload<unknown, {
|
|
152
125
|
Name: string;
|
|
153
126
|
}>;
|
|
127
|
+
/**
|
|
128
|
+
* Global fault broadcast. Receives a `Fault` whenever any action in the
|
|
129
|
+
* `<Boundary>` errors, times out, is supplanted, or is blocked by the
|
|
130
|
+
* regulator. Subscribe via `actions.useAction(Lifecycle.Fault, handler)`.
|
|
131
|
+
*
|
|
132
|
+
* Unlike the per-component `Lifecycle.Error()` factory, `Fault` is a single
|
|
133
|
+
* shared broadcast — every subscriber points at the same symbol. The
|
|
134
|
+
* regulator policy does not apply to `Fault`; faults always reach
|
|
135
|
+
* subscribers so error visibility cannot be silenced.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```tsx
|
|
139
|
+
* const actions = useActions<void, typeof Actions>();
|
|
140
|
+
*
|
|
141
|
+
* actions.useAction(Lifecycle.Fault, (context, fault) => {
|
|
142
|
+
* if (fault.reason === Reason.Errored) {
|
|
143
|
+
* console.error(`Action "${fault.action}" failed`, fault.error);
|
|
144
|
+
* }
|
|
145
|
+
* });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
static Fault: BroadcastPayload<Fault>;
|
|
154
149
|
}
|
|
155
150
|
/**
|
|
156
151
|
* Distribution modes for actions.
|
|
@@ -205,24 +200,6 @@ export declare enum Phase {
|
|
|
205
200
|
/** Component has fully unmounted. */
|
|
206
201
|
Unmounted = "unmounted"
|
|
207
202
|
}
|
|
208
|
-
/**
|
|
209
|
-
* Operations for toggling boolean feature flags via `actions.feature()`.
|
|
210
|
-
*
|
|
211
|
-
* @example
|
|
212
|
-
* ```ts
|
|
213
|
-
* actions.feature("sidebar", Feature.Toggle);
|
|
214
|
-
* actions.feature("sidebar", Feature.On);
|
|
215
|
-
* actions.feature("sidebar", Feature.Off);
|
|
216
|
-
* ```
|
|
217
|
-
*/
|
|
218
|
-
export declare enum Feature {
|
|
219
|
-
/** Sets the feature to `true`. */
|
|
220
|
-
On = "on",
|
|
221
|
-
/** Sets the feature to `false`. */
|
|
222
|
-
Off = "off",
|
|
223
|
-
/** Inverts the current boolean value. */
|
|
224
|
-
Toggle = "toggle"
|
|
225
|
-
}
|
|
226
203
|
/**
|
|
227
204
|
* Primary key type for identifying entities in collections.
|
|
228
205
|
* Can be undefined (not yet assigned), a symbol (temporary/local), or a concrete value T.
|
|
@@ -292,8 +269,12 @@ export type ChanneledAction<P = unknown, C = unknown> = {
|
|
|
292
269
|
* Broadcast actions are sent to all mounted components. Values are cached so that
|
|
293
270
|
* late-mounting components receive the most recent payload.
|
|
294
271
|
*
|
|
272
|
+
* Late-mounting components receive the most recent cached payload via their
|
|
273
|
+
* `useAction` handler during mount. Use `peek()` in a `Lifecycle.Mount` handler
|
|
274
|
+
* to check whether a cached value exists before performing default fetches.
|
|
275
|
+
*
|
|
295
276
|
* This type extends `HandlerPayload<P, C>` with an additional brand to enforce at compile-time
|
|
296
|
-
* that only broadcast actions can be passed to `context.actions.
|
|
277
|
+
* that only broadcast actions can be passed to `context.actions.resolution()`.
|
|
297
278
|
*
|
|
298
279
|
* @template P - The payload type for the action
|
|
299
280
|
* @template C - The channel type for channeled dispatches (defaults to never)
|
|
@@ -302,8 +283,8 @@ export type ChanneledAction<P = unknown, C = unknown> = {
|
|
|
302
283
|
* ```ts
|
|
303
284
|
* const SignedOut = Action<User>("SignedOut", Distribution.Broadcast);
|
|
304
285
|
*
|
|
305
|
-
* //
|
|
306
|
-
* const user = await context.actions.
|
|
286
|
+
* // Resolve the latest value inside a handler
|
|
287
|
+
* const user = await context.actions.resolution(SignedOut);
|
|
307
288
|
* ```
|
|
308
289
|
*/
|
|
309
290
|
export type BroadcastPayload<P = unknown, C extends Filter = never> = HandlerPayload<P, C> & {
|
|
@@ -313,20 +294,21 @@ export type BroadcastPayload<P = unknown, C extends Filter = never> = HandlerPay
|
|
|
313
294
|
* Branded type for multicast action objects created with `Action()` and `Distribution.Multicast`.
|
|
314
295
|
* Multicast actions are dispatched to all components within a named scope boundary.
|
|
315
296
|
*
|
|
316
|
-
* When dispatching a multicast action, you MUST provide the scope
|
|
297
|
+
* When dispatching a multicast action, you MUST provide the scope carrier as the third argument:
|
|
317
298
|
* ```ts
|
|
318
|
-
* actions.dispatch(Actions.Multicast.Update, payload, { scope:
|
|
299
|
+
* actions.dispatch(Actions.Multicast.Update, payload, { scope: Actions.Multicast });
|
|
319
300
|
* ```
|
|
320
301
|
*
|
|
321
|
-
* Components receive multicast events only if they are descendants of a `<Scope
|
|
302
|
+
* Components receive multicast events only if they are descendants of a `<Scope of={...}>`.
|
|
322
303
|
*
|
|
323
304
|
* @template P - The payload type for the action
|
|
324
305
|
* @template C - The channel type for channeled dispatches (defaults to never)
|
|
325
306
|
*
|
|
326
307
|
* @example
|
|
327
308
|
* ```tsx
|
|
328
|
-
* // Define multicast actions
|
|
309
|
+
* // Define multicast actions and their scope together
|
|
329
310
|
* class MulticastActions {
|
|
311
|
+
* static Scope = "Counter" as const;
|
|
330
312
|
* static Update = Action<number>("Update", Distribution.Multicast);
|
|
331
313
|
* }
|
|
332
314
|
*
|
|
@@ -336,26 +318,47 @@ export type BroadcastPayload<P = unknown, C extends Filter = never> = HandlerPay
|
|
|
336
318
|
* }
|
|
337
319
|
*
|
|
338
320
|
* // In JSX - create a named scope boundary
|
|
339
|
-
* <Scope
|
|
321
|
+
* <Scope of={MulticastActions}>
|
|
340
322
|
* <CounterA />
|
|
341
323
|
* <CounterB />
|
|
342
324
|
* </Scope>
|
|
343
325
|
*
|
|
344
|
-
* // Inside CounterA - dispatch to all components in
|
|
345
|
-
* actions.dispatch(Actions.Multicast.Update, 42, { scope:
|
|
326
|
+
* // Inside CounterA - dispatch to all components in the scope
|
|
327
|
+
* actions.dispatch(Actions.Multicast.Update, 42, { scope: Actions.Multicast });
|
|
346
328
|
* // CounterA and CounterB both receive the event
|
|
347
329
|
* ```
|
|
348
330
|
*/
|
|
349
331
|
export type MulticastPayload<P = unknown, C extends Filter = never> = HandlerPayload<P, C> & {
|
|
350
332
|
readonly [Brand.Multicast]: true;
|
|
351
333
|
};
|
|
334
|
+
/**
|
|
335
|
+
* A scope carrier — any object exposing a `Scope` string literal.
|
|
336
|
+
*
|
|
337
|
+
* By convention this is the feature's `MulticastActions` class, which owns
|
|
338
|
+
* the scope name alongside its multicast action declarations:
|
|
339
|
+
*
|
|
340
|
+
* ```ts
|
|
341
|
+
* export class MulticastActions {
|
|
342
|
+
* static Scope = "my-feature" as const;
|
|
343
|
+
* static Update = Action<T>("Update", Distribution.Multicast);
|
|
344
|
+
* }
|
|
345
|
+
* ```
|
|
346
|
+
*
|
|
347
|
+
* Requiring a carrier (rather than a bare string) prevents typos and enforces
|
|
348
|
+
* a single source of truth for each scope name.
|
|
349
|
+
*
|
|
350
|
+
* @template S - The scope name literal type.
|
|
351
|
+
*/
|
|
352
|
+
export type ScopeCarrier<S extends string = string> = {
|
|
353
|
+
readonly Scope: S;
|
|
354
|
+
};
|
|
352
355
|
/**
|
|
353
356
|
* Options for multicast dispatch.
|
|
354
357
|
* Required when dispatching a multicast action.
|
|
355
358
|
*/
|
|
356
359
|
export type MulticastOptions = {
|
|
357
|
-
/**
|
|
358
|
-
scope:
|
|
360
|
+
/** Carrier object exposing the scope name via `.Scope`. Typically the feature's `MulticastActions` class. */
|
|
361
|
+
scope: ScopeCarrier;
|
|
359
362
|
};
|
|
360
363
|
/**
|
|
361
364
|
* Extracts the payload type `P` from a `HandlerPayload<P>` or `ChanneledAction<P, C>`.
|
|
@@ -439,38 +442,106 @@ type AssertSync<F> = IsAsync<F> extends true ? "Error: async functions are not a
|
|
|
439
442
|
export type Props = Record<string, unknown>;
|
|
440
443
|
/**
|
|
441
444
|
* Extracts the nodes type from a Model.
|
|
442
|
-
* If the model has a `nodes` property, returns its type.
|
|
445
|
+
* If the model has a `meta.nodes` property, returns its type.
|
|
443
446
|
* Otherwise returns an empty record.
|
|
444
447
|
*
|
|
445
448
|
* @example
|
|
446
449
|
* ```ts
|
|
447
450
|
* type Model = {
|
|
448
451
|
* count: number;
|
|
449
|
-
* nodes: {
|
|
452
|
+
* meta: { nodes: { container: HTMLButtonElement | null } };
|
|
450
453
|
* };
|
|
451
454
|
*
|
|
452
|
-
* type N =
|
|
455
|
+
* type N = ExtractNodes<Model>; // { container: HTMLButtonElement | null }
|
|
453
456
|
* ```
|
|
454
457
|
*/
|
|
455
|
-
export type
|
|
456
|
-
|
|
458
|
+
export type ExtractNodes<M> = M extends {
|
|
459
|
+
meta: {
|
|
460
|
+
nodes: infer N extends Record<string, unknown>;
|
|
461
|
+
};
|
|
457
462
|
} ? N : Record<never, unknown>;
|
|
458
463
|
/**
|
|
459
|
-
*
|
|
460
|
-
*
|
|
464
|
+
* Transforms `meta.nodes` values to include `| null`, reflecting
|
|
465
|
+
* that node refs are initially `null` until a DOM element is captured.
|
|
466
|
+
* Models without `meta.nodes` pass through unchanged.
|
|
467
|
+
*
|
|
468
|
+
* @internal
|
|
469
|
+
*/
|
|
470
|
+
export type NullableNodes<M> = M extends {
|
|
471
|
+
meta: infer Meta & {
|
|
472
|
+
nodes: infer N extends Record<string, unknown>;
|
|
473
|
+
};
|
|
474
|
+
} ? Omit<M, "meta"> & {
|
|
475
|
+
meta: Omit<Meta, "nodes"> & {
|
|
476
|
+
nodes: {
|
|
477
|
+
[K in keyof N]: N[K] | null;
|
|
478
|
+
};
|
|
479
|
+
};
|
|
480
|
+
} : M;
|
|
481
|
+
/**
|
|
482
|
+
* Extracts the `meta.features` property from a Model type.
|
|
483
|
+
* If the model has a `meta.features` property whose values are all booleans,
|
|
461
484
|
* returns its type. Otherwise returns an empty record, making the
|
|
462
|
-
* `
|
|
485
|
+
* `features` methods effectively uncallable.
|
|
463
486
|
*
|
|
464
487
|
* @example
|
|
465
488
|
* ```ts
|
|
466
|
-
*
|
|
467
|
-
* type
|
|
468
|
-
* type F = Features<Model>; // { Sidebar: boolean; Modal: boolean }
|
|
489
|
+
* type Model = { count: number; meta: { features: { sidebar: boolean; modal: boolean } } };
|
|
490
|
+
* type F = FeatureFlags<Model>; // { sidebar: boolean; modal: boolean }
|
|
469
491
|
* ```
|
|
470
492
|
*/
|
|
471
493
|
export type FeatureFlags<M> = M extends {
|
|
472
|
-
|
|
494
|
+
meta: {
|
|
495
|
+
features: infer F extends Record<string, boolean>;
|
|
496
|
+
};
|
|
473
497
|
} ? F : Record<never, boolean>;
|
|
498
|
+
/**
|
|
499
|
+
* Resolves to `unknown` when the model has no `meta.features` or all
|
|
500
|
+
* feature values are booleans. Resolves to a descriptive string literal when
|
|
501
|
+
* any value is not a boolean, causing an intersection with the model type
|
|
502
|
+
* to become `never` and producing a compile-time error.
|
|
503
|
+
*
|
|
504
|
+
* @internal
|
|
505
|
+
*/
|
|
506
|
+
export type ValidateFeatures<M> = M extends {
|
|
507
|
+
meta: {
|
|
508
|
+
features: infer F;
|
|
509
|
+
};
|
|
510
|
+
} ? F extends Record<string, boolean> ? unknown : "meta.features values must all be boolean" : unknown;
|
|
511
|
+
/**
|
|
512
|
+
* Utility type for the `meta` model property. Combines optional `nodes`
|
|
513
|
+
* and `features` sub-objects into a single meta shape.
|
|
514
|
+
*
|
|
515
|
+
* - When `N` is provided, produces `{ nodes: { [K in keyof N]: N[K] | null } }`.
|
|
516
|
+
* - When `F` is provided, produces `{ features: F }`.
|
|
517
|
+
* - Pass `void` to omit either sub-object.
|
|
518
|
+
*
|
|
519
|
+
* @template N - Node type record (e.g. `{ input: HTMLInputElement }`)
|
|
520
|
+
* @template F - Feature flags record (e.g. `{ sidebar: boolean }`)
|
|
521
|
+
*
|
|
522
|
+
* @example
|
|
523
|
+
* ```ts
|
|
524
|
+
* import type { Meta } from "chizu";
|
|
525
|
+
*
|
|
526
|
+
* type Model = {
|
|
527
|
+
* count: number;
|
|
528
|
+
* meta: Meta<{ input: HTMLInputElement }, { sidebar: boolean }>;
|
|
529
|
+
* };
|
|
530
|
+
* // Equivalent to:
|
|
531
|
+
* // meta: { nodes: { input: HTMLInputElement | null }; features: { sidebar: boolean } }
|
|
532
|
+
* ```
|
|
533
|
+
*/
|
|
534
|
+
export type Meta<N extends Record<string, unknown> | void = void, F extends Record<string, boolean> | void = void> = ([N] extends [void] ? unknown : {
|
|
535
|
+
nodes: {
|
|
536
|
+
[K in keyof N]: N[K] | null;
|
|
537
|
+
};
|
|
538
|
+
}) & ([F] extends [void] ? unknown : {
|
|
539
|
+
features: F;
|
|
540
|
+
});
|
|
541
|
+
export declare namespace Meta {
|
|
542
|
+
type Nodes<N extends Record<string, unknown>> = Meta<N>;
|
|
543
|
+
type Features<F extends Record<string, boolean>> = Meta<void, F>;
|
|
544
|
+
}
|
|
474
545
|
/**
|
|
475
546
|
* Constraint type for action containers.
|
|
476
547
|
* Actions are symbols grouped in an object (typically a class with static properties).
|
|
@@ -573,18 +644,20 @@ export type HandlerContext<M extends Model | void, _AC extends Actions | void, D
|
|
|
573
644
|
*/
|
|
574
645
|
readonly tasks: ReadonlySet<Task>;
|
|
575
646
|
/**
|
|
576
|
-
*
|
|
577
|
-
* Nodes may be `null` if not yet captured or if the node was unmounted.
|
|
647
|
+
* Meta properties including captured DOM nodes and feature flags.
|
|
578
648
|
*
|
|
579
649
|
* @example
|
|
580
650
|
* ```ts
|
|
581
651
|
* actions.useAction(Actions.Focus, (context) => {
|
|
582
|
-
* context.nodes.input?.focus();
|
|
652
|
+
* context.meta.nodes.input?.focus();
|
|
583
653
|
* });
|
|
584
654
|
* ```
|
|
585
655
|
*/
|
|
586
|
-
readonly
|
|
587
|
-
|
|
656
|
+
readonly meta: {
|
|
657
|
+
readonly nodes: {
|
|
658
|
+
[K in keyof ExtractNodes<M>]: ExtractNodes<M>[K] | null;
|
|
659
|
+
};
|
|
660
|
+
readonly features: Readonly<FeatureFlags<M>>;
|
|
588
661
|
};
|
|
589
662
|
/**
|
|
590
663
|
* The regulator API for controlling which actions may be dispatched.
|
|
@@ -608,78 +681,42 @@ export type HandlerContext<M extends Model | void, _AC extends Actions | void, D
|
|
|
608
681
|
readonly regulator: Regulator;
|
|
609
682
|
readonly actions: {
|
|
610
683
|
produce<F extends (draft: {
|
|
611
|
-
model: M
|
|
684
|
+
model: Omit<M, "meta">;
|
|
612
685
|
readonly inspect: Readonly<Inspect<M>>;
|
|
613
686
|
}) => void>(ƒ: F & AssertSync<F>): void;
|
|
614
687
|
dispatch(action: ActionOrChanneled, payload?: unknown, options?: MulticastOptions): Promise<void>;
|
|
615
688
|
annotate<T>(operation: Operation, value: T): T;
|
|
616
689
|
/**
|
|
617
|
-
*
|
|
618
|
-
*
|
|
619
|
-
* The callback must return an `Option<T>` or `Result<T, E>`. Only `Some` / `Ok`
|
|
620
|
-
* values are stored; `None` / `Error` results are skipped and `{ data: null }`
|
|
621
|
-
* is returned. Exactly one layer of `Option` / `Result` is unwrapped.
|
|
622
|
-
*
|
|
623
|
-
* @param entry - The cache entry identifier (from `Entry()`).
|
|
624
|
-
* @param ttl - Time-to-live in milliseconds.
|
|
625
|
-
* @param fn - Async callback that produces the value to cache.
|
|
626
|
-
* @returns An object with `data` set to the cached or freshly-fetched value, or `null`.
|
|
627
|
-
*
|
|
628
|
-
* @example
|
|
629
|
-
* ```ts
|
|
630
|
-
* const { data } = await context.actions.cacheable(
|
|
631
|
-
* CacheStore.Pairs,
|
|
632
|
-
* 30_000,
|
|
633
|
-
* async () => Some(await api.fetchPairs()),
|
|
634
|
-
* );
|
|
635
|
-
* ```
|
|
636
|
-
*/
|
|
637
|
-
cacheable<T>(entry: CacheId<T> | ChanneledCacheId<T>, ttl: number, fn: () => Promise<Option<T>>): Promise<{
|
|
638
|
-
data: T | null;
|
|
639
|
-
}>;
|
|
640
|
-
cacheable<T>(entry: CacheId<T> | ChanneledCacheId<T>, ttl: number, fn: () => Promise<TsBeltResult<T, unknown>>): Promise<{
|
|
641
|
-
data: T | null;
|
|
642
|
-
}>;
|
|
643
|
-
/**
|
|
644
|
-
* Removes a cached value from the store.
|
|
645
|
-
*
|
|
646
|
-
* @param entry - The cache entry identifier to invalidate.
|
|
690
|
+
* Feature toggle methods for mutating boolean flags on the model.
|
|
647
691
|
*
|
|
648
692
|
* @example
|
|
649
693
|
* ```ts
|
|
650
|
-
* context.actions.
|
|
651
|
-
* context.actions.
|
|
694
|
+
* context.actions.features.on("sidebar");
|
|
695
|
+
* context.actions.features.off("sidebar");
|
|
696
|
+
* context.actions.features.invert("sidebar");
|
|
652
697
|
* ```
|
|
653
698
|
*/
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
* Read feature state from `model.features` directly.
|
|
660
|
-
*
|
|
661
|
-
* @example
|
|
662
|
-
* ```ts
|
|
663
|
-
* context.actions.feature(Feature.Sidebar, Feature.Toggle);
|
|
664
|
-
* context.actions.feature(Feature.Sidebar, Feature.Off);
|
|
665
|
-
* ```
|
|
666
|
-
*/
|
|
667
|
-
feature<K extends keyof FeatureFlags<M>>(name: K, operation: Feature): void;
|
|
699
|
+
features: {
|
|
700
|
+
on<K extends keyof FeatureFlags<M>>(name: K): void;
|
|
701
|
+
off<K extends keyof FeatureFlags<M>>(name: K): void;
|
|
702
|
+
invert<K extends keyof FeatureFlags<M>>(name: K): void;
|
|
703
|
+
};
|
|
668
704
|
/**
|
|
669
|
-
*
|
|
705
|
+
* Returns the resolved broadcast or multicast value, waiting for any
|
|
706
|
+
* pending annotations to settle before resolving.
|
|
670
707
|
*
|
|
671
708
|
* If a value has already been dispatched it resolves immediately.
|
|
672
709
|
* Otherwise it waits until the next dispatch of the action.
|
|
673
710
|
* Resolves with `null` if the task is aborted before a value arrives.
|
|
674
711
|
*
|
|
675
|
-
* @param action - The broadcast or multicast action to
|
|
676
|
-
* @param options - For multicast actions, must include `{ scope:
|
|
712
|
+
* @param action - The broadcast or multicast action to resolve.
|
|
713
|
+
* @param options - For multicast actions, must include `{ scope: MulticastActions }`.
|
|
677
714
|
* @returns The dispatched value, or `null` if aborted.
|
|
678
715
|
*
|
|
679
716
|
* @example
|
|
680
717
|
* ```ts
|
|
681
718
|
* actions.useAction(Actions.FetchPosts, async (context) => {
|
|
682
|
-
* const user = await context.actions.
|
|
719
|
+
* const user = await context.actions.resolution(Actions.Broadcast.User);
|
|
683
720
|
* if (!user) return;
|
|
684
721
|
* const posts = await fetchPosts(user.id, {
|
|
685
722
|
* signal: context.task.controller.signal,
|
|
@@ -688,15 +725,15 @@ export type HandlerContext<M extends Model | void, _AC extends Actions | void, D
|
|
|
688
725
|
* });
|
|
689
726
|
* ```
|
|
690
727
|
*/
|
|
691
|
-
|
|
692
|
-
|
|
728
|
+
resolution<T>(action: BroadcastPayload<T>): Promise<T | null>;
|
|
729
|
+
resolution<T>(action: MulticastPayload<T>, options: MulticastOptions): Promise<T | null>;
|
|
693
730
|
/**
|
|
694
731
|
* Returns the latest broadcast or multicast value immediately without
|
|
695
732
|
* waiting for annotations to settle. Use this when you need the current
|
|
696
733
|
* cached value and do not need to wait for pending operations to complete.
|
|
697
734
|
*
|
|
698
735
|
* @param action - The broadcast or multicast action to peek at.
|
|
699
|
-
* @param options - For multicast actions, must include `{ scope:
|
|
736
|
+
* @param options - For multicast actions, must include `{ scope: MulticastActions }`.
|
|
700
737
|
* @returns The cached value, or `null` if no value has been dispatched.
|
|
701
738
|
*
|
|
702
739
|
* @example
|
|
@@ -795,19 +832,19 @@ export type Handlers<M extends Model | void, AC extends Actions | void, D extend
|
|
|
795
832
|
[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>;
|
|
796
833
|
};
|
|
797
834
|
export type UseActions<M extends Model | void, AC extends Actions | void, D extends Props = Props> = [
|
|
798
|
-
Readonly<M
|
|
835
|
+
Readonly<NullableNodes<M>>,
|
|
799
836
|
{
|
|
800
837
|
/**
|
|
801
838
|
* Dispatches an action with an optional payload.
|
|
802
839
|
*
|
|
803
|
-
* For multicast actions, you MUST provide the scope as the third argument:
|
|
840
|
+
* For multicast actions, you MUST provide the scope carrier as the third argument:
|
|
804
841
|
* ```ts
|
|
805
|
-
* actions.dispatch(Actions.Multicast.Update, payload, { scope:
|
|
842
|
+
* actions.dispatch(Actions.Multicast.Update, payload, { scope: Actions.Multicast });
|
|
806
843
|
* ```
|
|
807
844
|
*
|
|
808
845
|
* @param action - The action to dispatch
|
|
809
846
|
* @param payload - The payload to send with the action
|
|
810
|
-
* @param options - For multicast actions, must include `{ scope:
|
|
847
|
+
* @param options - For multicast actions, must include `{ scope: MulticastActions }`
|
|
811
848
|
*/
|
|
812
849
|
dispatch<P>(action: HandlerPayload<P>, payload?: P, options?: MulticastOptions): Promise<void>;
|
|
813
850
|
dispatch<P>(action: BroadcastPayload<P>, payload?: P, options?: MulticastOptions): Promise<void>;
|
|
@@ -815,39 +852,32 @@ export type UseActions<M extends Model | void, AC extends Actions | void, D exte
|
|
|
815
852
|
dispatch<P, C extends Filter>(action: ChanneledAction<P, C>, payload?: P, options?: MulticastOptions): Promise<void>;
|
|
816
853
|
inspect: Inspect<M>;
|
|
817
854
|
/**
|
|
818
|
-
*
|
|
819
|
-
* Nodes may be `null` if not yet captured or if the node was unmounted.
|
|
855
|
+
* Meta properties including captured DOM nodes and feature flags.
|
|
820
856
|
*
|
|
821
857
|
* @example
|
|
822
858
|
* ```tsx
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
* nodes: { input: HTMLInputElement };
|
|
826
|
-
* };
|
|
827
|
-
* const [model, actions] = useActions<Model, typeof Actions>(model);
|
|
828
|
-
*
|
|
829
|
-
* // Access captured nodes
|
|
830
|
-
* actions.nodes.input?.focus();
|
|
859
|
+
* actions.meta.nodes.input?.focus();
|
|
860
|
+
* actions.meta.features.sidebar; // boolean
|
|
831
861
|
* ```
|
|
832
862
|
*/
|
|
833
|
-
|
|
834
|
-
|
|
863
|
+
meta: {
|
|
864
|
+
readonly nodes: {
|
|
865
|
+
[K in keyof ExtractNodes<M>]: ExtractNodes<M>[K] | null;
|
|
866
|
+
};
|
|
867
|
+
readonly features: Readonly<FeatureFlags<M>>;
|
|
835
868
|
};
|
|
836
869
|
/**
|
|
837
|
-
* Captures a DOM node for later access via `
|
|
838
|
-
* Use as a ref callback on JSX
|
|
870
|
+
* Captures a DOM node for later access via `meta.nodes`.
|
|
871
|
+
* Use as a ref callback on JSX elements.
|
|
839
872
|
*
|
|
840
|
-
* @param name - The node key (must match a key in
|
|
873
|
+
* @param name - The node key (must match a key in the model's `meta.nodes`)
|
|
841
874
|
* @param node - The DOM node or null (when unmounting)
|
|
842
875
|
*
|
|
843
876
|
* @example
|
|
844
877
|
* ```tsx
|
|
845
878
|
* type Model = {
|
|
846
879
|
* count: number;
|
|
847
|
-
*
|
|
848
|
-
* container: HTMLDivElement;
|
|
849
|
-
* input: HTMLInputElement;
|
|
850
|
-
* };
|
|
880
|
+
* meta: Meta<{ container: HTMLDivElement; input: HTMLInputElement }>;
|
|
851
881
|
* };
|
|
852
882
|
*
|
|
853
883
|
* const [model, actions] = useActions<Model, typeof Actions>(model);
|
|
@@ -859,20 +889,23 @@ export type UseActions<M extends Model | void, AC extends Actions | void, D exte
|
|
|
859
889
|
* );
|
|
860
890
|
* ```
|
|
861
891
|
*/
|
|
862
|
-
node<K extends keyof
|
|
892
|
+
node<K extends keyof ExtractNodes<M>>(name: K, node: ExtractNodes<M>[K] | null): void;
|
|
863
893
|
/**
|
|
864
|
-
*
|
|
865
|
-
*
|
|
866
|
-
* Read feature state from `model.features` directly.
|
|
894
|
+
* Feature toggle methods for mutating boolean flags on the model.
|
|
867
895
|
*
|
|
868
896
|
* @example
|
|
869
897
|
* ```tsx
|
|
870
|
-
* actions.
|
|
898
|
+
* actions.features.on("sidebar");
|
|
899
|
+
* actions.features.invert("sidebar");
|
|
871
900
|
*
|
|
872
|
-
* {model.features.
|
|
901
|
+
* {model.meta.features.sidebar && <Sidebar />}
|
|
873
902
|
* ```
|
|
874
903
|
*/
|
|
875
|
-
|
|
904
|
+
features: {
|
|
905
|
+
on<K extends keyof FeatureFlags<M>>(name: K): void;
|
|
906
|
+
off<K extends keyof FeatureFlags<M>>(name: K): void;
|
|
907
|
+
invert<K extends keyof FeatureFlags<M>>(name: K): void;
|
|
908
|
+
};
|
|
876
909
|
/**
|
|
877
910
|
* Streams broadcast values declaratively in JSX using a render-prop pattern.
|
|
878
911
|
*
|
|
@@ -925,4 +958,22 @@ export type UseActions<M extends Model | void, AC extends Actions | void, D exte
|
|
|
925
958
|
* ```
|
|
926
959
|
*/
|
|
927
960
|
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;
|
|
961
|
+
/**
|
|
962
|
+
* Connects a {@link Resource} declared at module scope to this component.
|
|
963
|
+
* Returns a thunk that fetches fresh data on every call – concurrent
|
|
964
|
+
* calls share the in-flight promise. The Resource's `onSuccess` and
|
|
965
|
+
* `onError` callbacks receive `(response, data, dispatch)` where `data`
|
|
966
|
+
* is this component's reactive `data` proxy.
|
|
967
|
+
*
|
|
968
|
+
* @example
|
|
969
|
+
* ```ts
|
|
970
|
+
* const fetchUser = actions.useResource(resources.user);
|
|
971
|
+
*
|
|
972
|
+
* actions.useAction(Actions.Mount, async (context) => {
|
|
973
|
+
* const data = await fetchUser();
|
|
974
|
+
* context.actions.produce(({ model }) => { model.user = data; });
|
|
975
|
+
* });
|
|
976
|
+
* ```
|
|
977
|
+
*/
|
|
978
|
+
useResource<T, E, Args extends readonly unknown[]>(resource: import('../resource/index.ts').ResourceHandle<T, E, Args>): (...args: Args) => Promise<T>;
|
|
928
979
|
};
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
1
|
import { Pk } from '../types/index.ts';
|
|
2
|
-
/**
|
|
3
|
-
* Configuration constants for Chizu action symbols.
|
|
4
|
-
*/
|
|
5
|
-
export declare const config: {
|
|
6
|
-
/** Prefix for all Chizu action symbols. */
|
|
7
|
-
actionPrefix: string;
|
|
8
|
-
/** Prefix for broadcast action symbols. */
|
|
9
|
-
broadcastActionPrefix: string;
|
|
10
|
-
/** Prefix for multicast action symbols. */
|
|
11
|
-
multicastActionPrefix: string;
|
|
12
|
-
/** Prefix for channeled action symbols. */
|
|
13
|
-
channelPrefix: string;
|
|
14
|
-
/** Prefix for cache operation symbols. */
|
|
15
|
-
cachePrefix: string;
|
|
16
|
-
/** Prefix for lifecycle action symbols. */
|
|
17
|
-
lifecyclePrefix: string;
|
|
18
|
-
};
|
|
19
2
|
/**
|
|
20
3
|
* Returns a promise that resolves after the specified number of milliseconds.
|
|
21
4
|
* The sleep will reject with an AbortError when the signal is aborted,
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal symbol description factories. Each function returns a namespaced
|
|
3
|
+
* string suitable for `Symbol()` descriptions or `startsWith` checks.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export declare const describe: {
|
|
8
|
+
/** Unicast action description. `describe.action("Fetch")` → `"chizu.action/Fetch"` */
|
|
9
|
+
action: (name?: string) => string;
|
|
10
|
+
/** Broadcast action description. `describe.broadcast("User")` → `"chizu.action/broadcast/User"` */
|
|
11
|
+
broadcast: (name?: string) => string;
|
|
12
|
+
/** Multicast action description. `describe.multicast("Update")` → `"chizu.action/multicast/Update"` */
|
|
13
|
+
multicast: (name?: string) => string;
|
|
14
|
+
/** Channeled action description. `describe.channel("user")` → `"chizu.channel/user"` */
|
|
15
|
+
channel: (name?: string) => string;
|
|
16
|
+
/** Cache entry description. `describe.cache("users")` → `"chizu.cache/users"` */
|
|
17
|
+
cache: (name?: string) => string;
|
|
18
|
+
/** Lifecycle action description. `describe.lifecycle("Mount")` → `"chizu.action.lifecycle/Mount"` */
|
|
19
|
+
lifecycle: (name?: string) => string;
|
|
20
|
+
/** Mount replay sentinel description. Used to create the {@link replay} symbol. */
|
|
21
|
+
replay: (name?: string) => string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Flat record used for shallow property comparison in {@link changes}.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
1
27
|
type Changes = Record<string, unknown>;
|
|
2
28
|
/**
|
|
3
29
|
* Get high-level changed paths between two objects.
|