1
0
mirror of https://github.com/robonen/tools.git synced 2026-03-20 02:44:45 +00:00

Merge pull request #127 from robonen/stdlib-fix-reusing

refactor(core/stdlib): update state machine classes to use consistent property names and improve type safety
This commit is contained in:
2026-02-15 03:28:09 +07:00
committed by GitHub
3 changed files with 40 additions and 41 deletions

View File

@@ -1,3 +1,4 @@
import { isString } from '../../../types';
import { BaseStateMachine } from './base'; import { BaseStateMachine } from './base';
import type { AsyncStateNodeConfig, ExtractStates, ExtractEvents } from './types'; import type { AsyncStateNodeConfig, ExtractStates, ExtractEvents } from './types';
@@ -24,33 +25,33 @@ export class AsyncStateMachine<
* @returns The current state after processing the event * @returns The current state after processing the event
*/ */
async send(event: Events): Promise<States> { async send(event: Events): Promise<States> {
const stateNode = this._states[this._current]; const stateNode = this.states[this.currentState];
if (!stateNode?.on) if (!stateNode?.on)
return this._current; return this.currentState;
const transition = stateNode.on[event]; const transition = stateNode.on[event];
if (transition === undefined) if (transition === undefined)
return this._current; return this.currentState;
let target: string; let target: string;
if (typeof transition === 'string') { if (isString(transition)) {
target = transition; target = transition;
} else { } else {
if (transition.guard && !(await transition.guard(this._context))) if (transition.guard && !(await transition.guard(this.context)))
return this._current; return this.currentState;
await transition.action?.(this._context); await transition.action?.(this.context);
target = transition.target; target = transition.target;
} }
await stateNode.exit?.(this._context); await stateNode.exit?.(this.context);
this._current = target as States; this.currentState = target as States;
await this._states[this._current]?.entry?.(this._context); await this.states[this.currentState]?.entry?.(this.context);
return this._current; return this.currentState;
} }
/** /**
@@ -59,7 +60,7 @@ export class AsyncStateMachine<
* @param event - Event to check * @param event - Event to check
*/ */
async can(event: Events): Promise<boolean> { async can(event: Events): Promise<boolean> {
const stateNode = this._states[this._current]; const stateNode = this.states[this.currentState];
if (!stateNode?.on) if (!stateNode?.on)
return false; return false;
@@ -69,8 +70,8 @@ export class AsyncStateMachine<
if (transition === undefined) if (transition === undefined)
return false; return false;
if (typeof transition !== 'string' && transition.guard) if (!isString(transition) && transition.guard)
return await transition.guard(this._context); return await transition.guard(this.context);
return true; return true;
} }

View File

@@ -12,28 +12,25 @@ export class BaseStateMachine<
Context, Context,
NodeConfig, NodeConfig,
> { > {
protected _current: States; protected currentState: States;
protected _context: Context; protected readonly states: Record<string, NodeConfig>;
protected _states: Record<string, NodeConfig>;
/** Machine context */
readonly context: Context;
constructor( constructor(
initial: States, initial: States,
states: Record<string, NodeConfig>, states: Record<string, NodeConfig>,
context: Context, context: Context,
) { ) {
this._current = initial; this.currentState = initial;
this._context = context; this.context = context;
this._states = states; this.states = states;
} }
/** Current state of the machine */ /** Current state of the machine */
get current(): States { get current(): States {
return this._current; return this.currentState;
}
/** Machine context */
get context(): Context {
return this._context;
} }
/** /**
@@ -42,6 +39,6 @@ export class BaseStateMachine<
* @param state - State to check * @param state - State to check
*/ */
matches(state: States): boolean { matches(state: States): boolean {
return this._current === state; return this.currentState === state;
} }
} }

View File

@@ -1,3 +1,4 @@
import { isString } from '../../../types';
import { BaseStateMachine } from './base'; import { BaseStateMachine } from './base';
import type { SyncStateNodeConfig, ExtractStates, ExtractEvents } from './types'; import type { SyncStateNodeConfig, ExtractStates, ExtractEvents } from './types';
@@ -24,33 +25,33 @@ export class StateMachine<
* @returns The current state after processing the event * @returns The current state after processing the event
*/ */
send(event: Events): States { send(event: Events): States {
const stateNode = this._states[this._current]; const stateNode = this.states[this.currentState];
if (!stateNode?.on) if (!stateNode?.on)
return this._current; return this.currentState;
const transition = stateNode.on[event]; const transition = stateNode.on[event];
if (transition === undefined) if (transition === undefined)
return this._current; return this.currentState;
let target: string; let target: string;
if (typeof transition === 'string') { if (isString(transition)) {
target = transition; target = transition;
} else { } else {
if (transition.guard && !transition.guard(this._context)) if (transition.guard && !transition.guard(this.context))
return this._current; return this.currentState;
transition.action?.(this._context); transition.action?.(this.context);
target = transition.target; target = transition.target;
} }
stateNode.exit?.(this._context); stateNode.exit?.(this.context);
this._current = target as States; this.currentState = target as States;
this._states[this._current]?.entry?.(this._context); this.states[this.currentState]?.entry?.(this.context);
return this._current; return this.currentState;
} }
/** /**
@@ -59,7 +60,7 @@ export class StateMachine<
* @param event - Event to check * @param event - Event to check
*/ */
can(event: Events): boolean { can(event: Events): boolean {
const stateNode = this._states[this._current]; const stateNode = this.states[this.currentState];
if (!stateNode?.on) if (!stateNode?.on)
return false; return false;
@@ -69,8 +70,8 @@ export class StateMachine<
if (transition === undefined) if (transition === undefined)
return false; return false;
if (typeof transition !== 'string' && transition.guard) if (!isString(transition) && transition.guard)
return transition.guard(this._context); return transition.guard(this.context);
return true; return true;
} }