react 0.5.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/README.md +5 -5
- package/doc/advanced.md +5 -0
- package/examples/{default1.js → longer-example.js} +0 -0
- package/examples/{default-simple.js → simple.js} +0 -0
- package/examples/{ast1.js → using-ast-directly.js} +4 -0
- package/examples/{default-events1.js → using-events1.js} +0 -0
- package/examples/{default-log-events.js → using-log-events.js} +0 -0
- package/lib/core.js +13 -1
- package/lib/event-collector.js +3 -0
- package/lib/event-manager.js +1 -0
- package/lib/id.js +1 -0
- package/lib/log-events.js +3 -3
- package/lib/task.js +8 -3
- package/lib/vcon.js +1 -1
- package/package.json +1 -1
- package/test/ast.test.js +27 -1
- package/test/core.test.js +26 -1
- package/test/dsl.test.js +2 -2
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ It takes inspiration from several projects including:
|
|
|
35
35
|
- object instance method calls
|
|
36
36
|
- class method calls
|
|
37
37
|
- selectFirst flow where the first task that returns defined, non-null value is used
|
|
38
|
-
- promise style functions - also automatic resolution of promise inputs (
|
|
38
|
+
- promise style functions - also automatic resolution of promise inputs (optionally loaded with `react.resolvePromises();`)
|
|
39
39
|
- use of resulting flow function as callback style or promise style (if no callback provided) (provided via plugin corresponding to the promise library used) See https://github.com/jeffbski/react-deferred
|
|
40
40
|
- (planned) iteration on arrays, streams, sockets
|
|
41
41
|
- (planned) event emitter integration
|
|
@@ -182,7 +182,7 @@ See the [Advanced React](https://github.com/jeffbski/react/blob/master/doc/advan
|
|
|
182
182
|
|
|
183
183
|
## Status
|
|
184
184
|
|
|
185
|
-
- 2012-01-18 - Remove old DSL interfaces, improve plugin loading (v0.5.
|
|
185
|
+
- 2012-01-18 - Remove old DSL interfaces, improve plugin loading, log flow name with task name, ast.defined event, test with node 0.7.0 (v0.5.1)
|
|
186
186
|
- 2012-01-17 - Additional documentation (v0.3.5)
|
|
187
187
|
- 2012-01-16 - Refine events and create logging plugin (v0.3.3)
|
|
188
188
|
- 2012-01-13 - Add promise tasks, promise resolution, refactor alternate DSL interfaces as optional requires (v0.3.0)
|
|
@@ -194,12 +194,12 @@ See the [Advanced React](https://github.com/jeffbski/react/blob/master/doc/advan
|
|
|
194
194
|
## Test Results
|
|
195
195
|
|
|
196
196
|
```bash
|
|
197
|
-
ok ast.test.js ....................
|
|
197
|
+
ok ast.test.js .................... 15/15
|
|
198
198
|
ok cb-task.test.js ................ 31/31
|
|
199
199
|
ok core-deferred.test.js .......... 11/11
|
|
200
200
|
ok core-promised.test.js .......... 11/11
|
|
201
201
|
ok core-when.test.js ................ 6/6
|
|
202
|
-
ok core.test.js .................
|
|
202
|
+
ok core.test.js ................. 108/108
|
|
203
203
|
ok dsl.test.js .................... 70/70
|
|
204
204
|
ok event-manager.test.js .......... 13/13
|
|
205
205
|
ok exec-options.test.js ............. 3/3
|
|
@@ -213,7 +213,7 @@ ok validate-cb-task.test.js ......... 6/6
|
|
|
213
213
|
ok validate-ret-task.test.js ........ 7/7
|
|
214
214
|
ok validate.test.js ............... 31/31
|
|
215
215
|
ok vcon.test.js ................... 55/55
|
|
216
|
-
total ...........................
|
|
216
|
+
total ........................... 466/466
|
|
217
217
|
|
|
218
218
|
ok
|
|
219
219
|
```
|
package/doc/advanced.md
CHANGED
|
@@ -133,6 +133,7 @@ react.trackTasks(); // turn on flow and task tracking events
|
|
|
133
133
|
|
|
134
134
|
Available Events that can be consumed
|
|
135
135
|
|
|
136
|
+
- ast.defined - ast was defined (receives the ast)
|
|
136
137
|
- flow.begin - flow execution has started (receives a flow env)
|
|
137
138
|
- flow.complete - flow execution has successfully completed (receives a flow env)
|
|
138
139
|
- flow.errored - flow execution has errored (receives a flow env)
|
|
@@ -159,3 +160,7 @@ collector.capture(flowFn, 'flow.*'); // add capture flow events on a flow
|
|
|
159
160
|
var events = collector.list(); // retrieve the list of events
|
|
160
161
|
collector.clear(); // clear the list of events;
|
|
161
162
|
```
|
|
163
|
+
|
|
164
|
+
### External Plugins
|
|
165
|
+
|
|
166
|
+
- https://github.com/jeffbski/react-deferred - integrates jQuery style Deferred/Promises with react, providing automatic promise resolution and optional usage for react functions where by calling without a callback returns a promise.
|
|
File without changes
|
|
File without changes
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
Advanced example using the AST directly which most users will not do.
|
|
5
|
+
For general use, see other examples like simple.js
|
|
6
|
+
*/
|
|
3
7
|
var react = require('../'); // require('react');
|
|
4
8
|
|
|
5
9
|
function load(res, cb) { setTimeout(cb, 100, null, res + '-loaded'); }
|
|
File without changes
|
|
File without changes
|
package/lib/core.js
CHANGED
|
@@ -10,6 +10,7 @@ var VContext = require('./vcon.js');
|
|
|
10
10
|
var EventManager = require('./event-manager.js');
|
|
11
11
|
var inputParser = require('./input-parser.js');
|
|
12
12
|
var idGenerator = require('./id.js');
|
|
13
|
+
var sprintf = require('sprintf').sprintf;
|
|
13
14
|
|
|
14
15
|
var reactOptions = {
|
|
15
16
|
stackTraceLimitMin: 30
|
|
@@ -27,6 +28,13 @@ function mergeOptions(parsedOptions) {
|
|
|
27
28
|
}, parsedOptions);
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
/**
|
|
32
|
+
generate a flow name when one is not provided
|
|
33
|
+
*/
|
|
34
|
+
function generateFlowName() {
|
|
35
|
+
return sprintf('flow_%s', idGenerator.createUniqueId());
|
|
36
|
+
}
|
|
37
|
+
|
|
30
38
|
/**
|
|
31
39
|
Creates react function which the AST can be manipulated and then
|
|
32
40
|
is ready to be executed. Can be used directly or a DSL can wrap this
|
|
@@ -64,13 +72,17 @@ function reactFactory() {
|
|
|
64
72
|
function setAndValidateAST(newAST) { //set AST then validate, ret error[]
|
|
65
73
|
Object.keys(newAST).forEach(function (k) { ast[k] = newAST[k]; }); // copy all properties
|
|
66
74
|
var errors = validate(ast);
|
|
67
|
-
if (!errors.length)
|
|
75
|
+
if (!errors.length) {
|
|
76
|
+
if (!ast.name) ast.name = generateFlowName();
|
|
77
|
+
tskutil.nameTasks(ast.tasks); //run this so names can be checked in ast
|
|
78
|
+
}
|
|
68
79
|
if (Object.freeze) { //lets freeze the AST so plugin writers don't accidentally manip the ast
|
|
69
80
|
Object.keys(newAST).forEach(function (k) {
|
|
70
81
|
if (typeof(newAST[k]) === 'object') Object.freeze(newAST[k]);
|
|
71
82
|
});
|
|
72
83
|
Object.freeze(newAST);
|
|
73
84
|
}
|
|
85
|
+
flowEmitter.emit(EventManager.TYPES.AST_DEFINED, ast);
|
|
74
86
|
return errors;
|
|
75
87
|
}
|
|
76
88
|
|
package/lib/event-collector.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var react = require('../'); // require('react');
|
|
4
4
|
react.trackTasks(); // enable task tracking
|
|
5
5
|
|
|
6
|
+
var AST_EVENTS_RE = /^ast\./;
|
|
6
7
|
var TASK_EVENTS_RE = /^task\./;
|
|
7
8
|
var FLOW_EVENTS_RE = /^flow\./;
|
|
8
9
|
|
|
@@ -48,6 +49,8 @@ EventCollector.prototype.capture = function (flowFn, eventId) {
|
|
|
48
49
|
eventObject.env = obj;
|
|
49
50
|
} else if (TASK_EVENTS_RE.test(this.event)) {
|
|
50
51
|
eventObject.task = obj;
|
|
52
|
+
} else if (AST_EVENTS_RE.test(this.event)) {
|
|
53
|
+
eventObject.ast = obj;
|
|
51
54
|
}
|
|
52
55
|
self.events.push(eventObject);
|
|
53
56
|
}
|
package/lib/event-manager.js
CHANGED
package/lib/id.js
CHANGED
package/lib/log-events.js
CHANGED
|
@@ -45,12 +45,12 @@ function taskLog(obj) {
|
|
|
45
45
|
var eventTimeStr = time.toISOString();
|
|
46
46
|
if (this.event === 'task.complete') {
|
|
47
47
|
var task = obj;
|
|
48
|
-
console.error('%s: %s \tmsecs: %s \n\targs: %s \n\tresults: %s\n',
|
|
49
|
-
this.event, task.name, task.elapsedTime, util.inspect(argsNoCb), util.inspect(task.results));
|
|
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
50
|
} else {
|
|
51
51
|
var name = obj.name;
|
|
52
52
|
var args = obj.args;
|
|
53
|
-
console.error('%s: %s \n\targs: %s\n', this.event, name, util.inspect(argsNoCb));
|
|
53
|
+
console.error('%s: %s:%s \n\targs: %s\n', this.event, obj.env.name, obj.name, util.inspect(argsNoCb));
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
}
|
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
|
}
|
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
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.
|
|
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/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
|
@@ -10,6 +10,7 @@ function add(x, y, cb) { cb(null, x + y); }
|
|
|
10
10
|
function badFunc(a, b, cb) { throw new Error('badFuncThrow'); }
|
|
11
11
|
function badF2(a, b, cb) { cb('my-error'); }
|
|
12
12
|
function fnRetsSum(a, b) { return a + b; }
|
|
13
|
+
var anonFn = function (a, b) { return a + b; };
|
|
13
14
|
|
|
14
15
|
test('set and validate AST', function (t) {
|
|
15
16
|
var fn = react();
|
|
@@ -42,16 +43,19 @@ test('unnamed tasks will be assigned unique names', function (t) {
|
|
|
42
43
|
{ f: multiply, a: ['a', 'b'], out: ['c'] },
|
|
43
44
|
{ f: multiply, a: ['a', 'b'], out: ['d'], name: 'multiply' },
|
|
44
45
|
{ f: multiply, a: ['a', 'b'], out: ['e'], name: 'times' },
|
|
46
|
+
{ f: anonFn, a: ['a', 'b'], out: ['g'], type: 'ret' },
|
|
45
47
|
{ f: multiply, a: ['a', 'b'], out: ['f'] }
|
|
46
48
|
],
|
|
47
49
|
outTask: { a: ['c'] }
|
|
48
50
|
});
|
|
49
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_');
|
|
50
53
|
t.deepEqual(fn.ast.tasks, [
|
|
51
54
|
{ f: multiply, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'multiply_0' },
|
|
52
55
|
{ f: multiply, a: ['a', 'b'], out: ['d'], name: 'multiply', type: 'cb' },
|
|
53
56
|
{ f: multiply, a: ['a', 'b'], out: ['e'], name: 'times', type: 'cb' },
|
|
54
|
-
{ 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' }
|
|
55
59
|
]);
|
|
56
60
|
t.end();
|
|
57
61
|
});
|
|
@@ -431,6 +435,27 @@ test('using "this" in a sync function', function (t) {
|
|
|
431
435
|
}]);
|
|
432
436
|
});
|
|
433
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
|
+
|
|
434
459
|
|
|
435
460
|
// Select first tests
|
|
436
461
|
|
package/test/dsl.test.js
CHANGED
|
@@ -16,7 +16,7 @@ test('module exports is a fn with properties', function (t) {
|
|
|
16
16
|
|
|
17
17
|
test('no arguments -> empty name, inParams, tasks, outTask', function (t) {
|
|
18
18
|
var r = react();
|
|
19
|
-
t.equal(r.ast.name,
|
|
19
|
+
t.equal(r.ast.name.slice(0, 'flow_'.length), 'flow_', 'generated flow name should start with flow_');
|
|
20
20
|
t.deepEqual(r.ast.inParams, []);
|
|
21
21
|
t.deepEqual(r.ast.tasks, []);
|
|
22
22
|
t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
|
|
@@ -26,7 +26,7 @@ test('no arguments -> empty name, inParams, tasks, outTask', function (t) {
|
|
|
26
26
|
|
|
27
27
|
test('empty first string -> empty name, inParams, tasks, outTask', function (t) {
|
|
28
28
|
var r = react('');
|
|
29
|
-
t.equal(r.ast.name, '');
|
|
29
|
+
t.equal(r.ast.name.slice(0, 'flow_'.length), 'flow_', 'generated flow name should start with flow_');
|
|
30
30
|
t.deepEqual(r.ast.inParams, []);
|
|
31
31
|
t.deepEqual(r.ast.tasks, []);
|
|
32
32
|
t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
|