mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
build(spf): build26 from 45504a2b
This commit is contained in:
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
import { Machine, MachineSnapshot } from "../machine.js";
|
||||
//#region src/core/actors/actor.d.ts
|
||||
/**
|
||||
* Complete actor snapshot: finite state + non-finite context.
|
||||
* Extends `MachineSnapshot` with context — the non-finite data managed by the actor.
|
||||
*/
|
||||
interface ActorSnapshot<State extends string, Context extends object> extends MachineSnapshot<State> {
|
||||
context: Context;
|
||||
}
|
||||
/** Generic actor interface: owns its snapshot as a reactive signal. */
|
||||
interface SignalActor<State extends string, Context extends object> extends Machine<ActorSnapshot<State, Context>> {}
|
||||
/**
|
||||
* A message-driven actor with no reactive snapshot.
|
||||
*
|
||||
* Use for actors that coordinate async work but have no state that external
|
||||
* consumers need to observe. Analogous to XState's `fromCallback`.
|
||||
*/
|
||||
interface CallbackActor<Message extends {
|
||||
type: string;
|
||||
}> {
|
||||
send(message: Message): void;
|
||||
destroy(): void;
|
||||
}
|
||||
//#endregion
|
||||
export { ActorSnapshot, CallbackActor, SignalActor };
|
||||
//# sourceMappingURL=actor.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"actor.d.ts","names":[],"sources":["../../../../src/core/actors/actor.ts"],"mappings":";;;;;;UAeiB,cAAc,sBAAsB,gCAAgC,gBAAgB;EACnG,SAAS;;;UAIM,YAAY,sBAAsB,gCACzC,QAAQ,cAAc,OAAO;;;;;;;UAQtB,cAAc;EAAkB;;EAC/C,KAAK,SAAS;EACd"}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
import { TaskLike } from "../tasks/task.js";
|
||||
import { SignalActor } from "./actor.js";
|
||||
//#region src/core/actors/create-machine-actor.d.ts
|
||||
/**
|
||||
* Minimal interface for any runner that can be used with createMachineActor.
|
||||
*/
|
||||
interface RunnerLike {
|
||||
schedule<Value = void, Err = unknown>(task: TaskLike<Value, Err>): Promise<Value>;
|
||||
abortAll(): void;
|
||||
destroy(): void;
|
||||
whenSettled(callback: () => void): void;
|
||||
}
|
||||
/**
|
||||
* Context passed to message handlers.
|
||||
* `runner` is present and typed as the exact runner instance only when the
|
||||
* definition includes a runner factory.
|
||||
*/
|
||||
type HandlerContext<UserState extends string, Context extends object, RunnerFactory extends (() => RunnerLike) | undefined> = {
|
||||
transition: (to: UserState) => void;
|
||||
/** Context snapshot captured at dispatch time. Stale after any `setContext` call. */
|
||||
context: Context;
|
||||
/**
|
||||
* Live untracked read of the current context. Use in async task closures that
|
||||
* execute after the handler returns — e.g. `getCtx: getContext` passed to tasks
|
||||
* scheduled on the runner, so each task reads the context committed by the
|
||||
* previous task rather than the stale snapshot from dispatch time.
|
||||
*/
|
||||
getContext: () => Context;
|
||||
setContext: (next: Context) => void;
|
||||
} & (RunnerFactory extends (() => infer R) ? {
|
||||
runner: R;
|
||||
} : object);
|
||||
/**
|
||||
* Definition for a single user-defined state.
|
||||
*/
|
||||
type ActorStateDefinition<UserState extends string, Context extends object, Message extends {
|
||||
type: string;
|
||||
}, RunnerFactory extends (() => RunnerLike) | undefined> = {
|
||||
/**
|
||||
* When the actor's runner settles while in this state, automatically
|
||||
* transition to this state. The framework owns the generation-token logic —
|
||||
* re-registering after each `runner.schedule()` call so that
|
||||
* `abortAll()` + reschedule correctly supersedes stale callbacks.
|
||||
*/
|
||||
onSettled?: UserState;
|
||||
/** Message handlers active in this state. Messages with no handler are silently dropped. */
|
||||
on?: { [M in Message as M['type']]?: (message: Extract<Message, {
|
||||
type: M['type'];
|
||||
}>, ctx: HandlerContext<UserState, Context, RunnerFactory>) => void; };
|
||||
};
|
||||
/**
|
||||
* Full actor definition passed to `createMachineActor`.
|
||||
*
|
||||
* `UserState` is the set of domain-meaningful states. `'destroyed'` is always
|
||||
* added by the framework as the implicit terminal state — do not include it here.
|
||||
*/
|
||||
type ActorDefinition<UserState extends string, Context extends object, Message extends {
|
||||
type: string;
|
||||
}, RunnerFactory extends (() => RunnerLike) | undefined = undefined> = {
|
||||
/**
|
||||
* Runner factory — called once at `createMachineActor()` time.
|
||||
* The runner lives for the full actor lifetime and is destroyed with it.
|
||||
*
|
||||
* @example
|
||||
* runner: () => new SerialRunner()
|
||||
*/
|
||||
runner?: RunnerFactory;
|
||||
/** Initial state. */
|
||||
initial: UserState;
|
||||
/** Initial context. */
|
||||
context: Context;
|
||||
/**
|
||||
* Per-state definitions. States with no definition silently drop all messages.
|
||||
* All user-defined states must appear as keys in the `UserState` union.
|
||||
*/
|
||||
states: Partial<Record<UserState, ActorStateDefinition<UserState, Context, Message, RunnerFactory>>>;
|
||||
};
|
||||
/** Live actor instance returned by `createMachineActor`. */
|
||||
interface MessageActor<State extends string, Context extends object, Message extends {
|
||||
type: string;
|
||||
}> extends SignalActor<State, Context> {
|
||||
send(message: Message): void;
|
||||
}
|
||||
/**
|
||||
* Creates a message-driven actor from a declarative definition.
|
||||
*
|
||||
* The actor owns a reactive snapshot signal (state + context), an optional
|
||||
* runner, and dispatches incoming messages to per-state handlers. `'destroyed'`
|
||||
* is always the implicit terminal state — `destroy()` transitions there
|
||||
* unconditionally and all subsequent `send()` calls are no-ops.
|
||||
*
|
||||
* When a state declares `onSettled`, the framework calls `runner.whenSettled()`
|
||||
* after the handler returns. The runner owns the generation-token logic — if
|
||||
* new tasks are scheduled before the current batch settles, the callback is
|
||||
* automatically superseded.
|
||||
*
|
||||
* @example
|
||||
* const actor = createMachineActor({
|
||||
* runner: () => new SerialRunner(),
|
||||
* initial: 'idle',
|
||||
* context: {},
|
||||
* states: {
|
||||
* idle: {
|
||||
* on: {
|
||||
* load: (msg, { transition, runner }) => {
|
||||
* segments.forEach(s => runner.schedule(new Task(...)));
|
||||
* transition('loading');
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* loading: {
|
||||
* onSettled: 'idle',
|
||||
* on: {
|
||||
* load: (msg, { runner }) => {
|
||||
* runner.abortAll();
|
||||
* segments.forEach(s => runner.schedule(new Task(...)));
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
declare function createMachineActor<UserState extends string, Context extends object, Message extends {
|
||||
type: string;
|
||||
}, RunnerFactory extends (() => RunnerLike) | undefined = undefined>(def: ActorDefinition<UserState, Context, Message, RunnerFactory>): MessageActor<UserState | 'destroyed', Context, Message>;
|
||||
//#endregion
|
||||
export { ActorDefinition, ActorStateDefinition, HandlerContext, MessageActor, RunnerLike, createMachineActor };
|
||||
//# sourceMappingURL=create-machine-actor.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"create-machine-actor.d.ts","names":[],"sources":["../../../../src/core/actors/create-machine-actor.ts"],"mappings":";;;;;;UAYiB;EACf,SAAS,cAAc,eAAe,MAAM,SAAS,OAAO,OAAO,QAAQ;EAC3E;EACA;EACA,YAAY;;;;;;;KAYF,eACV,0BACA,wBACA,6BAA6B;EAE7B,aAAa,IAAI;;EAEjB,SAAS;;;;;;;EAOT,kBAAkB;EAClB,aAAa,MAAM;KAChB,mCAAkC;EAAM,QAAQ;;;;;KAKzC,qBACV,0BACA,wBACA;EAAkB;GAClB,6BAA6B;;;;;;;EAQ7B,YAAY;;EAEZ,QACG,KAAK,WAAW,cACf,SAAS,QAAQ;IAAW,MAAM;MAClC,KAAK,eAAe,WAAW,SAAS;;;;;;;;KAWlC,gBACV,0BACA,wBACA;EAAkB;GAClB,6BAA6B;;;;;;;;EAS7B,SAAS;;EAET,SAAS;;EAET,SAAS;;;;;EAKT,QAAQ,QAAQ,OAAO,WAAW,qBAAqB,WAAW,SAAS,SAAS;;;UAQrE,aAAa,sBAAsB,wBAAwB;EAAkB;WACpF,YAAY,OAAO;EAC3B,KAAK,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8CA,mBACd,0BACA,wBACA;EAAkB;GAClB,6BAA6B,qCAE7B,KAAK,gBAAgB,WAAW,SAAS,SAAS,iBACjD,aAAa,yBAAyB,SAAS"}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
import { untrack, update } from "../signals/primitives.js";
|
||||
import { createMachineCore } from "../machine.js";
|
||||
//#region src/core/actors/create-machine-actor.ts
|
||||
/**
|
||||
* Creates a message-driven actor from a declarative definition.
|
||||
*
|
||||
* The actor owns a reactive snapshot signal (state + context), an optional
|
||||
* runner, and dispatches incoming messages to per-state handlers. `'destroyed'`
|
||||
* is always the implicit terminal state — `destroy()` transitions there
|
||||
* unconditionally and all subsequent `send()` calls are no-ops.
|
||||
*
|
||||
* When a state declares `onSettled`, the framework calls `runner.whenSettled()`
|
||||
* after the handler returns. The runner owns the generation-token logic — if
|
||||
* new tasks are scheduled before the current batch settles, the callback is
|
||||
* automatically superseded.
|
||||
*
|
||||
* @example
|
||||
* const actor = createMachineActor({
|
||||
* runner: () => new SerialRunner(),
|
||||
* initial: 'idle',
|
||||
* context: {},
|
||||
* states: {
|
||||
* idle: {
|
||||
* on: {
|
||||
* load: (msg, { transition, runner }) => {
|
||||
* segments.forEach(s => runner.schedule(new Task(...)));
|
||||
* transition('loading');
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* loading: {
|
||||
* onSettled: 'idle',
|
||||
* on: {
|
||||
* load: (msg, { runner }) => {
|
||||
* runner.abortAll();
|
||||
* segments.forEach(s => runner.schedule(new Task(...)));
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function createMachineActor(def) {
|
||||
const runner = def.runner?.();
|
||||
const { snapshotSignal, getState, transition } = createMachineCore({
|
||||
value: def.initial,
|
||||
context: def.context
|
||||
});
|
||||
const getContext = () => untrack(() => snapshotSignal.get().context);
|
||||
const setContext = (context) => {
|
||||
update(snapshotSignal, { context });
|
||||
};
|
||||
return {
|
||||
get snapshot() {
|
||||
return snapshotSignal;
|
||||
},
|
||||
send(message) {
|
||||
const state = getState();
|
||||
if (state === "destroyed") return;
|
||||
const handler = def.states[state]?.on?.[message.type];
|
||||
if (!handler) return;
|
||||
handler(message, {
|
||||
context: getContext(),
|
||||
getContext,
|
||||
transition: (to) => transition(to),
|
||||
setContext,
|
||||
...runner ? { runner } : {}
|
||||
});
|
||||
const newState = getState();
|
||||
if (newState !== "destroyed") {
|
||||
const newStateDef = def.states[newState];
|
||||
if (newStateDef?.onSettled && runner) {
|
||||
const targetState = newStateDef.onSettled;
|
||||
runner.whenSettled(() => {
|
||||
if (getState() !== newState) return;
|
||||
transition(targetState);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
destroy() {
|
||||
if (getState() === "destroyed") return;
|
||||
runner?.destroy();
|
||||
transition("destroyed");
|
||||
}
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
export { createMachineActor };
|
||||
|
||||
//# sourceMappingURL=create-machine-actor.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,41 @@
|
||||
import { ActorSnapshot } from "./actor.js";
|
||||
import { Machine } from "../machine.js";
|
||||
//#region src/core/actors/create-transition-actor.d.ts
|
||||
/**
|
||||
* A reducer-shaped actor: `(context, message) => context`.
|
||||
*
|
||||
* No finite states — the snapshot carries `value: 'active' | 'destroyed'`
|
||||
* as a universal lifecycle marker rather than domain state. The interesting
|
||||
* state is entirely in the context, which is reactive via `snapshot`.
|
||||
*
|
||||
* Use this when the actor has context that needs to be reactive but no
|
||||
* meaningful state machine (e.g., a message-driven model with DOM side
|
||||
* effects). For actors that need per-state behavior, use `createMachineActor`.
|
||||
*/
|
||||
interface TransitionActor<Context extends object, Message extends {
|
||||
type: string;
|
||||
}> extends Machine<ActorSnapshot<'active' | 'destroyed', Context>> {
|
||||
send(message: Message): void;
|
||||
}
|
||||
/**
|
||||
* Creates a reducer-shaped actor from an initial context and a reducer function.
|
||||
*
|
||||
* The reducer receives the current context and a message and returns the next
|
||||
* context. Returning the same reference (by identity) skips the signal update —
|
||||
* so early-returning `context` unchanged is both the no-op and the optimization.
|
||||
*
|
||||
* Side effects (e.g. DOM mutations) may be performed inside the reducer.
|
||||
* They run synchronously before the signal is updated.
|
||||
*
|
||||
* @example
|
||||
* const actor = createTransitionActor(
|
||||
* { count: 0 },
|
||||
* (context, message: { type: 'increment' }) => ({ count: context.count + 1 })
|
||||
* );
|
||||
*/
|
||||
declare function createTransitionActor<Context extends object, Message extends {
|
||||
type: string;
|
||||
}>(initialContext: Context, reducer: (context: Context, message: Message) => Context): TransitionActor<Context, Message>;
|
||||
//#endregion
|
||||
export { TransitionActor, createTransitionActor };
|
||||
//# sourceMappingURL=create-transition-actor.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"create-transition-actor.d.ts","names":[],"sources":["../../../../src/core/actors/create-transition-actor.ts"],"mappings":";;;;;;;;;;;;;;UAoBiB,gBAAgB,wBAAwB;EAAkB;WACjE,QAAQ,sCAAsC;EACtD,KAAK,SAAS;;;;;;;;;;;;;;;;;;iBAuBA,sBAAsB,wBAAwB;EAAkB;GAC9E,gBAAgB,SAChB,UAAU,SAAS,SAAS,SAAS,YAAY,UAChD,gBAAgB,SAAS"}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
import { untrack, update } from "../signals/primitives.js";
|
||||
import { createMachineCore } from "../machine.js";
|
||||
//#region src/core/actors/create-transition-actor.ts
|
||||
/**
|
||||
* Creates a reducer-shaped actor from an initial context and a reducer function.
|
||||
*
|
||||
* The reducer receives the current context and a message and returns the next
|
||||
* context. Returning the same reference (by identity) skips the signal update —
|
||||
* so early-returning `context` unchanged is both the no-op and the optimization.
|
||||
*
|
||||
* Side effects (e.g. DOM mutations) may be performed inside the reducer.
|
||||
* They run synchronously before the signal is updated.
|
||||
*
|
||||
* @example
|
||||
* const actor = createTransitionActor(
|
||||
* { count: 0 },
|
||||
* (context, message: { type: 'increment' }) => ({ count: context.count + 1 })
|
||||
* );
|
||||
*/
|
||||
function createTransitionActor(initialContext, reducer) {
|
||||
const { snapshotSignal, getState, transition } = createMachineCore({
|
||||
value: "active",
|
||||
context: initialContext
|
||||
});
|
||||
const getContext = () => untrack(() => snapshotSignal.get().context);
|
||||
const setContext = (context) => update(snapshotSignal, { context });
|
||||
return {
|
||||
get snapshot() {
|
||||
return snapshotSignal;
|
||||
},
|
||||
send(message) {
|
||||
if (getState() === "destroyed") return;
|
||||
const context = getContext();
|
||||
const newContext = reducer(context, message);
|
||||
if (newContext !== context) setContext(newContext);
|
||||
},
|
||||
destroy() {
|
||||
if (getState() === "destroyed") return;
|
||||
transition("destroyed");
|
||||
}
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
export { createTransitionActor };
|
||||
|
||||
//# sourceMappingURL=create-transition-actor.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"create-transition-actor.js","names":[],"sources":["../../../../src/core/actors/create-transition-actor.ts"],"sourcesContent":["import type { Machine } from '../machine';\nimport { createMachineCore } from '../machine';\nimport { untrack, update } from '../signals/primitives';\nimport type { ActorSnapshot } from './actor';\n\n// =============================================================================\n// Definition types\n// =============================================================================\n\n/**\n * A reducer-shaped actor: `(context, message) => context`.\n *\n * No finite states — the snapshot carries `value: 'active' | 'destroyed'`\n * as a universal lifecycle marker rather than domain state. The interesting\n * state is entirely in the context, which is reactive via `snapshot`.\n *\n * Use this when the actor has context that needs to be reactive but no\n * meaningful state machine (e.g., a message-driven model with DOM side\n * effects). For actors that need per-state behavior, use `createMachineActor`.\n */\nexport interface TransitionActor<Context extends object, Message extends { type: string }>\n extends Machine<ActorSnapshot<'active' | 'destroyed', Context>> {\n send(message: Message): void;\n}\n\n// =============================================================================\n// Implementation\n// =============================================================================\n\n/**\n * Creates a reducer-shaped actor from an initial context and a reducer function.\n *\n * The reducer receives the current context and a message and returns the next\n * context. Returning the same reference (by identity) skips the signal update —\n * so early-returning `context` unchanged is both the no-op and the optimization.\n *\n * Side effects (e.g. DOM mutations) may be performed inside the reducer.\n * They run synchronously before the signal is updated.\n *\n * @example\n * const actor = createTransitionActor(\n * { count: 0 },\n * (context, message: { type: 'increment' }) => ({ count: context.count + 1 })\n * );\n */\nexport function createTransitionActor<Context extends object, Message extends { type: string }>(\n initialContext: Context,\n reducer: (context: Context, message: Message) => Context\n): TransitionActor<Context, Message> {\n const { snapshotSignal, getState, transition } = createMachineCore<\n 'active' | 'destroyed',\n ActorSnapshot<'active' | 'destroyed', Context>\n >({ value: 'active', context: initialContext });\n\n const getContext = (): Context => untrack(() => snapshotSignal.get().context);\n const setContext = (context: Context): void => update(snapshotSignal, { context });\n\n return {\n get snapshot() {\n return snapshotSignal;\n },\n\n send(message: Message): void {\n if (getState() === 'destroyed') return;\n const context = getContext();\n const newContext = reducer(context, message);\n if (newContext !== context) setContext(newContext);\n },\n\n destroy(): void {\n if (getState() === 'destroyed') return;\n transition('destroyed');\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA6CA,SAAgB,sBACd,gBACA,SACmC;CACnC,MAAM,EAAE,gBAAgB,UAAU,eAAe,kBAG/C;EAAE,OAAO;EAAU,SAAS;CAAe,CAAC;CAE9C,MAAM,mBAA4B,cAAc,eAAe,IAAI,CAAC,CAAC,OAAO;CAC5E,MAAM,cAAc,YAA2B,OAAO,gBAAgB,EAAE,QAAQ,CAAC;CAEjF,OAAO;EACL,IAAI,WAAW;GACb,OAAO;EACT;EAEA,KAAK,SAAwB;GAC3B,IAAI,SAAS,MAAM,aAAa;GAChC,MAAM,UAAU,WAAW;GAC3B,MAAM,aAAa,QAAQ,SAAS,OAAO;GAC3C,IAAI,eAAe,SAAS,WAAW,UAAU;EACnD;EAEA,UAAgB;GACd,IAAI,SAAS,MAAM,aAAa;GAChC,WAAW,WAAW;EACxB;CACF;AACF"}
|
||||
Reference in New Issue
Block a user