flownote
Version:
FlowNote lets developers create, organize, and reason about event-oriented applications with a simple flow-based language.
183 lines (155 loc) • 4.49 kB
JavaScript
const CyclicalError = require('./errors/cyclicalError')
const noop = () => {}
const stacks = new WeakMap()
const Log = require('./utils/log')
/**
*
*/
class Request {
/**
* [constructor description]
* @param {[type]} flow [description]
* @param {[type]} onFlowSuccess [description]
* @param {[type]} onFlowFailure [description]
* @return {[type]} [description]
*/
constructor (application, initialValue = {}, flow, step, config = {}) {
const entries = Object.entries(initialValue)
this.application = application
this.changes = []
this.id = this.application.getUniqueId()
for (const [key, value] of entries) {
this.changes.push({
appId: application.id,
flowId: flow.id,
stepId: step.id,
key,
value
})
}
this.config = Object.assign(config, {
showState: application.config.showState || flow.config.showState || config.showState || true,
showChanges: application.config.showChanges || flow.config.showChanges || config.showChanges || false,
showTrace: application.config.showTrace || flow.config.showTrace || config.showTrace || false
})
this.onCyclicWarning = noop
this.onCyclicError = noop
this.accumulatedActions = []
this.steps = []
this.stack = stacks.set(this, new Map())
this.waiting = false
this.log = new Log(this.id, 'Request', this.application.name, this.application.config.logLevel, this.application.outputPipe, this.application.errorPipe)
}
/**
* [toJSON description]
* @return {[type]} [description]
*/
toJSON () {
return {
id: this.id,
changes: this.changes,
accumulatedActions: this.accumulatedActions,
steps: this.steps,
state: this.getState()
}
}
/**
* Keeps track of what values have changed during the lifecycle of this request
* @param {[type]} application [description]
* @param {[type]} flow [description]
* @param {[type]} step [description]
* @param {[type]} key [description]
* @param {[type]} value [description]
* @return {[type]} [description]
*/
change (application, flow, step, key, value) {
this.changes.push({
appId: application.id,
flowId: flow.id,
stepId: step.id,
key,
value
})
const isSilent = step.config && step.config.silent
this.application.emit('ValueChange', { [key]: value }, this, undefined, isSilent)
return this
}
/**
* Returns the current value map of the request
* @param {[type]} data [description]
* @return {[type]} [description]
*/
getState (data) {
const result = {}
const entries = Object.entries(data || {})
for (var [key, value] of entries) {
result[key] = value
}
for (var i = 0, len = this.changes.length; i < len; i++) {
result[this.changes[i].key] = this.changes[i].value
}
return result
}
/**
* [asResult description]
* @return {[type]} [description]
*/
asResult () {
const result = {}
if (this.config.showState) {
result.state = this.getState()
}
if (this.config.showChanges) {
result.changes = this.changes
}
if (this.config.showTrace) {
result.trace = this.steps
}
return result
}
/**
* [addStep description]
* @param {[type]} application [description]
* @param {[type]} flow [description]
* @param {[type]} step [description]
*/
addStep (application, flow, step) {
const stack = stacks.get(this)
const value = stack.get(step.id) || 1
if (value > 100) {
throw new CyclicalError()
}
stack.set(step.id, value + 1)
this.steps.push({
appId: application.id,
flowId: flow.id,
stepId: step.id
})
}
/**
* [addAction description]
* @param {[type]} action [description]
*/
addAction (action) {
this.accumulatedActions.push(action)
return this
}
/**
* [rollbackChanges description]
* @param {[type]} stepId [description]
* @return {[type]} [description]
*/
rollbackChanges (stepId) {
const len = this.changes.length - 1
let lastIndex
for (var i = len; i >= 0; i--) {
if (this.changes[i].stepId === stepId) {
lastIndex = i
}
}
if (lastIndex !== undefined) {
this.changes = this.changes.slice(0, lastIndex)
}
}
}
module.exports = Request