fix: fix bug with types
This commit is contained in:
parent
a85702fd7b
commit
9a499d3e9b
4 changed files with 56 additions and 31 deletions
18
package-lock.json
generated
18
package-lock.json
generated
|
@ -465,6 +465,19 @@
|
||||||
"integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==",
|
"integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/lodash": {
|
||||||
|
"version": "4.14.144",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.144.tgz",
|
||||||
|
"integrity": "sha512-ogI4g9W5qIQQUhXAclq6zhqgqNUr7UlFaqDHbch7WLSLeeM/7d3CRaw7GLajxvyFvhJqw4Rpcz5bhoaYtIx6Tg=="
|
||||||
|
},
|
||||||
|
"@types/lodash.clonedeep": {
|
||||||
|
"version": "4.5.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.6.tgz",
|
||||||
|
"integrity": "sha512-cE1jYr2dEg1wBImvXlNtp0xDoS79rfEdGozQVgliDZj1uERH4k+rmEMTudP9b4VQ8O6nRb5gPqft0QzEQGMQgA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/lodash": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/stack-utils": {
|
"@types/stack-utils": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
|
||||||
|
@ -3279,6 +3292,11 @@
|
||||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"lodash.clonedeep": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||||
|
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
|
||||||
|
},
|
||||||
"lodash.memoize": {
|
"lodash.memoize": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "it-fsm",
|
"name": "it-fsm",
|
||||||
"version": "1.0.3",
|
"version": "1.0.4",
|
||||||
"description": "Simple finite state machine for nodejs",
|
"description": "Simple finite state machine for nodejs",
|
||||||
"main": "./src/index.js",
|
"main": "./src/index.js",
|
||||||
"types": "./src/index.d.ts",
|
"types": "./src/index.d.ts",
|
||||||
|
@ -36,9 +36,13 @@
|
||||||
"homepage": "https://github.com/icetemple/npm-it-fsm#readme",
|
"homepage": "https://github.com/icetemple/npm-it-fsm#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^24.0.15",
|
"@types/jest": "^24.0.15",
|
||||||
|
"@types/lodash.clonedeep": "^4.5.6",
|
||||||
"coveralls": "^3.0.5",
|
"coveralls": "^3.0.5",
|
||||||
"jest": "^24.8.0",
|
"jest": "^24.8.0",
|
||||||
"ts-jest": "^24.0.2",
|
"ts-jest": "^24.0.2",
|
||||||
"typescript": "^3.5.3"
|
"typescript": "^3.5.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lodash.clonedeep": "^4.5.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
62
src/index.ts
62
src/index.ts
|
@ -1,16 +1,16 @@
|
||||||
|
import cloneDeep from 'lodash.clonedeep';
|
||||||
|
|
||||||
export type Payload = Record<string, any>
|
export type Payload = Record<string, any>
|
||||||
export type StateType = string | number
|
export type StateType = string | number
|
||||||
export type ActionConfigMap = Record<string, StateType | IActionConfig>
|
export type ActionConfigMap = Record<string, StateType | IActionConfig>
|
||||||
export type ActionEvent = (event: string, fromState: string, toState: string,
|
export type ActionEvent = (event: string, fromState: StateType, toState: StateType,
|
||||||
payload: Payload) => Promise<any>
|
payload: Payload) => Promise<any>
|
||||||
|
|
||||||
|
|
||||||
export interface IConfig {
|
export interface IConfig {
|
||||||
[key: string]: ActionEvent | ActionConfigMap
|
[key: string]: undefined | ActionEvent | ActionConfigMap
|
||||||
onEnter: ActionEvent
|
onEnter?: ActionEvent
|
||||||
onLeave: ActionEvent
|
onLeave?: ActionEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IActionConfig {
|
export interface IActionConfig {
|
||||||
|
@ -23,54 +23,58 @@ export interface IActionConfig {
|
||||||
export class StateMachine {
|
export class StateMachine {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
|
|
||||||
private _currentState: string;
|
private _currentState: StateType;
|
||||||
private _onEnter: ActionEvent;
|
private _onEnter?: ActionEvent;
|
||||||
private _onLeave: ActionEvent;
|
private _onLeave?: ActionEvent;
|
||||||
private _eventsByState: Record<string, Record<string, (payload: Payload) => any>> = {};
|
private _eventsByState: Record<string, Record<string, (payload: Payload) => any>> = {};
|
||||||
private _statesByState: Record<string, string[]> = {};
|
private _statesByState: Record<string, StateType[]> = {};
|
||||||
|
|
||||||
constructor(initial: StateType, config: IConfig) {
|
constructor(initial: StateType, config: IConfig) {
|
||||||
this._currentState = initial.toString();
|
this._currentState = initial;
|
||||||
|
|
||||||
for (let fromState in config) {
|
for (let fromStateKey in config) {
|
||||||
if (['onEnter', 'onLeave'].includes(fromState)) {
|
if (['onEnter', 'onLeave'].includes(fromStateKey)) {
|
||||||
this._onEnter = config.onEnter;
|
this._onEnter = config.onEnter;
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
this._statesByState[fromState] = [];
|
this._statesByState[fromStateKey] = [];
|
||||||
|
|
||||||
let actions = config[fromState] as ActionConfigMap;
|
let actions = config[fromStateKey] as ActionConfigMap;
|
||||||
for (let actionName in actions) {
|
for (let actionName in actions) {
|
||||||
let action = actions[actionName];
|
let action = actions[actionName];
|
||||||
let actionConfig: IActionConfig = action.constructor === Object ?
|
let actionConfig: IActionConfig = action.constructor === Object ?
|
||||||
action as IActionConfig
|
action as IActionConfig
|
||||||
: { state: action as StateType };
|
: { state: action as StateType };
|
||||||
|
|
||||||
this._statesByState[fromState].push(actionConfig.state.toString());
|
this._statesByState[fromStateKey].push(actionConfig.state);
|
||||||
this._initChangeState(actionName, fromState, actionConfig.state.toString(), actionConfig);
|
|
||||||
|
let fromState: StateType = /^\d+$/.test(fromStateKey) ? parseInt(fromStateKey, 10) : fromStateKey;
|
||||||
|
this._initChangeState(actionName, fromState, actionConfig.state, actionConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _initChangeState(eventName: string, fromState: string, toState: string, actionConfig: IActionConfig): void {
|
|
||||||
|
private _initChangeState(eventName: string, fromState: StateType, toState: StateType, actionConfig: IActionConfig): void {
|
||||||
if (!this._eventsByState[fromState]) {
|
if (!this._eventsByState[fromState]) {
|
||||||
this._eventsByState[fromState] = {};
|
this._eventsByState[fromState] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const { onBeforeChange, onChange } = actionConfig;
|
const { onBeforeChange, onChange } = actionConfig;
|
||||||
|
const _runEvent = async (method?: ActionEvent, payload: Payload = {}): Promise<void> => {
|
||||||
this._eventsByState[fromState][eventName] = async (payload: Payload = {}) => {
|
if (method) {
|
||||||
console.log(this._currentState, typeof this._currentState, fromState, typeof fromState);
|
await method(eventName, fromState, toState, payload);
|
||||||
if (this._currentState !== fromState) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this._onEnter && await this._onEnter(eventName, fromState, toState, payload);
|
this._eventsByState[fromState][eventName] = async (sourcePayload: Payload = {}) => {
|
||||||
onBeforeChange && await onBeforeChange(eventName, fromState, toState, payload);
|
const payload = cloneDeep(sourcePayload);
|
||||||
|
await _runEvent(this._onEnter, payload);
|
||||||
|
await _runEvent(onBeforeChange, payload);
|
||||||
this._currentState = toState;
|
this._currentState = toState;
|
||||||
onChange && await onChange(eventName, fromState, toState, payload);
|
await _runEvent(onChange, payload);
|
||||||
this._onLeave && await this._onLeave(eventName, fromState, toState, payload)
|
await _runEvent(this._onLeave, payload);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
@ -81,13 +85,11 @@ export class StateMachine {
|
||||||
&& this._eventsByState[this._currentState][eventName]) {
|
&& this._eventsByState[this._currentState][eventName]) {
|
||||||
return this._eventsByState[this._currentState][eventName](payload);
|
return this._eventsByState[this._currentState][eventName](payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(this._eventsByState, this._currentState, eventName)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getCurrentState(): string {
|
public getCurrentState(): StateType {
|
||||||
return this._currentState;
|
return this._currentState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +102,7 @@ export class StateMachine {
|
||||||
return Object.keys(events).includes(eventName);
|
return Object.keys(events).includes(eventName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public canToState(stateName: string) {
|
public canToState(stateName: StateType) {
|
||||||
const states = this._statesByState[this._currentState];
|
const states = this._statesByState[this._currentState];
|
||||||
if (!states) {
|
if (!states) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
"noImplicitThis": true,
|
"noImplicitThis": true,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
"outDir": "./src"
|
"outDir": "./src"
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|
Loading…
Reference in a new issue