react 0.2.2 → 0.2.6
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/README.md +8 -7
- package/lib/core.js +4 -4
- package/lib/dsl.js +3 -0
- package/lib/event-manager.js +2 -1
- package/lib/fstr.js +11 -2
- package/lib/pcode.js +11 -2
- package/lib/task.js +7 -2
- package/lib/validate.js +58 -1
- package/lib/vcon.js +2 -0
- package/package.json +1 -1
- package/test/chain.test.js +19 -5
- package/test/core.test.js +5 -4
- package/test/dsl.test.js +19 -6
- package/test/fstr.test.js +18 -6
- package/test/pcode.test.js +18 -4
- package/test/validate.test.js +77 -2
package/README.md
CHANGED
|
@@ -242,7 +242,8 @@ fn(2, 3, function (err, m, s) {
|
|
|
242
242
|
|
|
243
243
|
## Status
|
|
244
244
|
|
|
245
|
-
- 2012-01-
|
|
245
|
+
- 2012-01-11 - Provide warning/error when name is skipped in default DSL, literal check in validate (v0.2.5)
|
|
246
|
+
- 2012-01-10 - Create default DSL for react(), create error for missing variables, list remaining tasks when flow won't complete
|
|
246
247
|
- 2011-12-21 - Refactor from ground up with tests, changes to the interfaces
|
|
247
248
|
- 2011-10-26 - React is in active development and interface may change frequently in these early stages. Current code is functional but does not perform validation yet. Additional interfaces are planned to make it easy to define flows in a variety of ways. Documentation and examples forthcoming.
|
|
248
249
|
|
|
@@ -251,23 +252,23 @@ fn(2, 3, function (err, m, s) {
|
|
|
251
252
|
```bash
|
|
252
253
|
ok ast.test.js .................... 10/10
|
|
253
254
|
ok cb-task.test.js ................ 31/31
|
|
254
|
-
ok chain.test.js ..................
|
|
255
|
+
ok chain.test.js .................. 59/59
|
|
255
256
|
ok core.test.js ................... 98/98
|
|
256
|
-
ok dsl.test.js ....................
|
|
257
|
+
ok dsl.test.js .................... 63/63
|
|
257
258
|
ok event-manager.test.js .......... 13/13
|
|
258
259
|
ok exec-options.test.js ............. 3/3
|
|
259
260
|
ok finalcb-task.test.js ............. 5/5
|
|
260
|
-
ok fstr.test.js ...................
|
|
261
|
+
ok fstr.test.js ................... 67/67
|
|
261
262
|
ok input-parser.test.js ........... 15/15
|
|
262
263
|
ok module-use.test.js ............. 64/64
|
|
263
|
-
ok pcode.test.js ..................
|
|
264
|
+
ok pcode.test.js .................. 68/68
|
|
264
265
|
ok ret-task.test.js ............... 31/31
|
|
265
266
|
ok task.test.js ..................... 1/1
|
|
266
267
|
ok validate-cb-task.test.js ......... 6/6
|
|
267
268
|
ok validate-ret-task.test.js ........ 7/7
|
|
268
|
-
ok validate.test.js ...............
|
|
269
|
+
ok validate.test.js ............... 31/31
|
|
269
270
|
ok vcon.test.js ................... 42/42
|
|
270
|
-
total ...........................
|
|
271
|
+
total ........................... 632/632
|
|
271
272
|
|
|
272
273
|
ok
|
|
273
274
|
```
|
package/lib/core.js
CHANGED
|
@@ -13,10 +13,10 @@ var inputParser = require('./input-parser.js');
|
|
|
13
13
|
var idGenerator = require('./id.js');
|
|
14
14
|
|
|
15
15
|
var reactOptions = {
|
|
16
|
-
stackTraceLimitMin: 30
|
|
16
|
+
stackTraceLimitMin: 30
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
var reactEmitter = EventManager.
|
|
19
|
+
var reactEmitter = EventManager.globalEventManager; // the top emitter
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
Creates react function which the AST can be manipulated and then
|
|
@@ -39,7 +39,7 @@ var reactEmitter = EventManager.create(); // the top emitter
|
|
|
39
39
|
*/
|
|
40
40
|
function reactFactory() {
|
|
41
41
|
if (arguments.length) throw new Error('react() takes no args, check API');
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
error.ensureStackTraceLimitSet(reactOptions.stackTraceLimitMin);
|
|
44
44
|
var flowEmitter = EventManager.create();
|
|
45
45
|
flowEmitter.parent = reactEmitter;
|
|
@@ -75,7 +75,7 @@ function reactFactory() {
|
|
|
75
75
|
if (outTask.isReady()) return outTask.exec(); // all tasks done, exec cb, return
|
|
76
76
|
tskutil.findReadyAndExec(vCon, tasks, tasksByName, handleError, contExec); //exec tasks that ready to run
|
|
77
77
|
}
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
tasks.forEach(function (t) {
|
|
80
80
|
t.id = idGenerator.createUniqueId();
|
|
81
81
|
t.flowEmitter = flowEmitter;
|
package/lib/dsl.js
CHANGED
|
@@ -6,9 +6,11 @@ var core = require('./core.js');
|
|
|
6
6
|
var parse = require('./parse.js');
|
|
7
7
|
var tutil = require('./task.js');
|
|
8
8
|
|
|
9
|
+
var MISSING_NAME = 'param[0] should be the flow name, instead found in/out def: %s';
|
|
9
10
|
var INOUT_PARAMS_NO_MATCH = 'params in wrong format, wanted "foo, bar cb -> err, baz" - found: %s';
|
|
10
11
|
var EXTRA_TASKARG = 'extra unmatched task arg: %s';
|
|
11
12
|
|
|
13
|
+
var INOUT_RE = /\->/; // used to detect missing name, in/out as first arg
|
|
12
14
|
var CB_NAMES_RE = /^cb|callback$/i; //cb, Cb, CB, callback, Callback
|
|
13
15
|
var ERR_NAMES_RE = /^err$/i; // err, ERR, Err, ...
|
|
14
16
|
|
|
@@ -81,6 +83,7 @@ function parseVargs(vargs) {
|
|
|
81
83
|
|
|
82
84
|
function dslDefine(name, arg1, arg2, argN) {
|
|
83
85
|
var reactFn = core();
|
|
86
|
+
if (name && INOUT_RE.test(name)) throw new Error(sprintf(MISSING_NAME, name));
|
|
84
87
|
var defObj = parseVargs(Array.prototype.slice.call(arguments, 1)); // name, already used
|
|
85
88
|
var inOutDef = parseInOutParams(defObj.inOutParamStr);
|
|
86
89
|
var ast = {
|
package/lib/event-manager.js
CHANGED
package/lib/fstr.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
/*jshint regexp: false */
|
|
2
3
|
|
|
3
4
|
var sprintf = require('sprintf').sprintf;
|
|
4
5
|
var core = require('./core.js');
|
|
@@ -10,14 +11,22 @@ var OUTPARAMS_NO_MATCH = 'output params in wrong format, wanted "foo, bar" - fou
|
|
|
10
11
|
var INOUT_PARAMS_NO_MATCH = 'task params in wrong format, wanted "foo, bar -> err, baz" - found: %s';
|
|
11
12
|
var EXTRA_TASKARG = 'extra unmatched task arg: %s';
|
|
12
13
|
|
|
14
|
+
var ERR_NAMES_RE = /^err$/i; // err, ERR, Err, ...
|
|
15
|
+
|
|
16
|
+
function filterOutLeadingErrParam(args) { // if leading err param, filter it out
|
|
17
|
+
if (args.length && args[0].match(ERR_NAMES_RE)) args.shift();
|
|
18
|
+
return args;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
13
22
|
var inOutDefParse = {
|
|
14
|
-
regex: /^([
|
|
23
|
+
regex: /^([^\-]*)(->)?\s*(returns?\s+)?(.*)$/i,
|
|
15
24
|
fn: function (m) {
|
|
16
25
|
var reMatchReturns = /returns?/i;
|
|
17
26
|
return {
|
|
18
27
|
type: (m[3] && m[3].match(reMatchReturns)) ? 'ret' : 'cb',
|
|
19
28
|
inDef: parse.splitTrimFilterArgs(m[1]),
|
|
20
|
-
outDef: parse.splitTrimFilterArgs(m[4])
|
|
29
|
+
outDef: filterOutLeadingErrParam(parse.splitTrimFilterArgs(m[4]))
|
|
21
30
|
};
|
|
22
31
|
}
|
|
23
32
|
};
|
package/lib/pcode.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
/*jshint regexp: false */
|
|
2
3
|
|
|
3
4
|
var sprintf = require('sprintf').sprintf;
|
|
4
5
|
var core = require('./core.js');
|
|
@@ -10,6 +11,14 @@ var OUTPARAMS_NO_MATCH = 'output params in wrong format, wanted "cb(err, foo)" -
|
|
|
10
11
|
var INOUT_PARAMS_NO_MATCH = 'task params in wrong format, wanted "foo, bar := func(baz, cat, cb) " - found: %s';
|
|
11
12
|
var EXTRA_TASKARG = 'extra unmatched task arg: %s';
|
|
12
13
|
|
|
14
|
+
var ERR_NAMES_RE = /^err$/i; // err, ERR, Err, ...
|
|
15
|
+
|
|
16
|
+
function filterOutLeadingErrParam(args) { // if leading err param, filter it out
|
|
17
|
+
if (args.length && args[0].match(ERR_NAMES_RE)) args.shift();
|
|
18
|
+
return args;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
13
22
|
/**
|
|
14
23
|
Examples:
|
|
15
24
|
var react = require('react');
|
|
@@ -82,10 +91,10 @@ var retParse = {
|
|
|
82
91
|
};
|
|
83
92
|
|
|
84
93
|
var finalCbParse = {
|
|
85
|
-
regex: /^\s*(cb|callback)\s*\((
|
|
94
|
+
regex: /^\s*(cb|callback)\s*\(([^)]*)\)\s*;?$/i,
|
|
86
95
|
fn: function (m) {
|
|
87
96
|
return {
|
|
88
|
-
outDef: (m[
|
|
97
|
+
outDef: (m[2]) ? filterOutLeadingErrParam(parse.splitTrimFilterArgs(m[2])) : []
|
|
89
98
|
};
|
|
90
99
|
}
|
|
91
100
|
};
|
package/lib/task.js
CHANGED
|
@@ -25,7 +25,7 @@ function outTaskTypeKeys() { return Object.keys(OUT_TASK_TYPES); }
|
|
|
25
25
|
|
|
26
26
|
var LOCAL_FN_MISSING = 'function: %s not found in locals or input params - task[%s]';
|
|
27
27
|
var TASKDEF_IS_OBJECT = 'task must be an object';
|
|
28
|
-
var NO_TASKS_RUNNING_WONT_COMPLETE = 'no tasks running, flow will not complete';
|
|
28
|
+
var NO_TASKS_RUNNING_WONT_COMPLETE = 'no tasks running, flow will not complete, remaining tasks: %s';
|
|
29
29
|
var TASK_TYPE_SHOULD_MATCH = 'task.type should match one of ' +
|
|
30
30
|
Object.keys(TASK_TYPES).join(', ');
|
|
31
31
|
|
|
@@ -201,7 +201,12 @@ function checkIfTasksRunning(vCon, tasks, handleError) {
|
|
|
201
201
|
var tasksRunning = tasks.filter(function (t) {
|
|
202
202
|
return (t.status === STATUS.RUNNING || t.status === STATUS.READY);
|
|
203
203
|
});
|
|
204
|
-
if (!tasksRunning.length)
|
|
204
|
+
if (!tasksRunning.length) {
|
|
205
|
+
var remainingTasks = tasks.filter(function (t) { return (!t.status); });
|
|
206
|
+
var remainingTNames = remainingTasks.map(function (t) { return t.name; });
|
|
207
|
+
var errMsg = sprintf(NO_TASKS_RUNNING_WONT_COMPLETE, remainingTNames.join(', '));
|
|
208
|
+
handleError({}, new Error(errMsg));
|
|
209
|
+
}
|
|
205
210
|
}
|
|
206
211
|
|
|
207
212
|
function findReadyAndExec(vCon, tasks, tasksByName, handleError, contExec) {
|
package/lib/validate.js
CHANGED
|
@@ -11,14 +11,27 @@ var TASKS_ARR = 'ast.tasks must be an array of tasks';
|
|
|
11
11
|
var NAMES_UNIQUE = 'ast.tasks that specify name need to be unique, duplicate:';
|
|
12
12
|
var LOCALS_NOTNULL = 'ast.locals should not be null';
|
|
13
13
|
var DUP_OUTPUTS = 'multiple tasks output the same param, must be unique. param';
|
|
14
|
+
var MISSING_INPUTS = 'missing or mispelled variable referenced in flow definition: %s';
|
|
15
|
+
|
|
16
|
+
// match any of our literals true, false, int, float, quoted strings, or is property (has dot)
|
|
17
|
+
var LITERAL_OR_PROP_RE = /^(true|false|\-?[0-9\.]+)$|'|"|\./i;
|
|
14
18
|
|
|
15
19
|
var validateInParams, validateTasks, validateOutTask, validateTaskNamesUnique;
|
|
16
|
-
var validateLocals, validateOuputsUnique;
|
|
20
|
+
var validateLocals, validateOuputsUnique, validateNoMissingNames;
|
|
17
21
|
|
|
18
22
|
function format_error(errmsg, obj) {
|
|
19
23
|
return sprintf('%s - %s', errmsg, util.inspect(obj));
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
/**
|
|
27
|
+
true if is a literal name
|
|
28
|
+
*/
|
|
29
|
+
function isLiteralOrProp(name) { // need to match what is in vcon.js, TODO consolidate?
|
|
30
|
+
return LITERAL_OR_PROP_RE.test(name);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
22
35
|
/**
|
|
23
36
|
validate the AST return Errors
|
|
24
37
|
@example
|
|
@@ -37,6 +50,7 @@ function validate(ast) {
|
|
|
37
50
|
if (errors.length === 0) { // if no errors do additional validation
|
|
38
51
|
if (ast.outTask.type !== 'finalcbFirst') errors = errors.concat(validateOuputsUnique(ast.tasks));
|
|
39
52
|
errors = errors.concat(tutil.validateLocalFunctions(ast.inParams, ast.tasks, ast.locals));
|
|
53
|
+
errors = errors.concat(validateNoMissingNames(ast));
|
|
40
54
|
}
|
|
41
55
|
return errors;
|
|
42
56
|
}
|
|
@@ -99,4 +113,47 @@ function validateOuputsUnique(taskDefs) {
|
|
|
99
113
|
return errors;
|
|
100
114
|
}
|
|
101
115
|
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
validate there are no missing or mispelled param names in any task inputs
|
|
119
|
+
or the final task output
|
|
120
|
+
|
|
121
|
+
@return array of errors, or empty array if none
|
|
122
|
+
*/
|
|
123
|
+
function validateNoMissingNames(ast) {
|
|
124
|
+
var errors = [];
|
|
125
|
+
var names = {};
|
|
126
|
+
if (ast.locals) {
|
|
127
|
+
names = Object.keys(ast.locals).reduce(function (accum, k) { // start with locals
|
|
128
|
+
accum[k] = true;
|
|
129
|
+
return accum;
|
|
130
|
+
}, names);
|
|
131
|
+
}
|
|
132
|
+
ast.inParams.reduce(function (accum, p) { // add input params
|
|
133
|
+
accum[p] = true;
|
|
134
|
+
return accum;
|
|
135
|
+
}, names);
|
|
136
|
+
ast.tasks.reduce(function (accum, t) { // add task outputs
|
|
137
|
+
return t.out.reduce(function (innerAccum, p) {
|
|
138
|
+
innerAccum[p] = true;
|
|
139
|
+
return innerAccum;
|
|
140
|
+
}, accum);
|
|
141
|
+
}, names);
|
|
142
|
+
|
|
143
|
+
// now we have all possible provided vars, check task inputs are accounted for
|
|
144
|
+
ast.tasks.reduce(function (accum, t) { // for all tasks
|
|
145
|
+
return t.a.reduce(function (innerAccum, p) { // for all in params, except property
|
|
146
|
+
if (!isLiteralOrProp(p) && !names[p]) innerAccum.push(sprintf(MISSING_INPUTS, p)); // add error if missing
|
|
147
|
+
return innerAccum;
|
|
148
|
+
}, accum);
|
|
149
|
+
}, errors);
|
|
150
|
+
|
|
151
|
+
// now check the final task outputs
|
|
152
|
+
ast.outTask.a.reduce(function (accum, p) { // for final task out params
|
|
153
|
+
if (!isLiteralOrProp(p) && !names[p]) accum.push(sprintf(MISSING_INPUTS, p)); // add error if missing
|
|
154
|
+
return accum;
|
|
155
|
+
}, errors);
|
|
156
|
+
return errors; //TODO reenable
|
|
157
|
+
}
|
|
158
|
+
|
|
102
159
|
module.exports = validate;
|
package/lib/vcon.js
CHANGED
|
@@ -9,9 +9,11 @@ VContext.prototype.getLastResults = function () { return this.getVar(LAST_RESULT
|
|
|
9
9
|
VContext.prototype.setLastResults = function (args) { this.setVar(LAST_RESULTS_KEY, args); };
|
|
10
10
|
|
|
11
11
|
VContext.prototype.getVar = function (name) { //name might be simple or obj.prop, also literals
|
|
12
|
+
/*jshint regexp: false */
|
|
12
13
|
var vConValues = this.values;
|
|
13
14
|
if (typeof(name) !== 'string') return name; // literal boolean or number
|
|
14
15
|
name = name.trim();
|
|
16
|
+
// literal checks need to match what is in validate.js
|
|
15
17
|
if (name === 'true') return true;
|
|
16
18
|
if (name === 'false') return false;
|
|
17
19
|
if (/^-?[0-9]+$/.test(name)) return parseInt(name, 10); //int
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react",
|
|
3
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.2.
|
|
4
|
+
"version": "0.2.6",
|
|
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/test/chain.test.js
CHANGED
|
@@ -63,10 +63,11 @@ test('in triple first param -> inParams["foo", "bar", "baz"]', function (t) {
|
|
|
63
63
|
|
|
64
64
|
test('single task, single out params', function (t) {
|
|
65
65
|
var fn = chainDefine()
|
|
66
|
+
.in('a', 'b')
|
|
66
67
|
.out('c')
|
|
67
68
|
.async(falpha).in('a', 'b').out('c')
|
|
68
69
|
.end();
|
|
69
|
-
t.deepEqual(fn.ast.inParams, []);
|
|
70
|
+
t.deepEqual(fn.ast.inParams, ['a', 'b']);
|
|
70
71
|
t.deepEqual(fn.ast.tasks, [
|
|
71
72
|
{ f: falpha, type: 'cb', a: ['a', 'b'], out: ['c'], name: 'falpha' }
|
|
72
73
|
]);
|
|
@@ -74,14 +75,27 @@ test('single task, single out params', function (t) {
|
|
|
74
75
|
t.end();
|
|
75
76
|
});
|
|
76
77
|
|
|
78
|
+
test('single task, err params', function (t) {
|
|
79
|
+
var fn = chainDefine()
|
|
80
|
+
.out('err')
|
|
81
|
+
.async(falpha).in().out('err', 'c')
|
|
82
|
+
.end();
|
|
83
|
+
t.deepEqual(fn.ast.inParams, []);
|
|
84
|
+
t.deepEqual(fn.ast.tasks, [
|
|
85
|
+
{ f: falpha, type: 'cb', a: [], out: ['c'], name: 'falpha' }
|
|
86
|
+
]);
|
|
87
|
+
t.deepEqual(fn.ast.outTask, { a: [], type: 'finalcb' });
|
|
88
|
+
t.end();
|
|
89
|
+
});
|
|
90
|
+
|
|
77
91
|
test('single task, err and out params', function (t) {
|
|
78
92
|
var fn = chainDefine()
|
|
79
93
|
.out('err', 'c')
|
|
80
|
-
.async(falpha).in(
|
|
94
|
+
.async(falpha).in().out('err', 'c')
|
|
81
95
|
.end();
|
|
82
96
|
t.deepEqual(fn.ast.inParams, []);
|
|
83
97
|
t.deepEqual(fn.ast.tasks, [
|
|
84
|
-
{ f: falpha, type: 'cb', a: [
|
|
98
|
+
{ f: falpha, type: 'cb', a: [], out: ['c'], name: 'falpha' }
|
|
85
99
|
]);
|
|
86
100
|
t.deepEqual(fn.ast.outTask, { a: ['c'], type: 'finalcb' });
|
|
87
101
|
t.end();
|
|
@@ -90,11 +104,11 @@ test('single task, err and out params', function (t) {
|
|
|
90
104
|
test('single task, ERR and out params', function (t) {
|
|
91
105
|
var fn = chainDefine()
|
|
92
106
|
.out('ERR', 'c')
|
|
93
|
-
.async(falpha).in(
|
|
107
|
+
.async(falpha).in().out('ERR', 'c')
|
|
94
108
|
.end();
|
|
95
109
|
t.deepEqual(fn.ast.inParams, []);
|
|
96
110
|
t.deepEqual(fn.ast.tasks, [
|
|
97
|
-
{ f: falpha, type: 'cb', a: [
|
|
111
|
+
{ f: falpha, type: 'cb', a: [], out: ['c'], name: 'falpha' }
|
|
98
112
|
]);
|
|
99
113
|
t.deepEqual(fn.ast.outTask, { a: ['c'], type: 'finalcb' });
|
|
100
114
|
t.end();
|
package/test/core.test.js
CHANGED
|
@@ -198,14 +198,15 @@ test('error when cant complete', function (t) {
|
|
|
198
198
|
inParams: ['a', 'b', 'c'],
|
|
199
199
|
tasks: [
|
|
200
200
|
{ f: multiply, a: ['a', 'b'], out: ['c.mult'] },
|
|
201
|
-
{ f: fnRetsSum, a: ['c.bad', 'b'], out: ['c.sum'], type: 'ret' }
|
|
201
|
+
{ f: fnRetsSum, a: ['c.bad', 'b'], out: ['c.sum'], type: 'ret' },
|
|
202
|
+
{ f: add, a: ['c.sum', 'a'], out: ['d']}
|
|
202
203
|
],
|
|
203
|
-
outTask: { a: ['c.mult', 'c.sum', '
|
|
204
|
+
outTask: { a: ['c.mult', 'c.sum', 'd'] }
|
|
204
205
|
});
|
|
205
206
|
t.deepEqual(errors, [], 'no validation errors');
|
|
206
207
|
|
|
207
|
-
fn(2, 3, { foo: 1 }, function (err, cmult, csum,
|
|
208
|
-
t.equal(err.message, 'no tasks running, flow will not complete');
|
|
208
|
+
fn(2, 3, { foo: 1 }, function (err, cmult, csum, d) {
|
|
209
|
+
t.equal(err.message, 'no tasks running, flow will not complete, remaining tasks: fnRetsSum, add');
|
|
209
210
|
t.end();
|
|
210
211
|
});
|
|
211
212
|
});
|
package/test/dsl.test.js
CHANGED
|
@@ -55,11 +55,11 @@ test('triple first string -> inParams["foo", "bar", "baz"], empty tasks, outTask
|
|
|
55
55
|
|
|
56
56
|
test('single task, single out params', function (t) {
|
|
57
57
|
var r = react('myName', 'cb -> err, c',
|
|
58
|
-
falpha, '
|
|
58
|
+
falpha, 'cb -> err, c'
|
|
59
59
|
);
|
|
60
60
|
t.deepEqual(r.ast.inParams, []);
|
|
61
61
|
t.deepEqual(r.ast.tasks, [
|
|
62
|
-
{ f: falpha, a: [
|
|
62
|
+
{ f: falpha, a: [], out: ['c'], type: 'cb', name: 'falpha'}
|
|
63
63
|
]);
|
|
64
64
|
t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
|
|
65
65
|
t.end();
|
|
@@ -67,11 +67,11 @@ test('single task, single out params', function (t) {
|
|
|
67
67
|
|
|
68
68
|
test('single task, err and out params', function (t) {
|
|
69
69
|
var r = react('myName', 'cb -> err, c',
|
|
70
|
-
falpha, '
|
|
70
|
+
falpha, 'cb -> err, c'
|
|
71
71
|
);
|
|
72
72
|
t.deepEqual(r.ast.inParams, []);
|
|
73
73
|
t.deepEqual(r.ast.tasks, [
|
|
74
|
-
{ f: falpha, a: [
|
|
74
|
+
{ f: falpha, a: [], out: ['c'], type: 'cb', name: 'falpha'}
|
|
75
75
|
]);
|
|
76
76
|
t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
|
|
77
77
|
t.end();
|
|
@@ -79,11 +79,11 @@ test('single task, err and out params', function (t) {
|
|
|
79
79
|
|
|
80
80
|
test('single task, ERR and out params', function (t) {
|
|
81
81
|
var r = react('myName', 'cb -> ERR, c',
|
|
82
|
-
falpha, '
|
|
82
|
+
falpha, 'cb -> ERR, c'
|
|
83
83
|
);
|
|
84
84
|
t.deepEqual(r.ast.inParams, []);
|
|
85
85
|
t.deepEqual(r.ast.tasks, [
|
|
86
|
-
{ f: falpha, a: [
|
|
86
|
+
{ f: falpha, a: [], out: ['c'], type: 'cb', name: 'falpha'}
|
|
87
87
|
]);
|
|
88
88
|
t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
|
|
89
89
|
t.end();
|
|
@@ -191,6 +191,19 @@ test('object prop task params', function (t) {
|
|
|
191
191
|
t.end();
|
|
192
192
|
});
|
|
193
193
|
|
|
194
|
+
// Errors
|
|
195
|
+
|
|
196
|
+
test('missing name, throws error', function (t) {
|
|
197
|
+
var fn = function () {
|
|
198
|
+
var r = react('cb -> err, c',
|
|
199
|
+
falpha, 'cb -> err, c'
|
|
200
|
+
);
|
|
201
|
+
};
|
|
202
|
+
t.throws(fn, new Error('param[0] should be the flow name, instead found in/out def: cb -> err, c'));
|
|
203
|
+
t.end();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
|
|
194
207
|
test('extra arg throws error', function (t) {
|
|
195
208
|
var fn = function () {
|
|
196
209
|
var r = react('myName', 'a, b, cb -> err, c, d',
|
package/test/fstr.test.js
CHANGED
|
@@ -48,10 +48,10 @@ test('triple first string -> inParams["foo", "bar", "baz"], empty tasks, outTask
|
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
test('single task, single out params', function (t) {
|
|
51
|
-
var r = fstrDefine('', [
|
|
51
|
+
var r = fstrDefine('a, b', [
|
|
52
52
|
falpha, 'a, b -> err, c'
|
|
53
53
|
], 'c');
|
|
54
|
-
t.deepEqual(r.ast.inParams, []);
|
|
54
|
+
t.deepEqual(r.ast.inParams, ['a', 'b']);
|
|
55
55
|
t.deepEqual(r.ast.tasks, [
|
|
56
56
|
{ f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
|
|
57
57
|
]);
|
|
@@ -59,11 +59,23 @@ test('single task, single out params', function (t) {
|
|
|
59
59
|
t.end();
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
+
test('single task, err params', function (t) {
|
|
63
|
+
var r = fstrDefine('a, b', [
|
|
64
|
+
falpha, 'a, b -> err, c'
|
|
65
|
+
], 'err');
|
|
66
|
+
t.deepEqual(r.ast.inParams, ['a', 'b']);
|
|
67
|
+
t.deepEqual(r.ast.tasks, [
|
|
68
|
+
{ f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
|
|
69
|
+
]);
|
|
70
|
+
t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
|
|
71
|
+
t.end();
|
|
72
|
+
});
|
|
73
|
+
|
|
62
74
|
test('single task, err and out params', function (t) {
|
|
63
|
-
var r = fstrDefine('', [
|
|
75
|
+
var r = fstrDefine('a, b', [
|
|
64
76
|
falpha, 'a, b -> err, c'
|
|
65
77
|
], 'err, c');
|
|
66
|
-
t.deepEqual(r.ast.inParams, []);
|
|
78
|
+
t.deepEqual(r.ast.inParams, ['a', 'b']);
|
|
67
79
|
t.deepEqual(r.ast.tasks, [
|
|
68
80
|
{ f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
|
|
69
81
|
]);
|
|
@@ -72,10 +84,10 @@ test('single task, err and out params', function (t) {
|
|
|
72
84
|
});
|
|
73
85
|
|
|
74
86
|
test('single task, ERR and out params', function (t) {
|
|
75
|
-
var r = fstrDefine('', [
|
|
87
|
+
var r = fstrDefine('a, b', [
|
|
76
88
|
falpha, 'a, b -> ERR, c'
|
|
77
89
|
], 'ERR, c');
|
|
78
|
-
t.deepEqual(r.ast.inParams, []);
|
|
90
|
+
t.deepEqual(r.ast.inParams, ['a', 'b']);
|
|
79
91
|
t.deepEqual(r.ast.tasks, [
|
|
80
92
|
{ f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
|
|
81
93
|
]);
|
package/test/pcode.test.js
CHANGED
|
@@ -50,11 +50,11 @@ test('triple first string -> inParams["foo", "bar", "baz"], empty tasks, outTask
|
|
|
50
50
|
|
|
51
51
|
test('single task, single out params', function (t) {
|
|
52
52
|
var locals = { falpha: falpha };
|
|
53
|
-
var r = pcode('', [
|
|
53
|
+
var r = pcode('a, b', [
|
|
54
54
|
'c := falpha(a, b)',
|
|
55
55
|
'cb(err, c)'
|
|
56
56
|
], locals);
|
|
57
|
-
t.deepEqual(r.ast.inParams, []);
|
|
57
|
+
t.deepEqual(r.ast.inParams, ['a', 'b']);
|
|
58
58
|
t.deepEqual(r.ast.tasks, [
|
|
59
59
|
{ f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
|
|
60
60
|
]);
|
|
@@ -62,13 +62,27 @@ test('single task, single out params', function (t) {
|
|
|
62
62
|
t.end();
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
+
test('single task, single out params, cb(err)', function (t) {
|
|
66
|
+
var locals = { falpha: falpha };
|
|
67
|
+
var r = pcode('a, b', [
|
|
68
|
+
'c := falpha(a, b)',
|
|
69
|
+
'cb(err)'
|
|
70
|
+
], locals);
|
|
71
|
+
t.deepEqual(r.ast.inParams, ['a', 'b']);
|
|
72
|
+
t.deepEqual(r.ast.tasks, [
|
|
73
|
+
{ f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
|
|
74
|
+
]);
|
|
75
|
+
t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
|
|
76
|
+
t.end();
|
|
77
|
+
});
|
|
78
|
+
|
|
65
79
|
test('single task, err and out params', function (t) {
|
|
66
80
|
var locals = { falpha: falpha };
|
|
67
|
-
var r = pcode('', [
|
|
81
|
+
var r = pcode('a, b', [
|
|
68
82
|
'c := falpha(a, b)',
|
|
69
83
|
'cb(err, c)'
|
|
70
84
|
], locals);
|
|
71
|
-
t.deepEqual(r.ast.inParams, []);
|
|
85
|
+
t.deepEqual(r.ast.inParams, ['a', 'b']);
|
|
72
86
|
t.deepEqual(r.ast.tasks, [
|
|
73
87
|
{ f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
|
|
74
88
|
]);
|
package/test/validate.test.js
CHANGED
|
@@ -210,9 +210,84 @@ test('multiple tasks output the same param, must be unique', function (t) {
|
|
|
210
210
|
{ f: foo, a: [], out: ['baz', 'c'] },
|
|
211
211
|
{ f: bar, a: [], out: ['c'] }
|
|
212
212
|
],
|
|
213
|
-
outTask: { a: ['
|
|
213
|
+
outTask: { a: ['baz'] }
|
|
214
214
|
};
|
|
215
215
|
var msg = 'multiple tasks output the same param, must be unique. param: c';
|
|
216
216
|
t.deepEqual(validate(ast), [msg]);
|
|
217
217
|
t.end();
|
|
218
|
-
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
test('missing or mispelled input variable', function (t) {
|
|
221
|
+
var ast = {
|
|
222
|
+
inParams: [],
|
|
223
|
+
tasks: [
|
|
224
|
+
{ f: foo, a: [], out: [] },
|
|
225
|
+
{ f: bar, a: ['abc'], out: [] }
|
|
226
|
+
],
|
|
227
|
+
outTask: { a: [] }
|
|
228
|
+
};
|
|
229
|
+
var msg = 'missing or mispelled variable referenced in flow definition: abc';
|
|
230
|
+
t.deepEqual(validate(ast), [msg]);
|
|
231
|
+
t.end();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test('missing or mispelled input variables', function (t) {
|
|
235
|
+
var ast = {
|
|
236
|
+
inParams: ['aaa', 'bbb'],
|
|
237
|
+
tasks: [
|
|
238
|
+
{ f: foo, a: ['aaa', 'cat'], out: ['ccc'] },
|
|
239
|
+
{ f: bar, a: ['abc', 'bbb', 'ccc'], out: [] }
|
|
240
|
+
],
|
|
241
|
+
outTask: { a: [] }
|
|
242
|
+
};
|
|
243
|
+
var messages = [
|
|
244
|
+
'missing or mispelled variable referenced in flow definition: cat',
|
|
245
|
+
'missing or mispelled variable referenced in flow definition: abc'
|
|
246
|
+
];
|
|
247
|
+
t.deepEqual(validate(ast), messages);
|
|
248
|
+
t.end();
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
test('missing or mispelled final output variables', function (t) {
|
|
252
|
+
var ast = {
|
|
253
|
+
inParams: ['aaa'],
|
|
254
|
+
tasks: [
|
|
255
|
+
{ f: foo, a: ['aaa'], out: ['bbb'] },
|
|
256
|
+
{ f: bar, a: ['bbb'], out: ['ccc'] }
|
|
257
|
+
],
|
|
258
|
+
outTask: { a: ['ccc', 'ddd', 'eee'] }
|
|
259
|
+
};
|
|
260
|
+
var messages = [
|
|
261
|
+
'missing or mispelled variable referenced in flow definition: ddd',
|
|
262
|
+
'missing or mispelled variable referenced in flow definition: eee'
|
|
263
|
+
];
|
|
264
|
+
t.deepEqual(validate(ast), messages);
|
|
265
|
+
t.end();
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test('missing or mispelled validation ignores properties', function (t) {
|
|
269
|
+
var ast = {
|
|
270
|
+
inParams: ['obj'],
|
|
271
|
+
tasks: [
|
|
272
|
+
{ f: foo, a: ['obj.foo'], out: [] },
|
|
273
|
+
{ f: bar, a: ['obj.bar'], out: [] }
|
|
274
|
+
],
|
|
275
|
+
outTask: { a: ['obj.cat'] }
|
|
276
|
+
};
|
|
277
|
+
t.deepEqual(validate(ast), []);
|
|
278
|
+
t.end();
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
test('missing or mispelled validation ignores literals', function (t) {
|
|
282
|
+
var ast = {
|
|
283
|
+
inParams: [],
|
|
284
|
+
tasks: [
|
|
285
|
+
{ f: foo, a: ['true', 'false', '123', '123.1'], out: [] },
|
|
286
|
+
{ f: bar, a: ['-123', '-123.4', '"wow"', "'hey'"], out: [] }
|
|
287
|
+
],
|
|
288
|
+
outTask: { a: [] }
|
|
289
|
+
};
|
|
290
|
+
t.deepEqual(validate(ast), []);
|
|
291
|
+
t.end();
|
|
292
|
+
});
|
|
293
|
+
|