Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

statetransition-mixin

Package Overview
Dependencies
Maintainers
1
Versions
80
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

statetransition-mixin - npm Package Compare versions

Comparing version 1.1.0 to 1.2.0

2

package.json

@@ -38,3 +38,3 @@ {

"homepage": "https://github.com/arlac77/statetransition-mixin#readme",
"version": "1.1.0"
"version": "1.2.0"
}

@@ -7,25 +7,58 @@ /* jslint node: true, esnext: true */

const actions = {};
const states = {};
Object.keys(as).forEach(name => {
const a = as[name];
const ts = {};
Object.keys(a).forEach(tn => {
ts[tn] = a[tn];
a[tn].name = tn;
function addState(name, transition) {
if (!states[name]) {
states[name] = {
name: name,
transitions: {}
};
}
if (transition) {
states[name].transitions[transition.initial] = transition;
}
return states[name];
}
Object.keys(as).forEach(actionName => {
const a = as[actionName];
const initialTransitions = {};
const duringTransitions = {};
Object.keys(a).forEach(initialState => {
const t = a[initialState];
initialTransitions[initialState] = t;
duringTransitions[t.during] = t;
t.initial = initialState;
t.name = `${actionName}:${t.initial}->${t.target}`;
addState(t.initial, t);
addState(t.during, t);
addState(t.target);
});
actions[name] = {
name: name,
transitions: ts
actions[actionName] = {
name: actionName,
initial: initialTransitions,
during: duringTransitions
};
});
return actions;
/*
console.log(`${JSON.stringify(actions,undefined,1)}`);
console.log(`${JSON.stringify(states,undefined,1)}`);
*/
return [actions, states];
};
module.exports.StateTransitionMixin = (superclass, actions, currentState) => class extends superclass {
/**
* Called when state action is not allowed
* @param {Object} action
* @return {Promise} rejecting with an Error
*/
constructor() {
super();
this._state = currentState;
}
/**
* Called when state transition action is not allowed
* @param {Object} action
* @return {Promise} rejecting with an Error
*/
illegalStateTransition(action) {

@@ -36,3 +69,3 @@ return Promise.reject(new Error(`Can't ${action.name} ${this} in ${this.state} state`));

/**
* Called when the state transtinio implementation Promise rejects.
* Called when the state transtion implementation promise rejects.
* Resets the transition

@@ -61,8 +94,8 @@ * @return {Promise} rejecting promise

get state() {
return currentState;
return this._state;
}
set state(newState) {
if (newState !== currentState) {
this.stateChanged(currentState, newState);
currentState = newState;
if (newState !== this._state) {
this.stateChanged(this._state, newState);
this._state = newState;
}

@@ -76,10 +109,18 @@ }

return new Promise(function (fullfill, reject) {
const p = promise.then((fullfilled, rejected) => {
fullfilled(this);
});
const th = setTimeout(() => {
//console.log(`Not resolved within ${timeout}ms`);
reject(new Error(`Not resolved within ${timeout}ms`))
}, timeout);
setTimeout(function () {
reject(`Not resolved within ${timeout}s`);
return promise.then((fullfilled, rejected) => {
//console.log(`AA ${fullfilled} : ${rejected}`);
clearTimeout(th);
}, timeout * 1000);
if (fullfilled) {
fullfill(fullfilled);
}
if (rejected) {
reject(rejected);
}
});
});

@@ -111,4 +152,5 @@ }

*/
module.exports.defineActionMethods = function (object, actions) {
//console.log(`${JSON.stringify(actions,undefined,1)}`);
module.exports.defineActionMethods = function (object, actionsAndStates) {
const actions = actionsAndStates[0];
const states = actionsAndStates[1];

@@ -127,26 +169,28 @@ Object.keys(actions).forEach(actionName => {

value: function () {
if (this._transition) {
switch (this.state) {
case this._transition.during:
return this._transitionPromise;
case this._transition.target:
return Promise.resolve(this);
}
}
if (action.transitions[this.state]) {
this._transition = action.transitions[this.state];
// normal start
if (action.initial[this.state]) {
this._transition = action.initial[this.state];
this.state = this._transition.during;
this._transitionPromise = this[privateActionName]().then(
resolved => {
this.state = this._transition.target;
this._transitionPromise = undefined;
this._transition = undefined;
return this;
}, rejected => this.stateTransitionRejection(rejected));
this._transitionPromise = rejectUnlessResolvedWithin(this[privateActionName](), this._transition
.timeout)
.then(
resolved => {
this.state = this._transition.target;
this._transitionPromise = undefined;
this._transition = undefined;
return this;
}, rejected => this.stateTransitionRejection(rejected));
return this._transitionPromise;
} else {
return this.illegalStateTransition(action);
} else if (this._transition) {
if (action.during[this._transition.during]) {
//console.log(`XXX ${this.state} ${action.during[this._transition.during]}`);
return this._transitionPromise;
}
}
return this.illegalStateTransition(action);
}

@@ -153,0 +197,0 @@ });

@@ -17,3 +17,3 @@ /* global describe, it, xit */

during: "starting",
timeout: 10
timeout: 200
}

@@ -25,3 +25,3 @@ },

during: "stopping",
timeout: 5
timeout: 100
},

@@ -31,3 +31,3 @@ starting: {

during: "stopping",
timeout: 10
timeout: 100
}

@@ -39,9 +39,12 @@ }

var shouldReject = false;
class StatefullClass extends stm.StateTransitionMixin(BaseClass, actions, 'stopped') {
constructor(startTime, shouldReject) {
super();
this.startTime = startTime;
this.shouldReject = shouldReject;
}
_start() {
return new Promise((f, r) => {
setTimeout(() => {
if (shouldReject) {
if (this.shouldReject) {
r(new Error("always reject"));

@@ -51,5 +54,9 @@ } else {

}
}, 10);
}, this.startTime);
});
}
toString() {
return `sample: ${this.state}`
}
}

@@ -60,38 +67,45 @@

describe('states', function () {
const o1 = new StatefullClass();
describe('static', function () {
const o = new StatefullClass(10, false);
it('has initial state', function () {
assert.equal(o1.state, 'stopped');
});
it('has initial state', function () {
o.state = 'stopped';
assert.equal(o.state, 'stopped');
});
it('has action methods', function () {
assert.isDefined(o1.stop());
assert.isDefined(o1.start());
assert.isDefined(o1._start());
assert.isDefined(o1._stop());
it('has action methods', function () {
assert.isDefined(o.stop());
assert.isDefined(o.start());
assert.isDefined(o._start());
assert.isDefined(o._stop());
});
});
it('can be started', function (done) {
o1.start().then(() => {
assert.equal(o1.state, 'running');
done();
}, done);
});
describe('start-stop', function () {
const o = new StatefullClass(10, false);
it('and stoped', function (done) {
o1.stop().then(() => {
assert.equal(o1.state, 'stopped');
done();
}, done);
it('can be started', function (done) {
o.start().then(() => {
assert.equal(o.state, 'running');
done();
}, done);
});
it('and stoped', function (done) {
o.stop().then(() => {
assert.equal(o.state, 'stopped');
done();
}, done);
});
});
it('can be started while starting', function (done) {
assert.equal(o1.state, 'stopped');
const o = new StatefullClass(10, false);
o1.start().then(() => {});
o.start().then(() => {});
assert.equal(o1.state, 'starting');
assert.equal(o.state, 'starting');
o1.start().then(() => {
assert.equal(o1.state, 'running');
o.start().then(() => {
assert.equal(o.state, 'running');
done();

@@ -101,23 +115,32 @@ }, done).catch(done);

xit('can be stopped while starting', function (done) {
o1.stop().then(() => {
assert.equal(o1.state, 'stopped');
it('can be stopped while starting', function (done) {
const o = new StatefullClass(100, false);
o1.start().then(() => {});
o.start().then(() => {});
assert.equal(o1.state, 'starting');
assert.equal(o.state, 'starting');
o1.stop().then(() => {
assert.equal(o1.state, 'stopped');
o.stop().then(() => {
assert.equal(o.state, 'stopped');
done();
}, done).catch(done);
});
describe('failures', function () {
it('handle timeout while starting', function (done) {
const o = new StatefullClass(1000, false);
o.start().then(() => {}).catch(e => {
assert.equal(o.state, 'failed');
done();
}, done).catch(done);
});
});
});
it('handle failure while starting', function (done) {
o1.stop().then(() => {
shouldReject = true;
assert.equal(o1.state, 'stopped');
o1.start().then(() => {}).catch(e => {
assert.equal(o1.state, 'failed');
it('handle failure while starting', function (done) {
const o = new StatefullClass(10, true);
o.start().then((f, r) => {
console.log(`${f} ${r}`);
}).catch(e => {
//console.log(`catch: ${e}`);
assert.equal(o.state, 'failed');
done();

@@ -127,2 +150,3 @@ });

});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc