@rarible/action
Version:
Action is almost like async function, but actions can be divided into steps. It gives more control over action execution.
70 lines (69 loc) • 2.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Execution = void 0;
const tslib_1 = require("tslib");
class Execution {
constructor(input, steps) {
this.input = input;
this.steps = steps;
this.state = new Array(steps.length);
this.promises = new Array(steps.length);
}
get ids() {
return this.steps.map(s => s.id);
}
runAll() {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
for (let i = 0; i < this.ids.length; i++) {
yield this.run(i);
}
const last = this.state[this.ids.length - 1];
if (last.status === "resolved") {
return last.value;
}
else {
throw new Error("Should never happen");
}
});
}
run(idx) {
if (idx === 0) {
return this.runInternal(idx, this.input);
}
if (idx >= this.steps.length) {
throw new Error(`Stage with index ${idx} not found`);
}
const prevState = this.state[idx - 1];
if (prevState == null) {
throw new Error(`Stage ${idx - 1} hasn't been run yet`);
}
if (prevState.status !== "resolved") {
throw new Error(`Stage ${idx - 1} status is: ${prevState.status}`);
}
return this.runInternal(idx, prevState.value);
}
runInternal(idx, input) {
const state = this.state[idx];
if (state != null && (state.status === "pending" || state.status === "resolved")) {
return this.promises[idx];
}
else {
this.state[idx] = { status: "pending" };
const promise = this.steps[idx].run(input);
this.promises[idx] = promise
.then(r => {
this.state[idx] = { status: "resolved", value: r };
return r;
})
.catch(err => {
this.state[idx] = { status: "rejected", error: err };
return Promise.reject(err);
});
return this.promises[idx];
}
}
get result() {
return this.runAll();
}
}
exports.Execution = Execution;