react 0.2.6 → 0.5.0

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.
Files changed (73) hide show
  1. package/.npmignore +2 -1
  2. package/README.md +94 -149
  3. package/doc/advanced.md +161 -0
  4. package/doc/color-def.graffle +938 -0
  5. package/doc/color-def.png +0 -0
  6. package/doc/default-simple.dot +19 -0
  7. package/doc/default-simple.dot.png +0 -0
  8. package/examples/default-events1.js +33 -6
  9. package/examples/{fstr1.js → default-log-events.js} +20 -13
  10. package/examples/default-simple.js +45 -0
  11. package/lib/base-task.js +8 -6
  12. package/lib/cb-task.js +14 -1
  13. package/lib/core.js +43 -12
  14. package/lib/dsl.js +14 -6
  15. package/lib/event-collector.js +65 -0
  16. package/lib/event-manager.js +29 -16
  17. package/lib/finalcb-first-task.js +16 -10
  18. package/lib/finalcb-task.js +17 -10
  19. package/lib/input-parser.js +7 -3
  20. package/lib/log-events.js +86 -0
  21. package/lib/parse.js +6 -3
  22. package/lib/promise-resolve.js +35 -0
  23. package/lib/promise-task.js +89 -0
  24. package/lib/ret-task.js +1 -1
  25. package/lib/task.js +32 -23
  26. package/lib/track-tasks.js +60 -0
  27. package/lib/validate.js +3 -3
  28. package/lib/vcon.js +6 -3
  29. package/lib/when-task.js +81 -0
  30. package/package.json +5 -3
  31. package/react.js +33 -5
  32. package/test/core-deferred.test.js +134 -0
  33. package/test/core-promised.test.js +132 -0
  34. package/test/core-when.test.js +84 -0
  35. package/test/core.test.js +108 -60
  36. package/test/dsl.test.js +58 -6
  37. package/test/exec-options.test.js +2 -1
  38. package/test/finalcb-task.test.js +6 -5
  39. package/test/input-parser.test.js +10 -6
  40. package/test/module-use.test.js +16 -199
  41. package/test/promise-auto-resolve.test.js +52 -0
  42. package/test/validate.test.js +4 -2
  43. package/test/vcon.test.js +13 -0
  44. package/Jakefile.js +0 -8
  45. package/examples/chain-events1.js +0 -34
  46. package/examples/chain1.js +0 -19
  47. package/examples/fstr-events1.js +0 -51
  48. package/examples/pcode1.js +0 -22
  49. package/jake-tasks/jake-test.js +0 -64
  50. package/lib/chain.js +0 -148
  51. package/lib/fstr.js +0 -119
  52. package/lib/pcode.js +0 -173
  53. package/oldExamples/analyze.js +0 -29
  54. package/oldExamples/analyze2.js +0 -29
  55. package/oldExamples/example10-dsl.js +0 -63
  56. package/oldExamples/example11.js +0 -62
  57. package/oldExamples/example12.js +0 -63
  58. package/oldExamples/example13.js +0 -63
  59. package/oldExamples/example14.js +0 -63
  60. package/oldExamples/example15.js +0 -75
  61. package/oldExamples/example6-ast.js +0 -47
  62. package/oldExamples/example6-dsl.js +0 -49
  63. package/oldExamples/example8-ast.js +0 -55
  64. package/oldExamples/example8-dsl.js +0 -53
  65. package/oldExamples/example9-ast.js +0 -58
  66. package/oldExamples/example9-dsl.js +0 -57
  67. package/oldExamples/function-str-ex1.js +0 -33
  68. package/oldExamples/function-str-ex2.js +0 -67
  69. package/oldExamples/trait1.js +0 -41
  70. package/oldExamples/trait2.js +0 -44
  71. package/test/chain.test.js +0 -253
  72. package/test/fstr.test.js +0 -300
  73. package/test/pcode.test.js +0 -335
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ Test that arguments which are promises are automatically resolved
5
+ before calling react functions
6
+ */
7
+
8
+ var test = require('tap').test;
9
+ var Deferred = require('promised-io/promise').Deferred;
10
+
11
+ var react = require('../'); // require('react');
12
+ react.resolvePromises(); // enable promise resolving
13
+
14
+ function multiply(x, y, cb) { cb(null, x * y); }
15
+ function add(x, y, cb) { cb(null, x + y); }
16
+ // function badF2(a, b, cb) { cb('my-error'); }
17
+
18
+ test('auto resolve promises passed as args', function (t) {
19
+ t.plan(4);
20
+ var fn = react();
21
+ var errors = fn.setAndValidateAST({
22
+ inParams: ['a', 'b'],
23
+ tasks: [
24
+ { f: multiply, a: ['a', 'b'], out: ['c'] },
25
+ { f: add, a: ['c', 'b'], out: ['d'] }
26
+ ],
27
+ outTask: { a: ['c', 'd'] }
28
+ });
29
+ t.deepEqual(errors, [], 'no validation errors');
30
+
31
+ function retAP() {
32
+ var deferred = new Deferred();
33
+ setTimeout(function () { deferred.resolve(2); }, 10);
34
+ return deferred.promise;
35
+ }
36
+
37
+ function retBP() {
38
+ var deferred = new Deferred();
39
+ setTimeout(function () { deferred.resolve(3); }, 10);
40
+ return deferred.promise;
41
+ }
42
+
43
+ var ap = retAP();
44
+ var bp = retBP();
45
+
46
+ fn(ap, bp, function (err, c, d) {
47
+ t.equal(err, null);
48
+ t.equal(c, 6);
49
+ t.equal(d, 9);
50
+ t.end();
51
+ });
52
+ });
@@ -282,8 +282,10 @@ test('missing or mispelled validation ignores literals', function (t) {
282
282
  var ast = {
283
283
  inParams: [],
284
284
  tasks: [
285
- { f: foo, a: ['true', 'false', '123', '123.1'], out: [] },
286
- { f: bar, a: ['-123', '-123.4', '"wow"', "'hey'"], out: [] }
285
+ { f: foo, a: ['true', 'false', '123', '123.1', 'null'], out: [] },
286
+ { f: bar, a: ['-123', '-123.4', '"wow"', "'hey'"], out: [] },
287
+ { f: foo, a: ['"two-words"', "'also-two'", '"two.words"', "'also.two'"], out: [] },
288
+ { f: foo, a: ['this'], out: [] }
287
289
  ],
288
290
  outTask: { a: [] }
289
291
  };
package/test/vcon.test.js CHANGED
@@ -67,12 +67,25 @@ test('simple getVar returns existing value', function (t) {
67
67
  test('getVar on literals returns the literal', function (t) {
68
68
  t.equal(VContext.create([], []).getVar(true), true);
69
69
  t.equal(VContext.create([], []).getVar(false), false);
70
+ t.equal(VContext.create([], []).getVar(null), null);
71
+ t.equal(VContext.create([], []).getVar('true'), true);
72
+ t.equal(VContext.create([], []).getVar('false'), false);
73
+ t.equal(VContext.create([], []).getVar('null'), null);
70
74
  t.equal(VContext.create([], []).getVar(-100), -100);
71
75
  t.equal(VContext.create([], []).getVar(100), 100);
72
76
  t.equal(VContext.create([], []).getVar(123.4), 123.4);
73
77
  t.equal(VContext.create([], []).getVar(-987.6), -987.6);
78
+ t.equal(VContext.create([], []).getVar('-100'), -100);
79
+ t.equal(VContext.create([], []).getVar('100'), 100);
80
+ t.equal(VContext.create([], []).getVar('123.4'), 123.4);
81
+ t.equal(VContext.create([], []).getVar('-987.6'), -987.6);
74
82
  t.equal(VContext.create([], []).getVar('"foo"'), 'foo');
75
83
  t.equal(VContext.create([], []).getVar("'foo'"), 'foo');
84
+ t.equal(VContext.create([], []).getVar("'foo.bar'"), 'foo.bar');
85
+ t.equal(VContext.create([], []).getVar("'foo-bar'"), 'foo-bar');
86
+ t.equal(VContext.create([], []).getVar("'foo-bar.json'"), 'foo-bar.json');
87
+ t.equal(VContext.create([], []).getVar('"foo-bar.json"'), 'foo-bar.json');
88
+ t.deepEqual(VContext.create([], [], null, { a: 1}).getVar('this'), { a: 1});
76
89
  t.end();
77
90
  });
78
91
 
package/Jakefile.js DELETED
@@ -1,8 +0,0 @@
1
-
2
-
3
- require('./jake-tasks/jake-test.js');
4
-
5
- desc('Default - run watch');
6
- task('default', ['test:watch']);
7
-
8
-
@@ -1,34 +0,0 @@
1
- 'use strict';
2
-
3
- var react = require('../'); // require('react');
4
-
5
- //output events as tasks start and complete
6
- react.events.on('*', function (obj) {
7
- var time = new Date();
8
- time.setTime(obj.time);
9
- var eventTimeStr = time.toISOString();
10
- var argsNoCb = obj.args.filter(function (a) { return (typeof(a) !== 'function'); });
11
- if (obj.event === 'task.complete') {
12
- console.error('%s: %s \tmsecs:(%s) \n\targs:(%s) \n\tresults:(%s)\n',
13
- obj.event, obj.name, obj.elapsedTime, argsNoCb, obj.results);
14
- } else {
15
- console.error('%s: %s \n\targs:(%s)\n', obj.event, obj.name, argsNoCb);
16
- }
17
- });
18
-
19
-
20
- function multiply(a, b, cb) { cb(null, a * b); }
21
- function add(a, b) { return a + b; }
22
-
23
- var fn = react.chainDefine()
24
- .in('a', 'b', 'cb') // input params
25
- .out('err', 'm', 's') // final callback output params
26
- .async(multiply).in('a', 'b', 'cb').out('err', 'm') // task def - async fn, in params, callback out params
27
- .sync(add).in('m', 'a').out('s') // task def - sync fn, in params, return value
28
- .end();
29
-
30
- fn(2, 3, function (err, m, s) {
31
- console.error('err:', err); // null
32
- console.error('m:', m); // 2 * 3 = 6
33
- console.error('s:', s); // 6 + 2 = 8
34
- });
@@ -1,19 +0,0 @@
1
- 'use strict';
2
-
3
- var react = require('../'); // require('react');
4
-
5
- function multiply(a, b, cb) { cb(null, a * b); }
6
- function add(a, b) { return a + b; }
7
-
8
- var fn = react.chainDefine()
9
- .in('a', 'b', 'cb') // input params
10
- .out('err', 'm', 's') // final callback output params
11
- .async(multiply).in('a', 'b', 'cb').out('err', 'm') // task def - async fn, in params, callback out params
12
- .sync(add).in('m', 'a').out('s') // task def - sync fn, in params, return value
13
- .end();
14
-
15
- fn(2, 3, function (err, m, s) {
16
- console.error('err:', err); // null
17
- console.error('m:', m); // 2 * 3 = 6
18
- console.error('s:', s); // 6 + 2 = 8
19
- });
@@ -1,51 +0,0 @@
1
- 'use strict';
2
-
3
- var react = require('../'); // require('react');
4
-
5
- //output events as tasks start and complete
6
- react.events.on('*', function (obj) {
7
- var time = new Date();
8
- time.setTime(obj.time);
9
- var eventTimeStr = time.toISOString();
10
- var argsNoCb = obj.args.filter(function (a) { return (typeof(a) !== 'function'); });
11
- if (obj.event === 'task.complete') {
12
- console.error('%s: %s \tmsecs:(%s) \n\targs:(%s) \n\tresults:(%s)\n',
13
- obj.event, obj.name, obj.elapsedTime, argsNoCb, obj.results);
14
- } else {
15
- console.error('%s: %s \n\targs:(%s)\n', obj.event, obj.name, argsNoCb);
16
- }
17
- });
18
-
19
-
20
- function loadUser(uid, cb){ setTimeout(cb, 100, null, "User"+uid); }
21
- function loadFile(filename, cb){ setTimeout(cb, 100, null, 'Filedata'+filename); }
22
- function markdown(filedata) { return 'html'+filedata; }
23
- function prepareDirectory(outDirname, cb){ setTimeout(cb, 200, null, 'dircreated-'+outDirname); }
24
- function writeOutput(html, user, cb){ setTimeout(cb, 300, null, html+'_bytesWritten'); }
25
- function loadEmailTemplate(cb) { setTimeout(cb, 50, null, 'emailmd'); }
26
- function customizeEmail(user, emailHtml, cb) { return 'cust-'+user+emailHtml; }
27
- function deliverEmail(custEmailHtml, cb) { setTimeout(cb, 100, null, 'delivered-'+custEmailHtml); }
28
-
29
- function useHtml(err, html, user, bytesWritten) {
30
- if(err) {
31
- console.log('***Error: %s', err);
32
- return;
33
- }
34
- console.log('final result: %s, user: %s, written:%s', html, user, bytesWritten);
35
- }
36
-
37
- var loadAndSave = react.fstrDefine('filename, uid, outDirname, cb', [ // input params
38
- loadUser, 'uid -> err, user', // calling async fn loadUser with uid, callback is called with err and user
39
- loadFile, 'filename -> err, filedata',
40
- markdown, 'filedata -> returns html', // using a sync function
41
- prepareDirectory, 'outDirname -> err, dircreated',
42
- writeOutput, 'html, user -> err, bytesWritten', { after: prepareDirectory }, // only after prepareDirectory done
43
- loadEmailTemplate, ' -> err, emailmd',
44
- markdown, 'emailmd -> returns emailHtml', // using a sync function
45
- customizeEmail, 'user, emailHtml -> returns custEmailHtml',
46
- deliverEmail, 'custEmailHtml -> err, deliveredEmail', { after: writeOutput } // only after writeOutput is done
47
- ], 'err, html, user, bytesWritten'); // callback output params
48
-
49
- loadAndSave('file.md', 100, '/tmp/foo', useHtml); // executing the flow
50
-
51
-
@@ -1,22 +0,0 @@
1
- 'use strict';
2
-
3
- var react = require('../'); // require('react');
4
-
5
- function multiply(a, b, cb) { cb(null, a * b); }
6
- function add(a, b) { return a + b; }
7
- var locals = { // since pcodeDefine uses strings, need references to functions passed into react
8
- multiply: multiply,
9
- add: add
10
- };
11
-
12
- var fn = react.pcodeDefine('a, b, cb', [ // input params
13
- 'm := multiply(a, b)', // using a callback function, use :=
14
- 's = add(m, a)', // using a sync function, use =
15
- 'cb(err, m, s)' // output params for final callback
16
- ], locals); // hash of functions that will be used
17
-
18
- fn(2, 3, function (err, m, s) {
19
- console.error('err:', err); // null
20
- console.error('m:', m); // 2 * 3 = 6
21
- console.error('s:', s); // 6 + 2 = 8
22
- });
@@ -1,64 +0,0 @@
1
-
2
- var watch = require('watch');
3
- var cp = require('child_process');
4
-
5
- namespace('test', function () {
6
-
7
- var watchdir = '.';
8
- var cmd = 'tapper ./test';
9
-
10
- var alreadyExecuting = false;
11
-
12
- function execAndOutput(cmd){
13
- if(!alreadyExecuting){
14
- alreadyExecuting = true;
15
- console.log("Executing cmd:", cmd);
16
- cp.exec(cmd, function(err, stdout, stderr){
17
- if(err && err.message) console.log(err.message);
18
- console.log(stdout);
19
- console.error(stderr);
20
- alreadyExecuting = false;
21
- });
22
- }
23
- }
24
-
25
- function filterWatch(f){
26
- if(/flymake/.test(f)) return false; //ignore flymake files
27
- if(/^\.|\/\./.test(f)) return false; //ignore hidden files or dirs
28
- console.log(f);
29
- return true;
30
- }
31
-
32
- desc('watch and run tests');
33
- task('watch', ['test:run'], function () {
34
- // watch the watchdir and if anything changes, rerun the command
35
- watch.createMonitor(watchdir, { ignoreDotFiles: true }, function(monitor) {
36
- monitor.on("created", function(f, stat){ if(filterWatch(f)) execAndOutput(cmd); });
37
- monitor.on("changed", function(f, curr, prev){
38
- if(filterWatch(f) && curr.mtime > prev.mtime) {
39
- //console.log(prev.mtime);
40
- console.log(curr.mtime);
41
- execAndOutput(cmd);
42
- }
43
- });
44
- monitor.on("removed", function(f, stat){ if(filterWatch(f)) execAndOutput(cmd); });
45
- });
46
- });
47
-
48
-
49
- desc('run tests');
50
- task('run', [], function (cmdarg1, cmdarg2, cmdargN) {
51
- execAndOutput(cmd);
52
- });
53
-
54
- });
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
package/lib/chain.js DELETED
@@ -1,148 +0,0 @@
1
- 'use strict';
2
-
3
- var sprintf = require('sprintf').sprintf;
4
- var core = require('./core.js');
5
- var tutil = require('./task.js');
6
-
7
- // err for task type cb is implied and thus optional, but allow for clarity.
8
- var ERROR_NAMES_RE = /^err$/i; // first out param matching this is skipped as being the err object
9
-
10
- // callback is implied for task type cb is implied and thus optional, but allow for clarity.
11
- var CALLBACK_NAMES_RE = /^cb$|^callback$/i; // last in param matching this is skipped as being the cb
12
-
13
- var FlowBuilder;
14
-
15
- /**
16
- jQuery-like chain interface for defining flow
17
-
18
- @example
19
- // normal flow
20
- var react = require('react');
21
- var fn = react.chainDefine()
22
- .in('filename', 'uid', 'outDirname', 'cb')
23
- .out('err', 'html', 'user', 'bytesWritten')
24
- .async(loadUser) .in('uid') .out('err', 'user')
25
- .async(loadFile) .in('filename') .out('err', 'filedata')
26
- .sync(markdown) .in('filedata') .out('html')
27
- .async(prepareDirectory) .in('outDirname') .out('err', 'dircreated')
28
- .async(writeOutput) .in('html', 'user') .out('err', 'bytesWritten') .after('prepareDirectory')
29
- .async(loadEmailTemplate) .in() .out('err', 'emailmd')
30
- .sync(markdown) .in('emailmd') .out('emailHtml')
31
- .sync(customizeEmail) .in('user', 'emailHtml') .out('custEmailHtml')
32
- .async(deliverEmail) .in('custEmailHtml') .out('err', 'deliveredEmail') .after('writeOutput')
33
- .end();
34
-
35
- @example
36
- // selectFirst flow
37
- var fn = chainDefine()
38
- .selectFirst()
39
- .in('a', 'b', 'cb')
40
- .out('err', 'c')
41
- .async(falpha).in('a', 'b', 'cb').out('err', 'c')
42
- .sync(fbeta).in('a', 'b').out('c')
43
- .end();
44
- */
45
- function chainDefine() {
46
- return FlowBuilder.create();
47
- }
48
-
49
- function FlowBuilder() {
50
- this.main = {
51
- name: null,
52
- options: {}
53
- };
54
- this.tasks = [];
55
- this.focus = this.main;
56
- }
57
-
58
- FlowBuilder.create = function () { return new FlowBuilder(); };
59
-
60
- FlowBuilder.prototype.selectFirst = function () {
61
- this.main.outTaskType = 'finalcbFirst';
62
- return this;
63
- };
64
-
65
- FlowBuilder.prototype.name = function (name) {
66
- this.focus.name = name;
67
- return this;
68
- };
69
-
70
- FlowBuilder.prototype.in = function (param1, param2, paramN) {
71
- var args = Array.prototype.slice.call(arguments);
72
- if (args.length && this.focus.type !== 'ret') { // has args and cb or main
73
- if (args[args.length - 1].match(CALLBACK_NAMES_RE)) args.pop(); // pop off the cb name if specified
74
- }
75
- if (this.focus === this.main) this.focus.in = args;
76
- else this.focus.a = args; // for tasks
77
- return this;
78
- };
79
-
80
- FlowBuilder.prototype.out = function (param1, param2, paramN) {
81
- var args = Array.prototype.slice.call(arguments);
82
- if (args.length && this.focus.type !== 'ret') { // has args and cb or main
83
- if (args[0].match(ERROR_NAMES_RE)) args.shift(); // shift off err if specified
84
- }
85
- this.focus.out = args;
86
- return this;
87
- };
88
-
89
- FlowBuilder.prototype.options = function (options) {
90
- var self = this;
91
- if (this.focus === this.main) {
92
- Object.keys(options).forEach(function (k) { self.focus.options[k] = options[k]; });
93
- } else { // task so set options right on task
94
- Object.keys(options).forEach(function (k) { self.focus[k] = options[k]; });
95
- }
96
- return this;
97
- };
98
-
99
- FlowBuilder.prototype.async = function (funcOrStrMethod) {
100
- var task = { f: funcOrStrMethod, type: 'cb' };
101
- this.tasks.push(task);
102
- this.focus = task;
103
- return this;
104
- };
105
-
106
- FlowBuilder.prototype.sync = function (funcOrStrMethod) {
107
- var task = { f: funcOrStrMethod, type: 'ret' };
108
- this.tasks.push(task);
109
- this.focus = task;
110
- return this;
111
- };
112
-
113
- FlowBuilder.prototype.after = function (name1, name2, nameN) {
114
- this.focus.after = Array.prototype.slice.call(arguments);
115
- return this;
116
- };
117
-
118
- /**
119
- Complete the building of a flow and perform validation
120
- which throws error if flow is not valid.
121
- */
122
- FlowBuilder.prototype.end = function end() {
123
- var reactFn = core();
124
-
125
- if (this.main.outTaskType === 'finalcbFirst') {
126
- this.tasks = tutil.serializeTasks(this.tasks);
127
- }
128
-
129
- var ast = {
130
- inParams: this.main.in || [],
131
- tasks: this.tasks,
132
- outTask: {
133
- a: this.main.out || [],
134
- type: this.main.outTaskType || 'finalcb'
135
- }
136
- };
137
- if (this.main.name) ast.name = this.main.name;
138
- var self = this;
139
- Object.keys(this.main.options).forEach(function (k) { ast[k] = self.main.options[k]; });
140
- var errors = reactFn.setAndValidateAST(ast);
141
- if (errors.length) {
142
- var errorStr = errors.join('\n');
143
- throw new Error(errorStr);
144
- }
145
- return reactFn;
146
- };
147
-
148
- module.exports = chainDefine;