work.flow is an asynchronous workflow library for Node.
The current version is 0.0.0 and is still going through documentation and testing before development starts, Unless you are contributing, you should probably not be using this.
The purpose of work.flow is to provide a means of creating individual pieces of code that can be used to quickly create applications or data processing pipelines.
More Information
- Flow-based Programming https://www.jpaulmorrison.com/fbp/
- Flow-based programming https://en.wikipedia.org/wiki/Flow-based_programming
All Workflow instances share a single global definitions registry — creating new Workflow() in multiple files is safe, and importing a file as a side effect registers its definitions into the shared registry before run is called.
print-line.ts
import Workflow = require('work.flow');
const work = new Workflow();
work.flow.task.definition({
uri: 'incredi.co/games/worlds-fastest-game/print-line',
properties: {
message: { type: String, value: '' }
}
});ask-name.ts
import Workflow = require('work.flow');
const work = new Workflow();
work.flow.task.definition({
uri: 'incredi.co/games/worlds-fastest-game/ask-name',
properties: {
for: { type: String, value: 'Buddy' },
prompt: { type: String, value: 'Hey %s, What is your name?', readOnly: true }
}
});ask-for-player-names.ts
import Workflow = require('work.flow');
import './ask-name';
const work = new Workflow();
work.flow.path.definition({
uri: 'incredi.co/games/worlds-fastest-game/paths/ask-for-player-names',
start: [
{ name: 'player-one', uri: 'incredi.co/games/worlds-fastest-game/ask-name', properties: { for: 'Player 1' } },
{ name: 'player-two', uri: 'incredi.co/games/worlds-fastest-game/ask-name', properties: { for: 'Player 2' } }
],
timeout: 6000,
error: [{ uri: 'work.flow/task/restart' }]
});workflow.ts
import Workflow = require('work.flow');
import './print-line';
import './ask-for-player-names';
const work = new Workflow();
work.flow.definition({
name: 'worlds-fastest-game',
uri: 'incredi.co/games/worlds-fastest-game',
start: [
{ name: 'ask-names', uri: 'incredi.co/games/worlds-fastest-game/paths/ask-for-player-names' },
{
name: 'determine-winner',
uri: 'work.flow/task/if-then-else',
properties: {
if: {
equals: 1,
then: [{ name: 'player-one-wins', uri: 'incredi.co/games/worlds-fastest-game/print-line', properties: { message: '{ask-names.player-one} WINS!!!!' } }],
else: [{ name: 'player-two-wins', uri: 'incredi.co/games/worlds-fastest-game/print-line', properties: { message: '{ask-names.player-two} WINS!!!!' } }]
}
}
},
{ uri: 'work.flow/workflow/restart' }
],
timeout: 6000,
error: [{ uri: 'work.flow/workflow/restart' }]
});index.ts
import Workflow = require('work.flow');
import './workflow'; // registers all definitions as a side effect
const work = new Workflow();
work.flow.run({}, (err: Error | null) => {
console.log('MUAHAHAHAHAHAHAHAH');
});npm install work.flowReturns a Workflow instance. All instances share the same global definitions registry.
import Workflow = require('work.flow');
const work = new Workflow();Registers a task definition in the global registry.
| Field | Type | Required | Description |
|---|---|---|---|
uri |
string |
yes | Unique identifier for the task |
name |
string |
no | Human-readable name |
properties |
object |
no | Input property descriptors |
error |
array |
no | Error handler URIs |
timeout |
number |
no | Timeout in milliseconds |
Registers a path definition. Paths group tasks that run in parallel.
Same fields as task.definition, plus:
| Field | Type | Required | Description |
|---|---|---|---|
start |
object[] |
no | Tasks/paths to run at path start |
Registers a workflow definition.
Same fields as path.definition.
The global definitions registry. Methods:
work.flow.definitions.addTask(def, callback?)
work.flow.definitions.addPath(def, callback?)
work.flow.definitions.addWorkflow(def, callback?)
work.flow.definitions.get(uri) // → definition | undefined
work.flow.definitions.exists(uri) // → boolean
work.flow.definitions.valid(def) // → booleanInitiates a workflow run. Calls callback(null) on success.
Tracks execution state for named steps within a run. Each step must be started before it can be completed or failed.
import WorkflowState = require('work.flow/lib/work/flow/state');
const state = new WorkflowState();
state.start('step-a', (err) => { /* started */ });
state.complete('step-a', (err) => { /* completed */ });
state.fail('step-a', (err) => { /* marked as failed */ });
// Wait for one or more steps to complete (supports optional timeout)
state.awaits({ names: ['step-a', 'step-b'], timeout: 5000 }, (err) => {
// err is TimeoutError if timeout expires before all names complete
});| Class | Code | Import |
|---|---|---|
ValidationError |
400 | work.flow/lib/work/flow/error/validation |
NotFoundError |
404 | work.flow/lib/work/flow/error/not-found |
TimeoutError |
408 | work.flow/lib/work/flow/error/timeout |
ExecutionError |
500 | work.flow/lib/work/flow/error/execution |
All error classes extend Error and accept an optional message and details argument.
Install dependencies first:
npm installnpm testCompiles TypeScript to ./dist with declaration files and source maps.
npm run buildnpm run cleanQuestions or comments can be posted on the work.flow GitHub issues page.
Hector Gray (@defstream)
Pull Requests welcome. Please make sure all tests pass:
$ npm testPlease submit GitHub issues for any feature enhancements, bugs or documentation problems.
MIT
