typescript-state-machine
Advanced tools
Comparing version 0.9.0 to 0.9.1
@@ -27,4 +27,4 @@ export declare namespace fsm { | ||
}; | ||
protected checkInState(state: T, message?: string): void; | ||
protected checkInOneOfStates(states: T[], message?: string): void; | ||
checkInState(state: T, message?: string): void; | ||
checkInOneOfStates(states: T[], message?: string): void; | ||
protected inOneOfStates(states: T[]): boolean; | ||
@@ -31,0 +31,0 @@ protected inState(state: T): boolean; |
@@ -1,2 +0,2 @@ | ||
import { getLogger } from "log4javascript"; | ||
import { getLogger } from 'log4javascript'; | ||
export var fsm; | ||
@@ -47,3 +47,3 @@ (function (fsm) { | ||
if (!this.inState(state)) { | ||
throw new Error(message || "Expected to be in " + state + " but was in " + this.state); | ||
throw new Error(message || 'Expected to be in ' + state + ' but was in ' + this.state); | ||
} | ||
@@ -53,7 +53,7 @@ }; | ||
if (!this.inOneOfStates(states)) { | ||
throw new Error(message || "Expected to be in one of " + states + " but was in " + this.state); | ||
throw new Error(message || 'Expected to be in one of ' + states + ' but was in ' + this.state); | ||
} | ||
}; | ||
StateMachineImpl.prototype.inOneOfStates = function (states) { | ||
return (states.indexOf(this._state) != -1); | ||
return (states.indexOf(this._state) !== -1); | ||
}; | ||
@@ -82,3 +82,3 @@ StateMachineImpl.prototype.inState = function (state) { | ||
catch (e) { | ||
this.log.warn("Uncaught error in listener :" + e); | ||
this.log.warn('Uncaught error in listener :' + e); | ||
} | ||
@@ -95,3 +95,3 @@ } | ||
StateMachineImpl.prototype.transitionLabel = function (fromState, toState) { | ||
return ((fromState && fromState.label) || "*") + " --> " + ((toState && toState.label) || "*"); | ||
return ((fromState && fromState.label) || '*') + ' --> ' + ((toState && toState.label) || '*'); | ||
}; | ||
@@ -101,3 +101,3 @@ StateMachineImpl.prototype.waitUntilLeft = function (state) { | ||
return new Promise(function (resolve) { | ||
if (_this._state != state) { | ||
if (_this._state !== state) { | ||
resolve(_this._state); | ||
@@ -119,3 +119,3 @@ } | ||
return new Promise(function (resolve) { | ||
if (states.indexOf(_this._state) != -1) { | ||
if (states.indexOf(_this._state) !== -1) { | ||
resolve(_this._state); | ||
@@ -160,7 +160,7 @@ } | ||
if (!this.canGoToState(newState)) { | ||
throw new Error("Invalid transition from " + this._state + " to " + newState); | ||
throw new Error('Invalid transition from ' + this._state + ' to ' + newState); | ||
} | ||
}; | ||
StateMachineImpl.prototype.canGoToState = function (newState) { | ||
return this.validTransitions[this._state.label].indexOf(newState) != -1; | ||
return this.validTransitions[this._state.label].indexOf(newState) !== -1; | ||
}; | ||
@@ -177,3 +177,3 @@ return StateMachineImpl; | ||
if (_this.parent) { | ||
return _this.parent.toString() + "/" + _this.label; | ||
return _this.parent.toString() + '/' + _this.label; | ||
} | ||
@@ -185,2 +185,3 @@ else { | ||
} | ||
// noinspection JSUnusedGlobalSymbols | ||
State.prototype.userFriendlyDescription = function () { | ||
@@ -202,6 +203,6 @@ return this.label; | ||
// Decorators | ||
var log = getLogger("fsm.decorators"); | ||
var log = getLogger('fsm.decorators'); | ||
/* | ||
Method annotator. Throw an error if the state when the method is called | ||
is different from the given state | ||
Method annotator. Throw an error if the state when the method is called | ||
is different from the given state | ||
*/ | ||
@@ -213,7 +214,7 @@ function CheckStateIs(state, message) { | ||
var context = this; | ||
if (context.state == state) { | ||
if (context.state === state) { | ||
originalMethod.apply(context, arguments); | ||
} | ||
else { | ||
throw new Error(message || "Illegal execution of " + propertyKey + " : State should be " + state + " but state = " + context.state); | ||
throw new Error(message || 'Illegal execution of ' + propertyKey + ' : State should be ' + state + ' but state = ' + context.state); | ||
} | ||
@@ -226,4 +227,4 @@ }; | ||
/* | ||
Method annotator. Throw an error if the state when the method is called | ||
is not one of the given states | ||
Method annotator. Throw an error if the state when the method is called | ||
is not one of the given states | ||
*/ | ||
@@ -237,7 +238,7 @@ function CheckStateIn(states, message) { | ||
var context = this; | ||
if (states.indexOf(context.state) != -1) { | ||
if (states.indexOf(context.state) !== -1) { | ||
return originalMethod.apply(context, arguments); | ||
} | ||
else { | ||
throw new Error(message || "Illegal execution of " + propertyKey + " : State should be one of " + states + " but state = " + context.state); | ||
throw new Error(message || 'Illegal execution of ' + propertyKey + ' : State should be one of ' + states + ' but state = ' + context.state); | ||
} | ||
@@ -250,7 +251,7 @@ }; | ||
var context = this; | ||
if (states.indexOf(context.state) != -1) { | ||
if (states.indexOf(context.state) !== -1) { | ||
return originalGetter_1.apply(context, arguments); | ||
} | ||
else { | ||
throw new Error(message || "Illegal execution of " + propertyKey + " : State should be one of " + states + " but state = " + context.state); | ||
throw new Error(message || 'Illegal execution of ' + propertyKey + ' : State should be one of ' + states + ' but state = ' + context.state); | ||
} | ||
@@ -264,5 +265,5 @@ }; | ||
/* | ||
Method annotator. Skip the method execution if the state when the method is called | ||
is different from the given state | ||
*/ | ||
Method annotator. Skip the method execution if the state when the method is called | ||
is different from the given state | ||
*/ | ||
function AssumeStateIs(state) { | ||
@@ -273,7 +274,7 @@ return function (target, propertyKey, descriptor) { | ||
var context = this; | ||
if (context.state == state) { | ||
if (context.state === state) { | ||
originalMethod.apply(context, arguments); | ||
} | ||
else { | ||
log.warn("Skipping execution of " + propertyKey + " : State should be " + state + " but state = " + context.state); | ||
log.warn('Skipping execution of ' + propertyKey + ' : State should be ' + state + ' but state = ' + context.state); | ||
} | ||
@@ -286,5 +287,5 @@ }; | ||
/* | ||
Method annotator. Skip the method execution if the state when the method is called | ||
is the same as the given state | ||
*/ | ||
Method annotator. Skip the method execution if the state when the method is called | ||
is the same as the given state | ||
*/ | ||
function AssumeStateIsNot(state) { | ||
@@ -295,7 +296,7 @@ return function (target, propertyKey, descriptor) { | ||
var context = this; | ||
if (context.state != state) { | ||
if (context.state !== state) { | ||
originalMethod.apply(context, arguments); | ||
} | ||
else { | ||
log.warn("Skipping execution of " + propertyKey + " : State should be different from " + state); | ||
log.warn('Skipping execution of ' + propertyKey + ' : State should be different from ' + state); | ||
} | ||
@@ -302,0 +303,0 @@ }; |
{ | ||
"name": "typescript-state-machine", | ||
"version": "0.9.0", | ||
"version": "0.9.1", | ||
"description": "", | ||
@@ -19,3 +19,4 @@ "main": "dist/index.js", | ||
"prepublish": "npm run build", | ||
"build": "tsc" | ||
"build": "npm run tslint && tsc", | ||
"tslint": "tslint src/*" | ||
}, | ||
@@ -27,4 +28,7 @@ "homepage": "https://github.com/taktik/typescript-state-machine#readme", | ||
"devDependencies": { | ||
"typescript": "^3.1.4" | ||
"tslint": "^5.11.0", | ||
"tslint-config-standard": "^8.0.1", | ||
"typescript": "^3.1.6", | ||
"typescript-eslint-parser": "^20.1.1" | ||
} | ||
} |
585
src/index.ts
@@ -1,340 +0,339 @@ | ||
import {getLogger} from "log4javascript"; | ||
import { getLogger } from 'log4javascript' | ||
export namespace fsm { | ||
export interface StateMachine<T extends State> { | ||
/* Get the current state of the fsm */ | ||
readonly state: T | ||
export interface StateMachine<T extends State> { | ||
/* Get the current state of the fsm */ | ||
readonly state: T; | ||
/* | ||
Listen for state changes. The callback will be called once when the fsm enters the given state. | ||
@param callBack The callBack that will be called | ||
*/ | ||
onEnterState (state: T, callBack: (from: T, to: T) => void): ListenerRegistration | ||
/* | ||
Listen for state changes. The callback will be called once when the fsm enters the given state. | ||
/* | ||
Listen for state changes. The callback will be called once when the fsm leaves the given state. | ||
@param callBack The callBack that will be called | ||
*/ | ||
onLeaveState (state: T, callBack: (from: T, to: T) => void): ListenerRegistration | ||
@param callBack The callBack that will be called | ||
*/ | ||
onEnterState(state: T, callBack: (from: T, to: T) => void): ListenerRegistration; | ||
/* | ||
Listen for state changes. The callback will be called once when the fsm leaves the given fromState and enters the given toState. | ||
@param callBack The callBack that will be called | ||
*/ | ||
onTransition (fromState: T, toState: T, callBack: (from: T, to: T) => void): ListenerRegistration | ||
/* | ||
Listen for state changes. The callback will be called once when the fsm leaves the given state. | ||
onAnyTransition (callBack: (from: T, to: T) => void): ListenerRegistration | ||
@param callBack The callBack that will be called | ||
*/ | ||
onLeaveState(state: T, callBack: (from: T, to: T) => void): ListenerRegistration; | ||
/* | ||
Wait for state changes. | ||
*/ | ||
waitUntilLeft (state: T): Promise<T> | ||
/* | ||
Listen for state changes. The callback will be called once when the fsm leaves the given fromState and enters the given toState. | ||
waitUntilEntered (state: T): Promise<T> | ||
@param callBack The callBack that will be called | ||
*/ | ||
onTransition(fromState: T, toState: T, callBack: (from: T, to: T) => void): ListenerRegistration; | ||
onAnyTransition(callBack: (from: T, to: T) => void): ListenerRegistration; | ||
waitUntilEnteredOneOf (states: [T]): Promise<T> | ||
/* | ||
Wait for state changes. | ||
*/ | ||
waitUntilLeft(state: T): Promise<T>; | ||
waitUntilEntered(state: T): Promise<T>; | ||
waitUntilEnteredOneOf(states: [T]): Promise<T>; | ||
} | ||
} | ||
export class StateMachineImpl<T extends State> implements StateMachine<T> { | ||
readonly states: T[] | ||
readonly validTransitions: Transitions<T> | ||
protected _state: T | ||
private readonly _transitionListeners: TransitionListeners<T> | ||
protected log = getLogger(this.constructor.name) | ||
export class StateMachineImpl<T extends State> implements StateMachine<T> { | ||
readonly states:T[]; | ||
readonly validTransitions: Transitions<T>; | ||
protected _state: T; | ||
private readonly _transitionListeners: TransitionListeners<T>; | ||
protected log = getLogger(this.constructor.name); | ||
constructor (states: T[], validTransitions: Transitions<T>, initialState: T) { | ||
this.states = states | ||
this.validTransitions = validTransitions | ||
this._state = initialState | ||
this._transitionListeners = {} | ||
} | ||
get state (): T { | ||
return this._state | ||
} | ||
constructor(states:T[], validTransitions: Transitions<T>, initialState:T) { | ||
this.states = states; | ||
this.validTransitions = validTransitions; | ||
this._state = initialState; | ||
this._transitionListeners = {}; | ||
} | ||
onEnterState (state: T, callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, undefined, state) | ||
} | ||
get state(): T { | ||
return this._state; | ||
} | ||
onLeaveState (state: T, callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, state, undefined) | ||
} | ||
onEnterState(state: T, callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, undefined, state); | ||
} | ||
onTransition (fromState: T, toState: T, callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, fromState, toState) | ||
} | ||
onLeaveState(state: T, callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, state, undefined); | ||
} | ||
onAnyTransition (callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, undefined, undefined) | ||
} | ||
onTransition(fromState: T, toState: T, callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, fromState, toState); | ||
} | ||
protected addTransitionListener (callBack: (from: T, to: T) => void, fromState?: T, toState?: T) { | ||
const transition = this.transitionLabel(fromState, toState) | ||
if (!this._transitionListeners[transition]) { | ||
this._transitionListeners[transition] = [] | ||
} | ||
const listenersForTransition = this._transitionListeners[transition] | ||
const transitionListener = new TransitionListener(callBack, fromState, toState) | ||
listenersForTransition.push(transitionListener) | ||
return { | ||
cancel (): void { | ||
transitionListener.active = false | ||
} | ||
} | ||
} | ||
onAnyTransition(callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, undefined, undefined); | ||
} | ||
checkInState (state: T, message?: string): void { | ||
if (!this.inState(state)) { | ||
throw new Error(message || 'Expected to be in ' + state + ' but was in ' + this.state) | ||
} | ||
} | ||
protected addTransitionListener(callBack: (from: T, to: T) => void, fromState?: T, toState?: T) { | ||
const transition = this.transitionLabel(fromState, toState); | ||
if (!this._transitionListeners[transition]) { | ||
this._transitionListeners[transition] = []; | ||
} | ||
const listenersForTransition = this._transitionListeners[transition]; | ||
const transitionListener = new TransitionListener(callBack, fromState, toState); | ||
listenersForTransition.push(transitionListener); | ||
return { | ||
cancel(): void { | ||
transitionListener.active = false; | ||
} | ||
} | ||
} | ||
checkInOneOfStates (states: T[], message?: string): void { | ||
if (!this.inOneOfStates(states)) { | ||
throw new Error(message || 'Expected to be in one of ' + states + ' but was in ' + this.state) | ||
} | ||
} | ||
protected checkInState(state: T, message?: string): void { | ||
if (!this.inState(state)) { | ||
throw new Error(message || "Expected to be in " + state + " but was in " + this.state); | ||
} | ||
} | ||
protected inOneOfStates (states: T[]): boolean { | ||
return (states.indexOf(this._state) !== -1) | ||
} | ||
protected checkInOneOfStates(states: T[], message?: string): void { | ||
if (!this.inOneOfStates(states)) { | ||
throw new Error(message || "Expected to be in one of " + states + " but was in " + this.state); | ||
} | ||
} | ||
protected inState (state: T): boolean { | ||
return this._state === state | ||
} | ||
protected inOneOfStates(states: T[]): boolean { | ||
return (states.indexOf(this._state) != -1); | ||
} | ||
private invokeAllTransitionListeners (fromState: T, toState: T) { | ||
const allLeaveTransitions = this.transitionLabel(fromState, undefined) | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[allLeaveTransitions]) | ||
const transition = this.transitionLabel(fromState, toState) | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[transition]) | ||
const allEnterTransitions = this.transitionLabel(undefined, toState) | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[allEnterTransitions]) | ||
const allTransitions = this.transitionLabel(undefined, undefined) | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[allTransitions]) | ||
} | ||
protected inState(state: T): boolean { | ||
return this._state === state; | ||
} | ||
private invokeTransitionListeners (fromState: T, toState: T, listeners?: TransitionListener<T>[]) { | ||
if (listeners) { | ||
for (let index = 0; index < listeners.length; index++) { | ||
const listener = listeners[index] | ||
if (listener.active) { | ||
try { | ||
listener.callBack(fromState, toState) | ||
} catch (e) { | ||
this.log.warn('Uncaught error in listener :' + e) | ||
} | ||
} else { | ||
// Remove inactive listener | ||
listeners.splice(index, 1) | ||
index-- | ||
} | ||
} | ||
} | ||
} | ||
private invokeAllTransitionListeners(fromState: T, toState: T) { | ||
const allLeaveTransitions = this.transitionLabel(fromState, undefined); | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[allLeaveTransitions]); | ||
const transition = this.transitionLabel(fromState, toState); | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[transition]); | ||
const allEnterTransitions = this.transitionLabel(undefined, toState); | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[allEnterTransitions]); | ||
const allTransitions = this.transitionLabel(undefined, undefined); | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[allTransitions]); | ||
} | ||
private transitionLabel (fromState?: T, toState?: T) { | ||
return ((fromState && fromState.label) || '*') + ' --> ' + ((toState && toState.label) || '*') | ||
} | ||
private invokeTransitionListeners(fromState: T, toState: T, listeners?: TransitionListener<T>[]) { | ||
if (listeners) { | ||
for (let index = 0; index < listeners.length; index++) { | ||
const listener = listeners[index]; | ||
if (listener.active) { | ||
try { | ||
listener.callBack(fromState, toState); | ||
} catch (e) { | ||
this.log.warn("Uncaught error in listener :" + e) | ||
} | ||
} else { | ||
// Remove inactive listener | ||
listeners.splice(index, 1); | ||
index--; | ||
} | ||
} | ||
} | ||
} | ||
waitUntilLeft (state: T): Promise<T> { | ||
return new Promise<T>((resolve) => { | ||
if (this._state !== state) { | ||
resolve(this._state) | ||
} else { | ||
const registration = this.onLeaveState(state, (from, to) => { | ||
registration.cancel() | ||
resolve(to) | ||
}) | ||
} | ||
}) | ||
} | ||
private transitionLabel(fromState?: T, toState?: T) { | ||
return ((fromState && fromState.label) || "*") + " --> " + ((toState && toState.label) || "*"); | ||
} | ||
waitUntilEntered (state: T): Promise<T> { | ||
return this.waitUntilEnteredOneOf([state]) | ||
} | ||
waitUntilEnteredOneOf (states: T[]): Promise<T> { | ||
return new Promise<T>((resolve) => { | ||
if (states.indexOf(this._state) !== -1) { | ||
resolve(this._state) | ||
} else { | ||
const registrations: ListenerRegistration[] = [] | ||
let finished = false | ||
for (let state of states) { | ||
let registration = this.onEnterState(state, (from, to) => { | ||
registration.cancel() | ||
registrations.forEach(reg => { | ||
if (registration !== reg) { | ||
reg.cancel() | ||
} | ||
}) | ||
finished = true | ||
resolve(to) | ||
}) | ||
if (finished) { | ||
break | ||
} | ||
registrations.push(registration) | ||
} | ||
} | ||
}) | ||
} | ||
waitUntilLeft(state: T): Promise<T> { | ||
return new Promise<T>((resolve) => { | ||
if (this._state != state) { | ||
resolve(this._state); | ||
} else { | ||
const registration = this.onLeaveState(state, (from, to) => { | ||
registration.cancel(); | ||
resolve(to); | ||
}) | ||
} | ||
}); | ||
} | ||
setState (newState: T) { | ||
this.checkTransition(newState) | ||
this.log.debug(`State : ${this._state} --> ${newState}`) | ||
const oldState = this._state | ||
this._state = newState | ||
waitUntilEntered(state: T): Promise<T> { | ||
return this.waitUntilEnteredOneOf([state]); | ||
} | ||
this.invokeAllTransitionListeners(oldState, newState) | ||
} | ||
waitUntilEnteredOneOf(states: T[]): Promise<T> { | ||
return new Promise<T>((resolve) => { | ||
if (states.indexOf(this._state) != -1) { | ||
resolve(this._state); | ||
} else { | ||
const registrations: ListenerRegistration[] = []; | ||
let finished = false; | ||
for (let state of states) { | ||
let registration = this.onEnterState(state, (from, to) => { | ||
registration.cancel(); | ||
registrations.forEach(reg => { | ||
if (registration !== reg) { | ||
reg.cancel() | ||
} | ||
}); | ||
finished = true; | ||
resolve(to); | ||
}); | ||
if (finished) { | ||
break; | ||
} | ||
registrations.push(registration); | ||
} | ||
} | ||
}); | ||
} | ||
private checkTransition (newState: T) { | ||
if (!this.canGoToState(newState)) { | ||
throw new Error('Invalid transition from ' + this._state + ' to ' + newState) | ||
} | ||
} | ||
setState(newState: T) { | ||
this.checkTransition(newState); | ||
this.log.debug(`State : ${this._state} --> ${newState}`); | ||
const oldState = this._state; | ||
this._state = newState; | ||
protected canGoToState (newState: T): boolean { | ||
return this.validTransitions[this._state.label].indexOf(newState) !== -1 | ||
} | ||
} | ||
this.invokeAllTransitionListeners(oldState, newState); | ||
} | ||
export interface Transitions<T> { | ||
[stateLabel: string]: T[] | ||
} | ||
private checkTransition(newState: T) { | ||
if (!this.canGoToState(newState)) { | ||
throw new Error("Invalid transition from " + this._state + " to " + newState ); | ||
} | ||
} | ||
export class State { | ||
constructor (readonly label: string, readonly parent?: State) {} | ||
protected canGoToState(newState: T): boolean { | ||
return this.validTransitions[this._state.label].indexOf(newState) != -1; | ||
} | ||
} | ||
toString = (): string => { | ||
if (this.parent) { | ||
return this.parent.toString() + '/' + this.label | ||
} else { | ||
return this.label | ||
} | ||
} | ||
export interface Transitions<T> { | ||
[stateLabel: string]: T[]; | ||
} | ||
// noinspection JSUnusedGlobalSymbols | ||
userFriendlyDescription () { | ||
return this.label | ||
} | ||
} | ||
export class State { | ||
constructor(readonly label: string, readonly parent?: State) {} | ||
class TransitionListener<T> { | ||
active: boolean = true | ||
public toString = () : string => { | ||
if (this.parent) { | ||
return this.parent.toString() + "/" + this.label; | ||
} else { | ||
return this.label; | ||
} | ||
}; | ||
constructor ( | ||
readonly callBack: (from: T, to: T) => void, | ||
readonly fromState?: T, | ||
readonly toState?: T | ||
) { | ||
} | ||
} | ||
public userFriendlyDescription() { | ||
return this.label; | ||
} | ||
} | ||
interface TransitionListeners<T> { | ||
[transition: string]: TransitionListener<T>[] | ||
} | ||
class TransitionListener<T> { | ||
active: boolean = true; | ||
constructor( | ||
readonly callBack: (from: T, to: T) => void, | ||
readonly fromState?: T, | ||
readonly toState?: T | ||
) { | ||
} | ||
} | ||
export interface ListenerRegistration { | ||
// Cancels listener registration | ||
cancel (): void | ||
} | ||
interface TransitionListeners<T> { | ||
[transition: string]: TransitionListener<T>[]; | ||
} | ||
// Decorators | ||
const log = getLogger('fsm.decorators') | ||
export interface ListenerRegistration { | ||
// Cancels listener registration | ||
cancel(): void; | ||
} | ||
/* | ||
Method annotator. Throw an error if the state when the method is called | ||
is different from the given state | ||
*/ | ||
export function CheckStateIs (state: State, message?: string) { | ||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { | ||
const originalMethod = descriptor.value | ||
descriptor.value = function () { | ||
const context = this as StateMachine<any> | ||
if (context.state === state) { | ||
originalMethod.apply(context, arguments) | ||
} else { | ||
throw new Error(message || 'Illegal execution of ' + propertyKey + ' : State should be ' + state + ' but state = ' + context.state) | ||
} | ||
} | ||
return descriptor | ||
} | ||
} | ||
// Decorators | ||
const log = getLogger("fsm.decorators"); | ||
/* | ||
Method annotator. Throw an error if the state when the method is called | ||
is not one of the given states | ||
*/ | ||
export function CheckStateIn (states: State[], message?: string) { | ||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { | ||
let originalMethod: any | ||
if (descriptor.value) { | ||
originalMethod = descriptor.value | ||
descriptor.value = function () { | ||
const context = this as StateMachine<any> | ||
if (states.indexOf(context.state) !== -1) { | ||
return originalMethod.apply(context, arguments) | ||
} else { | ||
throw new Error(message || 'Illegal execution of ' + propertyKey + ' : State should be one of ' + states + ' but state = ' + context.state) | ||
} | ||
} | ||
} else if (descriptor.get) { | ||
const originalGetter = descriptor.get | ||
descriptor.get = function () { | ||
const context = this as StateMachine<any> | ||
if (states.indexOf(context.state) !== -1) { | ||
return originalGetter.apply(context, arguments) | ||
} else { | ||
throw new Error(message || 'Illegal execution of ' + propertyKey + ' : State should be one of ' + states + ' but state = ' + context.state) | ||
} | ||
} | ||
} | ||
return descriptor | ||
} | ||
} | ||
/* | ||
Method annotator. Throw an error if the state when the method is called | ||
is different from the given state | ||
*/ | ||
export function CheckStateIs(state:State, message?:string) { | ||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { | ||
const originalMethod = descriptor.value; | ||
descriptor.value = function() { | ||
const context = this as StateMachine<any>; | ||
if (context.state == state) { | ||
originalMethod.apply(context, arguments); | ||
} else { | ||
throw new Error(message || "Illegal execution of " + propertyKey + " : State should be " + state + " but state = " + context.state); | ||
} | ||
}; | ||
return descriptor; | ||
} | ||
} | ||
/* | ||
Method annotator. Skip the method execution if the state when the method is called | ||
is different from the given state | ||
*/ | ||
export function AssumeStateIs (state: State) { | ||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { | ||
const originalMethod = descriptor.value | ||
descriptor.value = function () { | ||
const context = this as StateMachine<any> | ||
if (context.state === state) { | ||
originalMethod.apply(context, arguments) | ||
} else { | ||
log.warn('Skipping execution of ' + propertyKey + ' : State should be ' + state + ' but state = ' + context.state) | ||
} | ||
} | ||
return descriptor | ||
} | ||
} | ||
/* | ||
Method annotator. Throw an error if the state when the method is called | ||
is not one of the given states | ||
*/ | ||
export function CheckStateIn(states:State[], message?:string) { | ||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { | ||
let originalMethod:any; | ||
if (descriptor.value) { | ||
originalMethod = descriptor.value; | ||
descriptor.value = function() { | ||
const context = this as StateMachine<any>; | ||
if (states.indexOf(context.state) != -1) { | ||
return originalMethod.apply(context, arguments); | ||
} else { | ||
throw new Error(message || "Illegal execution of " + propertyKey + " : State should be one of " + states + " but state = " + context.state); | ||
} | ||
}; | ||
} else if (descriptor.get) { | ||
const originalGetter = descriptor.get; | ||
descriptor.get = function() { | ||
const context = this as StateMachine<any>; | ||
if (states.indexOf(context.state) != -1) { | ||
return originalGetter.apply(context, arguments); | ||
} else { | ||
throw new Error(message || "Illegal execution of " + propertyKey + " : State should be one of " + states + " but state = " + context.state); | ||
} | ||
}; | ||
} | ||
return descriptor; | ||
} | ||
} | ||
/* | ||
Method annotator. Skip the method execution if the state when the method is called | ||
is different from the given state | ||
*/ | ||
export function AssumeStateIs(state: State) { | ||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { | ||
const originalMethod = descriptor.value; | ||
descriptor.value = function() { | ||
const context = this as StateMachine<any>; | ||
if (context.state == state) { | ||
originalMethod.apply(context, arguments); | ||
} else { | ||
log.warn("Skipping execution of " + propertyKey + " : State should be " + state + " but state = " + context.state); | ||
} | ||
}; | ||
return descriptor; | ||
} | ||
} | ||
/* | ||
Method annotator. Skip the method execution if the state when the method is called | ||
is the same as the given state | ||
*/ | ||
export function AssumeStateIsNot(state:State) { | ||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { | ||
const originalMethod = descriptor.value; | ||
descriptor.value = function() { | ||
const context = this as StateMachine<any>; | ||
if (context.state != state) { | ||
originalMethod.apply(context, arguments); | ||
} else { | ||
log.warn("Skipping execution of " + propertyKey + " : State should be different from " + state); | ||
} | ||
}; | ||
return descriptor; | ||
} | ||
} | ||
/* | ||
Method annotator. Skip the method execution if the state when the method is called | ||
is the same as the given state | ||
*/ | ||
export function AssumeStateIsNot (state: State) { | ||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { | ||
const originalMethod = descriptor.value | ||
descriptor.value = function () { | ||
const context = this as StateMachine<any> | ||
if (context.state !== state) { | ||
originalMethod.apply(context, arguments) | ||
} else { | ||
log.warn('Skipping execution of ' + propertyKey + ' : State should be different from ' + state) | ||
} | ||
} | ||
return descriptor | ||
} | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
158259
9
669
4
1