typescript-state-machine
Advanced tools
Comparing version 0.9.5 to 0.9.6
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var log4javascript_1 = require("log4javascript"); | ||
var fsm; | ||
(function (fsm) { | ||
var StateMachineImpl = /** @class */ (function () { | ||
function StateMachineImpl(states, validTransitions, initialState) { | ||
this.log = log4javascript_1.getLogger(this.constructor.name); | ||
this.states = states; | ||
this.validTransitions = validTransitions; | ||
this._state = initialState; | ||
this._transitionListeners = {}; | ||
} | ||
Object.defineProperty(StateMachineImpl.prototype, "state", { | ||
get: function () { | ||
return this._state; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
StateMachineImpl.prototype.onEnterState = function (state, callBack) { | ||
return this.addTransitionListener(callBack, undefined, state); | ||
}; | ||
StateMachineImpl.prototype.onLeaveState = function (state, callBack) { | ||
return this.addTransitionListener(callBack, state, undefined); | ||
}; | ||
StateMachineImpl.prototype.onTransition = function (fromState, toState, callBack) { | ||
return this.addTransitionListener(callBack, fromState, toState); | ||
}; | ||
StateMachineImpl.prototype.onAnyTransition = function (callBack) { | ||
return this.addTransitionListener(callBack, undefined, undefined); | ||
}; | ||
StateMachineImpl.prototype.addTransitionListener = function (callBack, fromState, toState) { | ||
var transition = this.transitionLabel(fromState, toState); | ||
if (!this._transitionListeners[transition]) { | ||
this._transitionListeners[transition] = []; | ||
} | ||
var listenersForTransition = this._transitionListeners[transition]; | ||
var transitionListener = new TransitionListener(callBack, fromState, toState); | ||
listenersForTransition.push(transitionListener); | ||
return { | ||
cancel: function () { | ||
transitionListener.active = false; | ||
} | ||
}; | ||
}; | ||
StateMachineImpl.prototype.checkInState = function (state, message) { | ||
if (!this.inState(state)) { | ||
throw new Error(message || 'Expected to be in ' + state + ' but was in ' + this.state); | ||
} | ||
}; | ||
StateMachineImpl.prototype.checkInOneOfStates = function (states, message) { | ||
if (!this.inOneOfStates(states)) { | ||
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); | ||
}; | ||
StateMachineImpl.prototype.inState = function (state) { | ||
return this._state === state; | ||
}; | ||
StateMachineImpl.prototype.invokeAllTransitionListeners = function (fromState, toState) { | ||
var allLeaveTransitions = this.transitionLabel(fromState, undefined); | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[allLeaveTransitions]); | ||
var transition = this.transitionLabel(fromState, toState); | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[transition]); | ||
var allEnterTransitions = this.transitionLabel(undefined, toState); | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[allEnterTransitions]); | ||
var allTransitions = this.transitionLabel(undefined, undefined); | ||
this.invokeTransitionListeners(fromState, toState, this._transitionListeners[allTransitions]); | ||
}; | ||
StateMachineImpl.prototype.invokeTransitionListeners = function (fromState, toState, listeners) { | ||
if (listeners) { | ||
for (var index = 0; index < listeners.length; index++) { | ||
var listener = listeners[index]; | ||
if (listener.active) { | ||
try { | ||
listener.callBack(fromState, toState); | ||
} | ||
catch (e) { | ||
this.log.error('Uncaught error in listener', e); | ||
} | ||
} | ||
else { | ||
// Remove inactive listener | ||
listeners.splice(index, 1); | ||
index--; | ||
} | ||
} | ||
} | ||
}; | ||
StateMachineImpl.prototype.transitionLabel = function (fromState, toState) { | ||
return ((fromState && fromState.label) || '*') + ' --> ' + ((toState && toState.label) || '*'); | ||
}; | ||
StateMachineImpl.prototype.waitUntilLeft = function (state) { | ||
var _this = this; | ||
return new Promise(function (resolve) { | ||
if (_this._state !== state) { | ||
resolve(_this._state); | ||
} | ||
else { | ||
var registration_1 = _this.onLeaveState(state, function (from, to) { | ||
registration_1.cancel(); | ||
resolve(to); | ||
}); | ||
} | ||
}); | ||
}; | ||
StateMachineImpl.prototype.waitUntilEntered = function (state) { | ||
return this.waitUntilEnteredOneOf([state]); | ||
}; | ||
StateMachineImpl.prototype.waitUntilEnteredOneOf = function (states) { | ||
var _this = this; | ||
return new Promise(function (resolve) { | ||
if (states.indexOf(_this._state) !== -1) { | ||
resolve(_this._state); | ||
} | ||
else { | ||
var registrations_1 = []; | ||
var finished_1 = false; | ||
var _loop_1 = function (state) { | ||
var registration = _this.onEnterState(state, function (from, to) { | ||
registration.cancel(); | ||
registrations_1.forEach(function (reg) { | ||
if (registration !== reg) { | ||
reg.cancel(); | ||
} | ||
}); | ||
finished_1 = true; | ||
resolve(to); | ||
}); | ||
if (finished_1) { | ||
return "break"; | ||
} | ||
registrations_1.push(registration); | ||
}; | ||
for (var _i = 0, states_1 = states; _i < states_1.length; _i++) { | ||
var state = states_1[_i]; | ||
var state_1 = _loop_1(state); | ||
if (state_1 === "break") | ||
break; | ||
} | ||
} | ||
}); | ||
}; | ||
StateMachineImpl.prototype.setState = function (newState) { | ||
this.checkTransition(newState); | ||
this.log.debug("State : " + this._state + " --> " + newState); | ||
var oldState = this._state; | ||
this._state = newState; | ||
this.invokeAllTransitionListeners(oldState, newState); | ||
}; | ||
StateMachineImpl.prototype.canGoToState = function (newState) { | ||
return this.validTransitions[this._state.label].indexOf(newState) !== -1; | ||
}; | ||
StateMachineImpl.prototype.checkTransition = function (newState) { | ||
if (!this.canGoToState(newState)) { | ||
throw new Error('Invalid transition from ' + this._state + ' to ' + newState); | ||
} | ||
}; | ||
return StateMachineImpl; | ||
}()); | ||
fsm.StateMachineImpl = StateMachineImpl; | ||
var State = /** @class */ (function () { | ||
function State(label, parent) { | ||
var _this = this; | ||
this.label = label; | ||
this.parent = parent; | ||
this.toString = function () { | ||
if (_this.parent) { | ||
return _this.parent.toString() + '/' + _this.label; | ||
} | ||
else { | ||
return _this.label; | ||
} | ||
}; | ||
} | ||
// noinspection JSUnusedGlobalSymbols | ||
State.prototype.userFriendlyDescription = function () { | ||
return this.label; | ||
}; | ||
return State; | ||
}()); | ||
fsm.State = State; | ||
var TransitionListener = /** @class */ (function () { | ||
function TransitionListener(callBack, fromState, toState) { | ||
this.callBack = callBack; | ||
this.fromState = fromState; | ||
this.toState = toState; | ||
this.active = true; | ||
} | ||
return TransitionListener; | ||
}()); | ||
// Decorators | ||
var log = log4javascript_1.getLogger('fsm.decorators'); | ||
/* | ||
Method annotator. Throw an error if the state when the method is called | ||
is different from the given state | ||
*/ | ||
function CheckStateIs(state, message) { | ||
return function (target, propertyKey, descriptor) { | ||
var originalMethod = descriptor.value; | ||
descriptor.value = function () { | ||
var context = this; | ||
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; | ||
}; | ||
} | ||
fsm.CheckStateIs = CheckStateIs; | ||
/* | ||
Method annotator. Throw an error if the state when the method is called | ||
is not one of the given states | ||
*/ | ||
function CheckStateIn(states, message) { | ||
return function (target, propertyKey, descriptor) { | ||
var originalMethod; | ||
if (descriptor.value) { | ||
originalMethod = descriptor.value; | ||
descriptor.value = function () { | ||
var context = this; | ||
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) { | ||
var originalGetter_1 = descriptor.get; | ||
descriptor.get = function () { | ||
var context = this; | ||
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); | ||
} | ||
}; | ||
} | ||
return descriptor; | ||
}; | ||
} | ||
fsm.CheckStateIn = CheckStateIn; | ||
/* | ||
Method annotator. Throw an error if the state when the method is called | ||
is one of the given states | ||
*/ | ||
function CheckStateNotIn(states, message) { | ||
return function (target, propertyKey, descriptor) { | ||
var originalMethod; | ||
if (descriptor.value) { | ||
originalMethod = descriptor.value; | ||
descriptor.value = function () { | ||
var context = this; | ||
if (states.indexOf(context.state) === -1) { | ||
return originalMethod.apply(context, arguments); | ||
} | ||
else { | ||
throw new Error(message || 'Illegal execution of ' + propertyKey + ' : State should not be one of ' + states); | ||
} | ||
}; | ||
} | ||
else if (descriptor.get) { | ||
var originalGetter_2 = descriptor.get; | ||
descriptor.get = function () { | ||
var context = this; | ||
if (states.indexOf(context.state) === -1) { | ||
return originalGetter_2.apply(context, arguments); | ||
} | ||
else { | ||
throw new Error(message || 'Illegal execution of ' + propertyKey + ' : State should not be one of these states: ' + states); | ||
} | ||
}; | ||
} | ||
return descriptor; | ||
}; | ||
} | ||
fsm.CheckStateNotIn = CheckStateNotIn; | ||
/* | ||
Method annotator. Skip the method execution if the state when the method is called | ||
is different from the given state | ||
*/ | ||
function AssumeStateIs(state) { | ||
return function (target, propertyKey, descriptor) { | ||
var originalMethod = descriptor.value; | ||
descriptor.value = function () { | ||
var context = this; | ||
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; | ||
}; | ||
} | ||
fsm.AssumeStateIs = AssumeStateIs; | ||
/* | ||
Method annotator. Skip the method execution if the state when the method is called | ||
is the same as the given state | ||
*/ | ||
function AssumeStateIsNot(state) { | ||
return function (target, propertyKey, descriptor) { | ||
var originalMethod = descriptor.value; | ||
descriptor.value = function () { | ||
var context = this; | ||
if (context.state !== state) { | ||
originalMethod.apply(context, arguments); | ||
} | ||
else { | ||
log.warn('Skipping execution of ' + propertyKey + ' : State should be different from ' + state); | ||
} | ||
}; | ||
return descriptor; | ||
}; | ||
} | ||
fsm.AssumeStateIsNot = AssumeStateIsNot; | ||
})(fsm = exports.fsm || (exports.fsm = {})); | ||
__exportStar(require("./decorators"), exports); | ||
__exportStar(require("./stateMachine"), exports); | ||
__exportStar(require("./typings"), exports); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "typescript-state-machine", | ||
"version": "0.9.5", | ||
"version": "0.9.6", | ||
"description": "", | ||
@@ -18,16 +18,25 @@ "main": "dist/index.js", | ||
"scripts": { | ||
"prepublish": "npm run build", | ||
"build": "npm run tslint && tsc", | ||
"tslint": "tslint src/*" | ||
"prepublishOnly": "npm run build && jest", | ||
"build": "npm run eslint && tsc --project tsconfig.build.json", | ||
"eslint": "eslint src/*" | ||
}, | ||
"homepage": "https://github.com/taktik/typescript-state-machine#readme", | ||
"dependencies": { | ||
"log4javascript": "^1.4.15" | ||
"devDependencies": { | ||
"@types/jest": "27.0.3", | ||
"@typescript-eslint/eslint-plugin": "5.7.0", | ||
"@typescript-eslint/parser": "5.7.0", | ||
"eslint": "8.4.1", | ||
"eslint-config-prettier": "8.3.0", | ||
"husky": "7.0.4", | ||
"jest": "27.4.5", | ||
"lint-staged": "12.1.3", | ||
"prettier": "2.5.1", | ||
"ts-jest": "27.1.2", | ||
"typescript": "4.5.4" | ||
}, | ||
"devDependencies": { | ||
"tslint": "^5.11.0", | ||
"tslint-config-standard": "^8.0.1", | ||
"typescript": "^3.1.6", | ||
"typescript-eslint-parser": "^20.1.1" | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged" | ||
} | ||
} | ||
} |
372
src/index.ts
@@ -1,369 +0,3 @@ | ||
import { getLogger } from 'log4javascript' | ||
export namespace fsm { | ||
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 leaves the given state. | ||
@param callBack The callBack that will be called | ||
*/ | ||
onLeaveState(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 | ||
onAnyTransition(callBack: (from: T, to: T) => void): ListenerRegistration | ||
/* | ||
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) | ||
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 | ||
} | ||
onEnterState(state: T, callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, undefined, state) | ||
} | ||
onLeaveState(state: T, callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, state, undefined) | ||
} | ||
onTransition(fromState: T, toState: T, callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, fromState, toState) | ||
} | ||
onAnyTransition(callBack: (from: T, to: T) => void): ListenerRegistration { | ||
return this.addTransitionListener(callBack, undefined, undefined) | ||
} | ||
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 | ||
} | ||
} | ||
} | ||
checkInState(state: T, message?: string): void { | ||
if (!this.inState(state)) { | ||
throw new Error(message || 'Expected to be in ' + state + ' but was in ' + this.state) | ||
} | ||
} | ||
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) | ||
} | ||
} | ||
inOneOfStates(states: T[]): boolean { | ||
return (states.indexOf(this._state) !== -1) | ||
} | ||
inState(state: T): boolean { | ||
return this._state === state | ||
} | ||
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 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.error('Uncaught error in listener', e) | ||
} | ||
} else { | ||
// Remove inactive listener | ||
listeners.splice(index, 1) | ||
index-- | ||
} | ||
} | ||
} | ||
} | ||
private transitionLabel(fromState?: T, toState?: T) { | ||
return ((fromState && fromState.label) || '*') + ' --> ' + ((toState && toState.label) || '*') | ||
} | ||
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) | ||
}) | ||
} | ||
}) | ||
} | ||
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) | ||
} | ||
} | ||
}) | ||
} | ||
setState(newState: T) { | ||
this.checkTransition(newState) | ||
this.log.debug(`State : ${this._state} --> ${newState}`) | ||
const oldState = this._state | ||
this._state = newState | ||
this.invokeAllTransitionListeners(oldState, newState) | ||
} | ||
canGoToState(newState: T): boolean { | ||
return this.validTransitions[this._state.label].indexOf(newState) !== -1 | ||
} | ||
private checkTransition(newState: T) { | ||
if (!this.canGoToState(newState)) { | ||
throw new Error('Invalid transition from ' + this._state + ' to ' + newState) | ||
} | ||
} | ||
} | ||
export interface Transitions<T> { | ||
[stateLabel: string]: T[] | ||
} | ||
export class State { | ||
constructor(readonly label: string, readonly parent?: State) {} | ||
toString = (): string => { | ||
if (this.parent) { | ||
return this.parent.toString() + '/' + this.label | ||
} else { | ||
return this.label | ||
} | ||
} | ||
// noinspection JSUnusedGlobalSymbols | ||
userFriendlyDescription() { | ||
return this.label | ||
} | ||
} | ||
class TransitionListener<T> { | ||
active: boolean = true | ||
constructor( | ||
readonly callBack: (from: T, to: T) => void, | ||
readonly fromState?: T, | ||
readonly toState?: T | ||
) { | ||
} | ||
} | ||
interface TransitionListeners<T> { | ||
[transition: string]: TransitionListener<T>[] | ||
} | ||
export interface ListenerRegistration { | ||
// Cancels listener registration | ||
cancel(): void | ||
} | ||
// Decorators | ||
const log = getLogger('fsm.decorators') | ||
/* | ||
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. 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 one of the given states | ||
*/ | ||
export function CheckStateNotIn(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 not be one of ' + states) | ||
} | ||
} | ||
} 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 not be one of these states: ' + states) | ||
} | ||
} | ||
} | ||
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 | ||
} | ||
} | ||
} | ||
export * from './decorators' | ||
export * from './stateMachine' | ||
export * from './typings' |
@@ -17,8 +17,3 @@ { | ||
"allowSyntheticDefaultImports": true, | ||
"lib": [ | ||
"es2017", | ||
"es6", | ||
"es5", | ||
"dom" | ||
], | ||
"lib": ["es2017", "es6", "es5", "dom"], | ||
"sourceMap": true, | ||
@@ -30,5 +25,3 @@ "declaration": true, | ||
}, | ||
"files": [ | ||
"./src/index.ts" | ||
] | ||
"include": ["./src"] | ||
} |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Possible typosquat attack
Supply chain riskThere is a package with a similar name that is downloaded much more often.
Did you mean |
---|
javascript-state-machine |
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
0
17
0
18757
11
530
- Removedlog4javascript@^1.4.15
- Removedlog4javascript@1.4.16(transitive)