react 0.3.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +2 -1
- package/README.md +99 -155
- package/doc/advanced.md +166 -0
- package/doc/color-def.graffle +938 -0
- package/doc/color-def.png +0 -0
- package/doc/default-simple.dot +19 -0
- package/doc/default-simple.dot.png +0 -0
- package/examples/{default1.js → longer-example.js} +0 -0
- package/examples/simple.js +45 -0
- package/examples/{ast1.js → using-ast-directly.js} +4 -0
- package/examples/using-events1.js +79 -0
- package/examples/{default-events1.js → using-log-events.js} +5 -14
- package/lib/base-task.js +7 -6
- package/lib/core.js +33 -14
- package/lib/event-collector.js +68 -0
- package/lib/event-manager.js +16 -13
- package/lib/finalcb-first-task.js +14 -11
- package/lib/finalcb-task.js +15 -11
- package/lib/id.js +1 -0
- package/lib/log-events.js +86 -0
- package/{promise-resolve.js → lib/promise-resolve.js} +5 -5
- package/lib/task.js +18 -8
- package/lib/track-tasks.js +60 -0
- package/lib/vcon.js +1 -1
- package/package.json +2 -2
- package/react.js +33 -1
- package/test/ast.test.js +27 -1
- package/test/core.test.js +71 -57
- package/test/dsl.test.js +2 -2
- package/test/module-use.test.js +14 -9
- package/test/promise-auto-resolve.test.js +2 -1
- package/Jakefile.js +0 -8
- package/dsl/chain.js +0 -150
- package/dsl/fstr.js +0 -121
- package/dsl/pcode.js +0 -175
- package/examples/chain-events1.js +0 -34
- package/examples/chain1.js +0 -19
- package/examples/fstr-events1.js +0 -52
- package/examples/fstr1.js +0 -37
- package/examples/pcode1.js +0 -22
- package/jake-tasks/jake-test.js +0 -64
- package/test/dsl/chain.test.js +0 -323
- package/test/dsl/fstr.test.js +0 -300
- package/test/dsl/pcode.test.js +0 -456
package/lib/finalcb-task.js
CHANGED
|
@@ -4,23 +4,23 @@ var sprintf = require('sprintf').sprintf;
|
|
|
4
4
|
var util = require('util');
|
|
5
5
|
|
|
6
6
|
var STATUS = require('./status.js');
|
|
7
|
+
var EventManager = require('./event-manager.js');
|
|
7
8
|
|
|
8
9
|
var OUTTASK_A_REQ = 'ast.outTask.a should be an array of string param names';
|
|
9
10
|
|
|
10
11
|
function FinalCbTask(outTaskOptions) {
|
|
11
12
|
var taskDef = outTaskOptions.taskDef;
|
|
12
|
-
|
|
13
|
-
var tasks = outTaskOptions.tasks;
|
|
14
|
-
var vCon = outTaskOptions.vCon;
|
|
15
|
-
var execOptions = outTaskOptions.execOptions;
|
|
16
|
-
var retValue = outTaskOptions.retValue;
|
|
17
|
-
if (typeof(cbFunc) !== 'function') throw new Error('callback is not a function');
|
|
13
|
+
if (typeof(outTaskOptions.cbFunc) !== 'function') throw new Error('callback is not a function');
|
|
18
14
|
var self = this;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
15
|
+
for (var k in taskDef) {
|
|
16
|
+
if (true) self[k] = taskDef[k]; // if to make jshint happy
|
|
17
|
+
}
|
|
18
|
+
this.f = outTaskOptions.cbFunc;
|
|
19
|
+
this.tasks = outTaskOptions.tasks;
|
|
20
|
+
this.vCon = outTaskOptions.vCon;
|
|
21
|
+
this.retValue = outTaskOptions.retValue;
|
|
22
|
+
this.execOptions = outTaskOptions.execOptions;
|
|
23
|
+
this.env = outTaskOptions.env;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
function format_error(errmsg, obj) {
|
|
@@ -44,11 +44,15 @@ FinalCbTask.prototype.isReady = function () {
|
|
|
44
44
|
FinalCbTask.prototype.exec = function (err) {
|
|
45
45
|
if (!this.f) return; //must have already been called
|
|
46
46
|
if (err) {
|
|
47
|
+
this.env.error = err;
|
|
48
|
+
this.env.flowEmitter.emit(EventManager.TYPES.EXEC_FLOW_ERRORED, this.env);
|
|
47
49
|
this.f.call(null, err); //call the final callback with the first error hit
|
|
48
50
|
} else { // no error, call with args
|
|
49
51
|
var vCon = this.vCon;
|
|
50
52
|
var finalArgs = this.a.map(function (k) { return vCon.getVar(k); });
|
|
51
53
|
finalArgs.unshift(null); //unshift err=null to front
|
|
54
|
+
this.env.results = finalArgs;
|
|
55
|
+
this.env.flowEmitter.emit(EventManager.TYPES.EXEC_FLOW_COMPLETE, this.env);
|
|
52
56
|
this.f.apply(null, finalArgs);
|
|
53
57
|
}
|
|
54
58
|
this.f = null; // prevent multiple calls
|
package/lib/id.js
CHANGED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Log events to console.error
|
|
5
|
+
|
|
6
|
+
@example
|
|
7
|
+
var react = require('react');
|
|
8
|
+
react.logEvents(); // log all task and flow events on all react functions
|
|
9
|
+
react.logEvents('task.*'); // log all task events on all react functions
|
|
10
|
+
react.logEvents(flowFn); // log all task and flow events on flowFn only
|
|
11
|
+
react.logEvents(flowFn, 'flow.*'); // log all flow events on flowFn only
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
var util = require('util'); // TODO replace inspect with something portable to browser
|
|
15
|
+
|
|
16
|
+
var react = require('../'); // require('react');
|
|
17
|
+
react.trackTasks(); // enable task and flow tracking
|
|
18
|
+
|
|
19
|
+
var ALL_FLOW_EVENTS = 'flow.*';
|
|
20
|
+
var ALL_TASK_EVENTS = 'task.*';
|
|
21
|
+
var FLOW_RE = /^flow\./;
|
|
22
|
+
|
|
23
|
+
function flowLog(obj) {
|
|
24
|
+
/*jshint validthis: true */
|
|
25
|
+
var time = new Date();
|
|
26
|
+
time.setTime(obj.time);
|
|
27
|
+
var argsNoCb = obj.args.filter(function (a) { return (typeof(a) !== 'function'); });
|
|
28
|
+
var eventTimeStr = time.toISOString();
|
|
29
|
+
if (this.event === 'flow.complete') {
|
|
30
|
+
var env = obj;
|
|
31
|
+
console.error('%s: %s \tmsecs: %s \n\targs: %s \n\tresults: %s\n',
|
|
32
|
+
this.event, env.name, env.elapsedTime, util.inspect(argsNoCb), util.inspect(env.results));
|
|
33
|
+
} else {
|
|
34
|
+
var name = obj.name;
|
|
35
|
+
var args = obj.args;
|
|
36
|
+
console.error('%s: %s \n\targs: %s\n', this.event, name, util.inspect(argsNoCb));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function taskLog(obj) {
|
|
41
|
+
/*jshint validthis: true */
|
|
42
|
+
var time = new Date();
|
|
43
|
+
time.setTime(obj.time);
|
|
44
|
+
var argsNoCb = obj.args.filter(function (a) { return (typeof(a) !== 'function'); });
|
|
45
|
+
var eventTimeStr = time.toISOString();
|
|
46
|
+
if (this.event === 'task.complete') {
|
|
47
|
+
var task = obj;
|
|
48
|
+
console.error('%s: %s:%s \tmsecs: %s \n\targs: %s \n\tresults: %s\n',
|
|
49
|
+
this.event, task.env.name, task.name, task.elapsedTime, util.inspect(argsNoCb), util.inspect(task.results));
|
|
50
|
+
} else {
|
|
51
|
+
var name = obj.name;
|
|
52
|
+
var args = obj.args;
|
|
53
|
+
console.error('%s: %s:%s \n\targs: %s\n', this.event, obj.env.name, obj.name, util.inspect(argsNoCb));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
Log flow and task events for a flowFn or all of react.
|
|
60
|
+
If called multiple times, remove previous listener (if any) before
|
|
61
|
+
adding.
|
|
62
|
+
|
|
63
|
+
@example
|
|
64
|
+
var react = require('react');
|
|
65
|
+
react.logEvents(flowFn, eventWildcard); //log events on flowfn matching wildcard
|
|
66
|
+
|
|
67
|
+
@param flowFn Flow function or global react object
|
|
68
|
+
@param eventWildcard wildcarded event type, if not provided use flow.* and task.*
|
|
69
|
+
*/
|
|
70
|
+
function logEvents(flowFn, eventWildcard) {
|
|
71
|
+
if (!flowFn) flowFn = react; // use global
|
|
72
|
+
if (eventWildcard && eventWildcard !== '*') {
|
|
73
|
+
var logFn = (FLOW_RE.test(eventWildcard)) ? flowLog : taskLog;
|
|
74
|
+
flowFn.events.removeListener(eventWildcard, logFn);
|
|
75
|
+
flowFn.events.on(eventWildcard, logFn);
|
|
76
|
+
} else { // none provided, use flow.* and task.*
|
|
77
|
+
//output events as tasks start and complete
|
|
78
|
+
flowFn.events.removeListener(ALL_FLOW_EVENTS, flowLog);
|
|
79
|
+
flowFn.events.on(ALL_FLOW_EVENTS, flowLog);
|
|
80
|
+
flowFn.events.removeListener(ALL_TASK_EVENTS, taskLog);
|
|
81
|
+
flowFn.events.on(ALL_TASK_EVENTS, taskLog);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = react;
|
|
86
|
+
module.exports.logEvents = logEvents;
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
var react = require('
|
|
13
|
+
var react = require('../'); // require('react');
|
|
14
14
|
|
|
15
15
|
var PROMISE_SUFFIX = '__promise'; // added to param names that are promises
|
|
16
16
|
|
|
17
|
-
react.events.on(react.events.TYPES.EXEC_TASKS_PRECREATE, function (
|
|
18
|
-
var vConValues =
|
|
19
|
-
var promiseParams =
|
|
17
|
+
react.events.on(react.events.TYPES.EXEC_TASKS_PRECREATE, function (env) {
|
|
18
|
+
var vConValues = env.vCon.values;
|
|
19
|
+
var promiseParams = env.ast.inParams.filter(function (p) {
|
|
20
20
|
var value = vConValues[p];
|
|
21
21
|
return (value && typeof(value.then) === 'function');
|
|
22
22
|
});
|
|
@@ -24,7 +24,7 @@ react.events.on(react.events.TYPES.EXEC_TASKS_PRECREATE, function (taskEnv) {
|
|
|
24
24
|
var promiseName = p + PROMISE_SUFFIX;
|
|
25
25
|
vConValues[promiseName] = vConValues[p];
|
|
26
26
|
vConValues[p] = undefined;
|
|
27
|
-
|
|
27
|
+
env.taskDefs.push({
|
|
28
28
|
type: 'when',
|
|
29
29
|
a: [promiseName],
|
|
30
30
|
out: [p]
|
package/lib/task.js
CHANGED
|
@@ -20,6 +20,9 @@ var TASK_TYPES = {
|
|
|
20
20
|
promise: PromiseTask,
|
|
21
21
|
when: WhenTask
|
|
22
22
|
};
|
|
23
|
+
|
|
24
|
+
var DEFAULT_TASK_NAME = 'task_%s'; // for unnamed tasks use task_idx, like task_0
|
|
25
|
+
|
|
23
26
|
function taskTypeKeys() { return Object.keys(TASK_TYPES); }
|
|
24
27
|
|
|
25
28
|
var OUT_TASK_TYPES = {
|
|
@@ -127,9 +130,10 @@ function validateLocalFunctions(inParams, taskDefs, locals) {
|
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
function fName(fn) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
if (typeof(fn) === 'function') {
|
|
134
|
+
return fn.name;
|
|
135
|
+
}
|
|
136
|
+
return (fn) ? fn : '';
|
|
133
137
|
}
|
|
134
138
|
|
|
135
139
|
/**
|
|
@@ -148,6 +152,7 @@ function nameTasks(tasks) { //name tasks that are not already named, validation
|
|
|
148
152
|
tasks.forEach(function (t, idx) {
|
|
149
153
|
if (!t.name) { //not already named
|
|
150
154
|
var name = fName(t.f);
|
|
155
|
+
if (!name) name = sprintf(DEFAULT_TASK_NAME, idx);
|
|
151
156
|
if (!name || namesMap[name]) {
|
|
152
157
|
name = sprintf('%s_%s', name, idx); //if empty or already used, postfix with _idx
|
|
153
158
|
}
|
|
@@ -163,7 +168,7 @@ function create(taskDef) {
|
|
|
163
168
|
return new TaskConstructor(taskDef);
|
|
164
169
|
}
|
|
165
170
|
|
|
166
|
-
function createOutTask(taskDef, cbFunc, tasks, vCon, execOptions) {
|
|
171
|
+
function createOutTask(taskDef, cbFunc, tasks, vCon, execOptions, env) {
|
|
167
172
|
setMissingOutTaskType(taskDef);
|
|
168
173
|
var outTaskOptions = {
|
|
169
174
|
taskDef: taskDef,
|
|
@@ -171,6 +176,7 @@ function createOutTask(taskDef, cbFunc, tasks, vCon, execOptions) {
|
|
|
171
176
|
tasks: tasks,
|
|
172
177
|
vCon: vCon,
|
|
173
178
|
execOptions: execOptions,
|
|
179
|
+
env: env,
|
|
174
180
|
TaskConstructor: OUT_TASK_TYPES[taskDef.type]
|
|
175
181
|
};
|
|
176
182
|
EventManager.global.emit(EventManager.TYPES.EXEC_OUTTASK_CREATE, outTaskOptions); // hook
|
|
@@ -181,6 +187,9 @@ function createOutTask(taskDef, cbFunc, tasks, vCon, execOptions) {
|
|
|
181
187
|
function createErrorHandler(vCon, outTask) {
|
|
182
188
|
return function handleError(task, err) {
|
|
183
189
|
task.status = STATUS.ERRORED;
|
|
190
|
+
task.error = err;
|
|
191
|
+
outTask.env.currentTask = task;
|
|
192
|
+
outTask.env.flowEmitter.emit(EventManager.TYPES.EXEC_TASK_ERRORED, task);
|
|
184
193
|
var errWithMeta = error.augmentError(err, {task: task, vcon: vCon});
|
|
185
194
|
outTask.exec(errWithMeta); //call the final callback with the first error hit
|
|
186
195
|
};
|
|
@@ -202,7 +211,7 @@ function execTasks(tasksReady, vCon, handleError, contExec) {
|
|
|
202
211
|
case everything is fine. If no tasks are running then
|
|
203
212
|
call handleError since this will never complete.
|
|
204
213
|
*/
|
|
205
|
-
function checkIfTasksRunning(vCon, tasks, handleError) {
|
|
214
|
+
function checkIfTasksRunning(vCon, tasks, handleError, env) {
|
|
206
215
|
var tasksRunning = tasks.filter(function (t) {
|
|
207
216
|
return (t.status === STATUS.RUNNING || t.status === STATUS.READY);
|
|
208
217
|
});
|
|
@@ -210,13 +219,14 @@ function checkIfTasksRunning(vCon, tasks, handleError) {
|
|
|
210
219
|
var remainingTasks = tasks.filter(function (t) { return (!t.status); });
|
|
211
220
|
var remainingTNames = remainingTasks.map(function (t) { return t.name; });
|
|
212
221
|
var errMsg = sprintf(NO_TASKS_RUNNING_WONT_COMPLETE, remainingTNames.join(', '));
|
|
213
|
-
|
|
222
|
+
var emptyTask = { env: env };
|
|
223
|
+
handleError(emptyTask, new Error(errMsg));
|
|
214
224
|
}
|
|
215
225
|
}
|
|
216
226
|
|
|
217
|
-
function findReadyAndExec(vCon, tasks, tasksByName, handleError, contExec) {
|
|
227
|
+
function findReadyAndExec(vCon, tasks, tasksByName, handleError, contExec, env) {
|
|
218
228
|
var tasksReady = findTasksReady(vCon, tasks, tasksByName);
|
|
219
|
-
if (!tasksReady.length) checkIfTasksRunning(vCon, tasks, handleError); // no tasks to run, check if ok
|
|
229
|
+
if (!tasksReady.length) checkIfTasksRunning(vCon, tasks, handleError, env); // no tasks to run, check if ok
|
|
220
230
|
execTasks(tasksReady, vCon, handleError, contExec);
|
|
221
231
|
}
|
|
222
232
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Track the tasks, start, complete, args, results, elapsed time
|
|
5
|
+
Emits events that can be monitored
|
|
6
|
+
|
|
7
|
+
- track start and complete
|
|
8
|
+
- record args each task was called with
|
|
9
|
+
- record results at completion
|
|
10
|
+
- record start, end, and calc elapsed time
|
|
11
|
+
- emits flow.begin with flowEnv
|
|
12
|
+
- emits task.begin with task
|
|
13
|
+
- emits task.complete with task
|
|
14
|
+
- emits flow complete with flowEnv
|
|
15
|
+
- emits flow errored with flowEnv
|
|
16
|
+
|
|
17
|
+
@example
|
|
18
|
+
var react = require('react');
|
|
19
|
+
react.trackTasks(); // enable task and flow tracking
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
var react = require('../'); // require('react');
|
|
24
|
+
|
|
25
|
+
react.events.on(react.events.TYPES.EXEC_FLOW_START, function (env){
|
|
26
|
+
env.startTime = Date.now();
|
|
27
|
+
env.flowEmitter.emit(react.events.TYPES.FLOW_BEGIN, env); //fire public ev
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
react.events.on(react.events.TYPES.EXEC_TASK_START, function (task) {
|
|
31
|
+
task.startTime = Date.now();
|
|
32
|
+
task.env.flowEmitter.emit(react.events.TYPES.TASK_BEGIN, task); //fire public ev
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
react.events.on(react.events.TYPES.EXEC_TASK_COMPLETE, function (task) {
|
|
36
|
+
task.endTime = Date.now();
|
|
37
|
+
task.elapsedTime = task.endTime - task.startTime;
|
|
38
|
+
task.env.flowEmitter.emit(react.events.TYPES.TASK_COMPLETE, task); // fire public ev
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
react.events.on(react.events.TYPES.EXEC_TASK_ERRORED, function (task) {
|
|
42
|
+
task.endTime = Date.now();
|
|
43
|
+
task.elapsedTime = task.endTime - task.startTime;
|
|
44
|
+
task.env.flowEmitter.emit(react.events.TYPES.TASK_ERRORED, task); // fire public ev
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
react.events.on(react.events.TYPES.EXEC_FLOW_COMPLETE, function (env) {
|
|
48
|
+
env.endTime = Date.now();
|
|
49
|
+
env.elapsedTime = env.endTime - env.startTime;
|
|
50
|
+
env.flowEmitter.emit(react.events.TYPES.FLOW_COMPLETE, env); //fire public ev
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
react.events.on(react.events.TYPES.EXEC_FLOW_ERRORED, function (env) {
|
|
54
|
+
env.endTime = Date.now();
|
|
55
|
+
env.elapsedTime = env.endTime - env.startTime;
|
|
56
|
+
env.flowEmitter.emit(react.events.TYPES.FLOW_ERRORED, env); //fire public ev
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
module.exports = react; // return react
|
package/lib/vcon.js
CHANGED
|
@@ -71,7 +71,7 @@ VContext.create = function (args, inParams, locals, self) {
|
|
|
71
71
|
var vContext = new VContext();
|
|
72
72
|
vContext.values = args.reduce(function (vcon, x, idx) { // create vCon start with input args
|
|
73
73
|
var param = inParams[idx];
|
|
74
|
-
if (param) vcon[param] = x;
|
|
74
|
+
if (param) vcon[param] = (x !== undefined) ? x : null; // upgrade undefined to null
|
|
75
75
|
return vcon;
|
|
76
76
|
}, initValues);
|
|
77
77
|
return vContext;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react",
|
|
3
|
-
"description": "React is a javascript module to make it easier to work with asynchronous code, by reducing boilerplate code and improving error and exception handling while allowing variable and task dependencies when defining flow.",
|
|
4
|
-
"version": "0.
|
|
3
|
+
"description": "React is a javascript module implementing a lightweight rules engine to make it easier to work with asynchronous code, by reducing boilerplate code and improving error and exception handling while allowing variable and task dependencies when defining flow.",
|
|
4
|
+
"version": "0.5.1",
|
|
5
5
|
"author": "Jeff Barczewski <jeff.barczewski@gmail.com>",
|
|
6
6
|
"repository": { "type": "git", "url": "http://github.com/jeffbski/react.git" },
|
|
7
7
|
"bugs" : { "url": "http://github.com/jeffbski/react/issues" },
|
package/react.js
CHANGED
|
@@ -2,7 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
var core = require('./lib/core.js');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
If called, load the built-in plugin for log events and invoke
|
|
7
|
+
|
|
8
|
+
@param flowFn [function] if not provided uses global react
|
|
9
|
+
@param eventWildcard [string] pattern to log events for
|
|
10
|
+
*/
|
|
11
|
+
function logEvents(flowFn, eventWildcard) {
|
|
12
|
+
var logEventsMod = require('./lib/log-events');
|
|
13
|
+
if (!eventWildcard && typeof(flowFn) === 'string') { // only wildcard provided
|
|
14
|
+
eventWildcard = flowFn;
|
|
15
|
+
flowFn = undefined;
|
|
16
|
+
}
|
|
17
|
+
return logEventsMod.logEvents(flowFn, eventWildcard);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
Enable detection of promises and resolution
|
|
22
|
+
*/
|
|
23
|
+
function resolvePromises() {
|
|
24
|
+
require('./lib/promise-resolve');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
Enable tracking of tasks and flow execution, emitting events and
|
|
29
|
+
tracking start, end, elapsed time
|
|
30
|
+
*/
|
|
31
|
+
function trackTasks() {
|
|
32
|
+
require('./lib/track-tasks');
|
|
33
|
+
}
|
|
34
|
+
|
|
5
35
|
module.exports = require('./lib/dsl.js'); // core + default dsl
|
|
6
36
|
module.exports.options = core.options; // global react options
|
|
7
37
|
module.exports.events = core.events; // global react event emitter
|
|
8
|
-
|
|
38
|
+
module.exports.logEvents = logEvents; // enable event logging
|
|
39
|
+
module.exports.resolvePromises = resolvePromises; // enable promise resolution
|
|
40
|
+
module.exports.trackTasks = trackTasks; // enable tracking of tasks
|
package/test/ast.test.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
var test = require('tap').test;
|
|
4
4
|
|
|
5
|
-
var react = require('../react');
|
|
5
|
+
var react = require('../'); // require('react');
|
|
6
|
+
var EventCollector = require('../lib/event-collector');
|
|
6
7
|
|
|
7
8
|
function load(res, cb) { cb(null, res + '-loaded'); }
|
|
8
9
|
function prefix(prefstr, str, cb) { cb(null, prefstr + str); }
|
|
@@ -38,6 +39,31 @@ test('mixed', function (t) {
|
|
|
38
39
|
});
|
|
39
40
|
});
|
|
40
41
|
|
|
42
|
+
test('ast.defined event called when ast is defined', function (t) {
|
|
43
|
+
var fn = react();
|
|
44
|
+
var collector = new EventCollector();
|
|
45
|
+
collector.capture(fn, 'ast.*');
|
|
46
|
+
|
|
47
|
+
var errors = fn.setAndValidateAST({
|
|
48
|
+
inParams: ['res', 'prefstr', 'poststr'],
|
|
49
|
+
tasks: [
|
|
50
|
+
{ f: load, a: ['res'], out: ['lres'] },
|
|
51
|
+
{ f: upper, a: ['lres'], out: ['ulres'], type: 'ret' },
|
|
52
|
+
{ f: prefix, a: ['prefstr', 'ulres'], out: ['plres'] },
|
|
53
|
+
{ f: postfix, a: ['plres', 'poststr'], out: ['plresp'] }
|
|
54
|
+
],
|
|
55
|
+
outTask: { a: ['plresp'] }
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
var events = collector.list();
|
|
59
|
+
t.equal(events.length, 1);
|
|
60
|
+
t.type(events[0].ast, 'object');
|
|
61
|
+
t.ok(events[0].ast.inParams);
|
|
62
|
+
t.ok(events[0].ast.tasks);
|
|
63
|
+
t.ok(events[0].ast.outTask);
|
|
64
|
+
t.end();
|
|
65
|
+
});
|
|
66
|
+
|
|
41
67
|
test('cb with err', function (t) {
|
|
42
68
|
t.plan(5);
|
|
43
69
|
|
package/test/core.test.js
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
var test = require('tap').test;
|
|
4
4
|
|
|
5
5
|
var react = require('../react');
|
|
6
|
+
var EventCollector = require('../lib/event-collector'); // require('react/lib/event-collector'); // turn on tracking and get EventCollector
|
|
6
7
|
|
|
7
8
|
function multiply(x, y, cb) { cb(null, x * y); }
|
|
8
9
|
function add(x, y, cb) { cb(null, x + y); }
|
|
9
10
|
function badFunc(a, b, cb) { throw new Error('badFuncThrow'); }
|
|
10
11
|
function badF2(a, b, cb) { cb('my-error'); }
|
|
11
12
|
function fnRetsSum(a, b) { return a + b; }
|
|
13
|
+
var anonFn = function (a, b) { return a + b; };
|
|
12
14
|
|
|
13
15
|
test('set and validate AST', function (t) {
|
|
14
16
|
var fn = react();
|
|
@@ -41,16 +43,19 @@ test('unnamed tasks will be assigned unique names', function (t) {
|
|
|
41
43
|
{ f: multiply, a: ['a', 'b'], out: ['c'] },
|
|
42
44
|
{ f: multiply, a: ['a', 'b'], out: ['d'], name: 'multiply' },
|
|
43
45
|
{ f: multiply, a: ['a', 'b'], out: ['e'], name: 'times' },
|
|
46
|
+
{ f: anonFn, a: ['a', 'b'], out: ['g'], type: 'ret' },
|
|
44
47
|
{ f: multiply, a: ['a', 'b'], out: ['f'] }
|
|
45
48
|
],
|
|
46
49
|
outTask: { a: ['c'] }
|
|
47
50
|
});
|
|
48
51
|
t.deepEqual(errors, [], 'should set and validate as true');
|
|
52
|
+
t.equal(fn.ast.name.slice(0, 'flow_'.length), 'flow_', 'generated flow name should start with flow_');
|
|
49
53
|
t.deepEqual(fn.ast.tasks, [
|
|
50
54
|
{ f: multiply, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'multiply_0' },
|
|
51
55
|
{ f: multiply, a: ['a', 'b'], out: ['d'], name: 'multiply', type: 'cb' },
|
|
52
56
|
{ f: multiply, a: ['a', 'b'], out: ['e'], name: 'times', type: 'cb' },
|
|
53
|
-
{ f:
|
|
57
|
+
{ f: anonFn, a: ['a', 'b'], out: ['g'], type: 'ret', name: 'task_3' },
|
|
58
|
+
{ f: multiply, a: ['a', 'b'], out: ['f'], type: 'cb', name: 'multiply_4' }
|
|
54
59
|
]);
|
|
55
60
|
t.end();
|
|
56
61
|
});
|
|
@@ -107,19 +112,17 @@ test('multi-step with after as nonarr fn', function (t) {
|
|
|
107
112
|
});
|
|
108
113
|
t.deepEqual(errors, [], 'no validation errors');
|
|
109
114
|
|
|
110
|
-
var
|
|
111
|
-
|
|
112
|
-
events.push(task);
|
|
113
|
-
}
|
|
114
|
-
fn.events.on('task.complete', accumEvents);
|
|
115
|
+
var collector = new EventCollector();
|
|
116
|
+
collector.capture(fn, 'task.complete');
|
|
115
117
|
|
|
116
118
|
fn(2, 3, function (err, c, d) {
|
|
117
119
|
t.equal(err, null);
|
|
118
120
|
t.equal(c, 6);
|
|
119
121
|
t.equal(d, 5);
|
|
122
|
+
var events = collector.list();
|
|
120
123
|
t.equal(events.length, 2, 'should have seen one task compl events');
|
|
121
|
-
t.equal(events[0].name, 'add', 'name matches');
|
|
122
|
-
t.equal(events[1].name, 'multiply', 'name matches');
|
|
124
|
+
t.equal(events[0].task.name, 'add', 'name matches');
|
|
125
|
+
t.equal(events[1].task.name, 'multiply', 'name matches');
|
|
123
126
|
t.end();
|
|
124
127
|
});
|
|
125
128
|
});
|
|
@@ -137,31 +140,29 @@ test('mixed multi-step with after as nonarr fn w/events', function (t) {
|
|
|
137
140
|
});
|
|
138
141
|
t.deepEqual(errors, [], 'no validation errors');
|
|
139
142
|
|
|
140
|
-
var
|
|
141
|
-
|
|
142
|
-
events.push(task);
|
|
143
|
-
}
|
|
144
|
-
fn.events.on('task.complete', accumEvents);
|
|
143
|
+
var collector = new EventCollector();
|
|
144
|
+
collector.capture(fn, 'task.complete');
|
|
145
145
|
|
|
146
146
|
fn(2, 3, function (err, c, d) {
|
|
147
147
|
t.equal(err, null);
|
|
148
148
|
t.equal(c, 6);
|
|
149
149
|
t.equal(d, 5);
|
|
150
|
+
var events = collector.list();
|
|
150
151
|
t.equal(events.length, 2, 'should have seen one task compl events');
|
|
151
|
-
t.equal(events[0].name, 'fnRetsSum', 'name matches');
|
|
152
|
-
t.ok(events[0].id, 'has unique id');
|
|
153
|
-
t.ok(events[0].startTime, 'has startTime');
|
|
154
|
-
t.ok(events[0].endTime, 'has endTime');
|
|
155
|
-
t.ok(events[0].elapsedTime !== undefined, 'has elapsedTime');
|
|
156
|
-
t.ok(events[0].args, 'has args');
|
|
157
|
-
t.ok(events[0].results, 'has results');
|
|
158
|
-
t.equal(events[1].name, 'multiply', 'name matches');
|
|
159
|
-
t.ok(events[1].id, 'has unique id');
|
|
160
|
-
t.ok(events[1].startTime, 'has startTime');
|
|
161
|
-
t.ok(events[1].endTime, 'has endTime');
|
|
162
|
-
t.ok(events[1].elapsedTime !== undefined, 'has elapsedTime');
|
|
163
|
-
t.ok(events[1].args, 'has args');
|
|
164
|
-
t.ok(events[1].results, 'has results');
|
|
152
|
+
t.equal(events[0].task.name, 'fnRetsSum', 'name matches');
|
|
153
|
+
t.ok(events[0].task.id, 'has unique id');
|
|
154
|
+
t.ok(events[0].task.startTime, 'has startTime');
|
|
155
|
+
t.ok(events[0].task.endTime, 'has endTime');
|
|
156
|
+
t.ok(events[0].task.elapsedTime !== undefined, 'has elapsedTime');
|
|
157
|
+
t.ok(events[0].task.args, 'has args');
|
|
158
|
+
t.ok(events[0].task.results, 'has results');
|
|
159
|
+
t.equal(events[1].task.name, 'multiply', 'name matches');
|
|
160
|
+
t.ok(events[1].task.id, 'has unique id');
|
|
161
|
+
t.ok(events[1].task.startTime, 'has startTime');
|
|
162
|
+
t.ok(events[1].task.endTime, 'has endTime');
|
|
163
|
+
t.ok(events[1].task.elapsedTime !== undefined, 'has elapsedTime');
|
|
164
|
+
t.ok(events[1].task.args, 'has args');
|
|
165
|
+
t.ok(events[1].task.results, 'has results');
|
|
165
166
|
t.end();
|
|
166
167
|
});
|
|
167
168
|
});
|
|
@@ -434,6 +435,27 @@ test('using "this" in a sync function', function (t) {
|
|
|
434
435
|
}]);
|
|
435
436
|
});
|
|
436
437
|
|
|
438
|
+
test('undefined input arguments will be upgraded from undefined to null', function (t) {
|
|
439
|
+
var fn = react();
|
|
440
|
+
function concat(a, b) {
|
|
441
|
+
return '' + a + b;
|
|
442
|
+
}
|
|
443
|
+
var errors = fn.setAndValidateAST({
|
|
444
|
+
inParams: ['a', 'b'],
|
|
445
|
+
tasks: [
|
|
446
|
+
{ f: concat, a: ['a', 'b'], out: ['c'], type: 'ret' }
|
|
447
|
+
],
|
|
448
|
+
outTask: { a: ['c'] }
|
|
449
|
+
});
|
|
450
|
+
t.deepEqual(errors, [], 'no validation errors');
|
|
451
|
+
fn('first', undefined, function (err, c) { // undefined second param, upgrade to null
|
|
452
|
+
t.equal(err, null);
|
|
453
|
+
t.equal(c, 'firstnull');
|
|
454
|
+
t.end();
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
|
|
437
459
|
|
|
438
460
|
// Select first tests
|
|
439
461
|
|
|
@@ -451,18 +473,16 @@ test('selectFirst with first succeeding', function (t) {
|
|
|
451
473
|
});
|
|
452
474
|
t.deepEqual(errors, [], 'no validation errors');
|
|
453
475
|
|
|
454
|
-
var
|
|
455
|
-
|
|
456
|
-
events.push(task);
|
|
457
|
-
}
|
|
458
|
-
fn.events.on('task.complete', accumEvents);
|
|
476
|
+
var collector = new EventCollector();
|
|
477
|
+
collector.capture(fn, 'task.complete');
|
|
459
478
|
|
|
460
479
|
fn(2, 3, function (err, c) {
|
|
461
480
|
t.equal(err, null);
|
|
462
481
|
t.equal(c, 6);
|
|
482
|
+
var events = collector.list();
|
|
463
483
|
t.equal(events.length, 1, 'should have seen one task compl events');
|
|
464
|
-
t.equal(events[0].name, 'multiply', 'name matches');
|
|
465
|
-
t.deepEqual(events[0].results, [6], 'results match');
|
|
484
|
+
t.equal(events[0].task.name, 'multiply', 'name matches');
|
|
485
|
+
t.deepEqual(events[0].task.results, [6], 'results match');
|
|
466
486
|
t.end();
|
|
467
487
|
});
|
|
468
488
|
});
|
|
@@ -484,18 +504,16 @@ test('selectFirst with third succeeding', function (t) {
|
|
|
484
504
|
});
|
|
485
505
|
t.deepEqual(errors, [], 'no validation errors');
|
|
486
506
|
|
|
487
|
-
var
|
|
488
|
-
|
|
489
|
-
events.push(task);
|
|
490
|
-
}
|
|
491
|
-
fn.events.on('task.complete', accumEvents);
|
|
507
|
+
var collector = new EventCollector();
|
|
508
|
+
collector.capture(fn, 'task.complete');
|
|
492
509
|
|
|
493
510
|
fn(2, 3, function (err, c) {
|
|
494
511
|
t.equal(err, null);
|
|
495
512
|
t.equal(c, 5);
|
|
513
|
+
var events = collector.list();
|
|
496
514
|
t.equal(events.length, 3, 'should have seen three task compl events');
|
|
497
|
-
t.equal(events[2].name, 'add', 'name matches');
|
|
498
|
-
t.deepEqual(events[2].results, [5], 'results match');
|
|
515
|
+
t.equal(events[2].task.name, 'add', 'name matches');
|
|
516
|
+
t.deepEqual(events[2].task.results, [5], 'results match');
|
|
499
517
|
t.end();
|
|
500
518
|
});
|
|
501
519
|
});
|
|
@@ -521,20 +539,18 @@ test('selectFirst forces order with third succeeding', function (t) {
|
|
|
521
539
|
});
|
|
522
540
|
t.deepEqual(errors, [], 'no validation errors');
|
|
523
541
|
|
|
524
|
-
var
|
|
525
|
-
|
|
526
|
-
events.push(task);
|
|
527
|
-
}
|
|
528
|
-
fn.events.on('task.complete', accumEvents);
|
|
542
|
+
var collector = new EventCollector();
|
|
543
|
+
collector.capture(fn, 'task.complete');
|
|
529
544
|
|
|
530
545
|
fn(2, 3, function (err, c) {
|
|
531
546
|
t.equal(err, null);
|
|
532
547
|
t.equal(c, 5);
|
|
548
|
+
var events = collector.list();
|
|
533
549
|
t.equal(events.length, 3, 'should have seen three task compl events');
|
|
534
|
-
t.equal(events[0].name, 'noSuccess', 'name matches');
|
|
535
|
-
t.equal(events[1].name, 'noSuccessNull', 'name matches');
|
|
536
|
-
t.equal(events[2].name, 'add', 'name matches');
|
|
537
|
-
t.deepEqual(events[2].results, [5], 'results match');
|
|
550
|
+
t.equal(events[0].task.name, 'noSuccess', 'name matches');
|
|
551
|
+
t.equal(events[1].task.name, 'noSuccessNull', 'name matches');
|
|
552
|
+
t.equal(events[2].task.name, 'add', 'name matches');
|
|
553
|
+
t.deepEqual(events[2].task.results, [5], 'results match');
|
|
538
554
|
t.end();
|
|
539
555
|
});
|
|
540
556
|
});
|
|
@@ -560,18 +576,16 @@ test('selectFirst using direct returns', function (t) {
|
|
|
560
576
|
});
|
|
561
577
|
t.deepEqual(errors, [], 'no validation errors');
|
|
562
578
|
|
|
563
|
-
var
|
|
564
|
-
|
|
565
|
-
events.push(task);
|
|
566
|
-
}
|
|
567
|
-
fn.events.on('task.complete', accumEvents);
|
|
579
|
+
var collector = new EventCollector();
|
|
580
|
+
collector.capture(fn, 'task.complete');
|
|
568
581
|
|
|
569
582
|
fn(2, 3, function (err, c) {
|
|
570
583
|
t.equal(err, null);
|
|
571
584
|
t.equal(c, 5);
|
|
585
|
+
var events = collector.list();
|
|
572
586
|
t.equal(events.length, 3, 'should have seen three task compl events');
|
|
573
|
-
t.equal(events[2].name, 'addRet', 'name matches');
|
|
574
|
-
t.deepEqual(events[2].results, [5], 'results match');
|
|
587
|
+
t.equal(events[2].task.name, 'addRet', 'name matches');
|
|
588
|
+
t.deepEqual(events[2].task.results, [5], 'results match');
|
|
575
589
|
t.end();
|
|
576
590
|
});
|
|
577
591
|
});
|