UNPKG

flownote

Version:

FlowNote lets developers create, organize, and reason about event-oriented applications with a simple flow-based language.

170 lines (145 loc) 5.06 kB
import Node from './node' import Spider from './spider' const CommonClass = require('./utils/commonClass') const Log = require('./utils/log') const noop = () => {} class Flow extends CommonClass { /** * [constructor description] * @param {[type]} id [description] * @param {[type]} name [description] * @param {[type]} config [description] * @param {[type]} to [description] * @param {[type]} endpointRoute [description] * @param {[type]} endpointMethod [description] * @param {[type]} endpointParams [description] * @return {[type]} [description] */ constructor (application, id, name, config, to, endpointMethod, endpointRoute, endpointParams) { super() this.application = application if (name !== undefined) { this.fromJSON({ id: id || this.application.getUniqueId(), name: name || 'Unnamed', config: Object.assign(config || {}, {}), to, endpointMethod: endpointMethod || 'GET', endpointRoute: endpointRoute || '/' + name || 'Unnamed', endpointParams: endpointParams || [] }) } } /** * [toJSON description] * @return {[type]} [description] */ toJSON () { return { id: this.id, name: this.name, config: this.config, to: this.to, endpointMethod: this.endpointMethod, endpointRoute: this.endpointRoute, endpointParams: this.endpointParams } } /** * [fromJSON description] * @param {[type]} json [description] * @return {[type]} [description] */ fromJSON (json) { let result if (typeof json === 'string') { result = this.loadFlattened(json) } else if (json instanceof Object && !(json instanceof Array)) { result = json } else { throw new Error(`Expected Flow JSON to be a string or an object, but got a ${typeof json} instead`) } this.id = result.id this.name = result.name this.config = result.config if (result.to instanceof Node) { this.connect(result.to) } else if (result.to !== undefined && !this.application.isPendingStep(result.to.id)) { this.application.setPendingStep(result.to.id) let existingNode if (this.application !== undefined) { existingNode = new Spider().search(this.application, result.to.id) } if (existingNode) { this.connect(existingNode) } else { this.connect(new Node(this.application).fromJSON(result.to)) } this.application.removePendingStep(result.to.id) } this.endpointRoute = result.endpointRoute this.endpointMethod = result.endpointMethod this.endpointParams = result.endpointParams this.onError = noop this.onComplete = noop this.log = new Log(this.id, 'Flow', this.name, this.application.config.logLevel, this.application.outputPipe, this.application.errorPipe) return this } /** * Connects a node or milestone to a specific location within the flow * @return {[type]} [description] */ connect (node) { this.application.log.debug(`Connecting node ${node.name}:${node.id} to ${this.name} flow`) this.to = node } /** * [request description] * @param {[type]} params [description] * @return {[type]} [description] */ request (params, request) { this.application.emit('Flow.start', this, request) return new Promise((resolve, reject) => { this.log.debug(`Waiting for Request ${request.id} to complete...`) const listener = this.application.on('Flow.end', (source, resultRequest, error) => { this.log.debug(`Handling flow end from ${source.name}...`) if (error !== undefined) { return reject(error) } if (resultRequest === request) { this.application.off(listener) this.log.debug(`Request ${request.id} complete.`) resolve(resultRequest.asResult()) } }) this.log.debug('Dispatching flow...') this.application.dispatch(`Flow.start`, request, this, this) }) } /** * Commits all accumulated actions within a request * @param {[type]} event [description] * @param {[type]} actionContext [description] * @return {[type]} [description] */ async process (event, actionContext) { this.log.debug('Processing flow', this.name) this.application.emit('Flow.start', this, event.request) if (this.to !== undefined) { this.log.debug('Dispatching event to proceed to node from flow...') this.application.dispatch(`Node.${this.to.name}`, event.request, this, this.to) } } print (source = this, indents = '') { console.log(indents + source.name + ` (${source.id})`) if (source.to instanceof Array) { for (var i = 0, len = source.to.length; i < len; i++) { this.print(source.to[i], indents + ' ') } } else if (source.to !== undefined) { this.print(source.to, indents + ' ') } } } export { Flow as default }