react 0.2.3 → 0.3.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 (61) hide show
  1. package/README.md +15 -13
  2. package/{lib → dsl}/chain.js +5 -3
  3. package/{lib → dsl}/fstr.js +17 -6
  4. package/{lib → dsl}/pcode.js +19 -8
  5. package/examples/chain-events1.js +3 -3
  6. package/examples/chain1.js +2 -2
  7. package/examples/default-events1.js +2 -2
  8. package/examples/fstr-events1.js +4 -3
  9. package/examples/fstr1.js +3 -2
  10. package/examples/pcode1.js +2 -2
  11. package/lib/base-task.js +1 -0
  12. package/lib/cb-task.js +14 -1
  13. package/lib/core.js +36 -12
  14. package/lib/dsl.js +16 -5
  15. package/lib/event-manager.js +16 -4
  16. package/lib/finalcb-first-task.js +9 -6
  17. package/lib/finalcb-task.js +9 -6
  18. package/lib/input-parser.js +7 -3
  19. package/lib/parse.js +6 -3
  20. package/lib/promise-task.js +89 -0
  21. package/lib/ret-task.js +1 -1
  22. package/lib/task.js +23 -19
  23. package/lib/validate.js +14 -5
  24. package/lib/vcon.js +8 -3
  25. package/lib/when-task.js +81 -0
  26. package/package.json +4 -2
  27. package/promise-resolve.js +35 -0
  28. package/react.js +0 -4
  29. package/test/core-deferred.test.js +134 -0
  30. package/test/core-promised.test.js +132 -0
  31. package/test/core-when.test.js +84 -0
  32. package/test/core.test.js +63 -4
  33. package/test/dsl.test.js +70 -5
  34. package/test/{chain.test.js → dsl/chain.test.js} +84 -1
  35. package/test/{fstr.test.js → dsl/fstr.test.js} +13 -1
  36. package/test/{pcode.test.js → dsl/pcode.test.js} +136 -1
  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 +2 -190
  41. package/test/promise-auto-resolve.test.js +51 -0
  42. package/test/validate.test.js +30 -1
  43. package/test/vcon.test.js +13 -0
  44. package/oldExamples/analyze.js +0 -29
  45. package/oldExamples/analyze2.js +0 -29
  46. package/oldExamples/example10-dsl.js +0 -63
  47. package/oldExamples/example11.js +0 -62
  48. package/oldExamples/example12.js +0 -63
  49. package/oldExamples/example13.js +0 -63
  50. package/oldExamples/example14.js +0 -63
  51. package/oldExamples/example15.js +0 -75
  52. package/oldExamples/example6-ast.js +0 -47
  53. package/oldExamples/example6-dsl.js +0 -49
  54. package/oldExamples/example8-ast.js +0 -55
  55. package/oldExamples/example8-dsl.js +0 -53
  56. package/oldExamples/example9-ast.js +0 -58
  57. package/oldExamples/example9-dsl.js +0 -57
  58. package/oldExamples/function-str-ex1.js +0 -33
  59. package/oldExamples/function-str-ex2.js +0 -67
  60. package/oldExamples/trait1.js +0 -41
  61. package/oldExamples/trait2.js +0 -44
package/lib/vcon.js CHANGED
@@ -9,11 +9,14 @@ 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;
19
+ if (name === 'null') return null;
17
20
  if (/^-?[0-9]+$/.test(name)) return parseInt(name, 10); //int
18
21
  if (/^-?[0-9.]+$/.test(name)) return parseFloat(name); //float
19
22
  var m = /^("|')([^\1]*)\1$/.exec(name); //check for quoted string " or '
@@ -30,13 +33,13 @@ VContext.prototype.getVar = function (name) { //name might be simple or obj.prop
30
33
  variable :LAST_RESULTS which keeps an array of the last values
31
34
  which can be used for chaining and testing last results, etc.
32
35
  */
33
- VContext.prototype.saveResults = function(paramArr, valuesArr) { // set values for params
36
+ VContext.prototype.saveResults = function (paramArr, valuesArr) { // set values for params
34
37
  var self = this;
35
38
  paramArr.forEach(function (k, idx) { //save values to v context
36
39
  self.setVar(k, (valuesArr[idx] !== undefined) ? valuesArr[idx] : null); //upgrade any undefined to null
37
40
  });
38
41
  this.setLastResults(valuesArr);
39
- }
42
+ };
40
43
 
41
44
  VContext.prototype.setVar = function (name, value) { //name might be simple or obj.prop
42
45
  if (!name) return; // if name is undefined or null, then discard
@@ -59,9 +62,11 @@ VContext.prototype.setVar = function (name, value) { //name might be simple or o
59
62
  Ignore extra arguments passed in. Locals can be
60
63
  passed into seed the VContext otherwise empty {}
61
64
  will be used
65
+ @param self used to pass 'this' context in
62
66
  */
63
- VContext.create = function (args, inParams, locals) {
67
+ VContext.create = function (args, inParams, locals, self) {
64
68
  var initValues = {};
69
+ if (self) initValues['this'] = self;
65
70
  if (locals) Object.keys(locals).forEach(function (k) { initValues[k] = locals[k]; }); // copy over keys
66
71
  var vContext = new VContext();
67
72
  vContext.values = args.reduce(function (vcon, x, idx) { // create vCon start with input args
@@ -0,0 +1,81 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ When task which checks if is a promise (has a then method)
5
+ and waits for it to resolve.
6
+
7
+ If argument does not have a then method, it resolves immediately
8
+ */
9
+
10
+ var util = require('util');
11
+ var sprintf = require('sprintf').sprintf;
12
+
13
+ var BaseTask = require('./base-task.js');
14
+
15
+ function format_error(errmsg, obj) {
16
+ return sprintf('%s - %s', errmsg, util.inspect(obj));
17
+ }
18
+
19
+ var REQ = 'whenTask requires a, out';
20
+ var A_REQ = 'whenTask requires a to be an array[1] of string param names';
21
+ var OUT_REQ = 'whenTask requires out to be an array[1] of string param names';
22
+
23
+ function WhenTask(taskDef) {
24
+ var self = this;
25
+ Object.keys(taskDef).forEach(function (k) { self[k] = taskDef[k]; });
26
+ }
27
+
28
+ WhenTask.prototype = new BaseTask();
29
+ WhenTask.prototype.constructor = WhenTask;
30
+
31
+ WhenTask.prototype.f = function when() { // just here to keep validations happy
32
+ }
33
+
34
+ WhenTask.validate = function (taskDef) {
35
+ var errors = [];
36
+ if (!taskDef.a || !taskDef.out) {
37
+ errors.push(format_error(REQ, taskDef));
38
+ } else {
39
+ if (! (Array.isArray(taskDef.a) && taskDef.a.length === 1 &&
40
+ taskDef.a.every(function (x) { return (typeof(x) === 'string'); }))) {
41
+ errors.push(format_error(A_REQ, taskDef));
42
+ }
43
+ if (! (Array.isArray(taskDef.out) && taskDef.out.length <= 1 &&
44
+ taskDef.out.every(function (x) { return (typeof(x) === 'string'); }))) {
45
+ errors.push(format_error(OUT_REQ, taskDef));
46
+ }
47
+ }
48
+ return errors;
49
+ };
50
+
51
+ WhenTask.prototype.prepare = function prepare(handleTaskError, vCon, contExec) {
52
+ var self = this;
53
+ this.nextFn = function (arg) {
54
+ var args = Array.prototype.slice.call(arguments);
55
+ vCon.saveResults(self.out, args);
56
+ self.complete(args);
57
+ contExec();
58
+ };
59
+ this.failFn = function (err) {
60
+ handleTaskError(self, err);
61
+ };
62
+ };
63
+
64
+ WhenTask.prototype.exec = function exec(vCon, handleError, contExec) {
65
+ try {
66
+ var args = this.a.map(function (k) { return vCon.getVar(k); }); //get args from vCon
67
+ //console.error('WhenTask.exec.args=', args);
68
+ //console.error('WhenTask.exec.vCon=', vCon);
69
+ this.start(args); //note the start time, args
70
+ var arg = args[0]; // one value allowed
71
+ if (arg && typeof(arg.then) === 'function') { // is a promise
72
+ arg.then(this.nextFn, this.failFn);
73
+ } else { // not a promise continue immediately
74
+ this.nextFn(arg);
75
+ }
76
+ } catch (err) { //catch and handle the task error, calling final cb
77
+ handleError(this, err);
78
+ }
79
+ };
80
+
81
+ module.exports = WhenTask;
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.3",
4
+ "version": "0.3.0",
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" },
@@ -15,7 +15,9 @@
15
15
  },
16
16
  "devDependencies": {
17
17
  "tap" : "~0.1.0",
18
- "tapr" : "~0.1.0"
18
+ "tapr" : "~0.1.0",
19
+ "promised-io" : "~0.3.0",
20
+ "Deferred" : "~0.1.1"
19
21
  },
20
22
  "scripts": {
21
23
  "test": "node_modules/.bin/tapr test"
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ Auto resolve promises passed in as arguments to the flow
5
+
6
+ - Detects promises by checking for .then()
7
+ - Create promise name for param (param__promise)
8
+ - moves existing vCon promise into the param__promise
9
+ - creates WhenTask which resolves param__promise into param
10
+ */
11
+
12
+
13
+ var react = require('./'); // require('react');
14
+
15
+ var PROMISE_SUFFIX = '__promise'; // added to param names that are promises
16
+
17
+ react.events.on(react.events.TYPES.EXEC_TASKS_PRECREATE, function (taskEnv) {
18
+ var vConValues = taskEnv.vCon.values;
19
+ var promiseParams = taskEnv.ast.inParams.filter(function (p) {
20
+ var value = vConValues[p];
21
+ return (value && typeof(value.then) === 'function');
22
+ });
23
+ promiseParams.forEach(function (p) {
24
+ var promiseName = p + PROMISE_SUFFIX;
25
+ vConValues[promiseName] = vConValues[p];
26
+ vConValues[p] = undefined;
27
+ taskEnv.taskDefs.push({
28
+ type: 'when',
29
+ a: [promiseName],
30
+ out: [p]
31
+ });
32
+ });
33
+ });
34
+
35
+ module.exports = react; // return react
package/react.js CHANGED
@@ -6,7 +6,3 @@ module.exports = require('./lib/dsl.js'); // core + default dsl
6
6
  module.exports.options = core.options; // global react options
7
7
  module.exports.events = core.events; // global react event emitter
8
8
 
9
- // additional interfaces
10
- module.exports.fstrDefine = require('./lib/fstr.js');
11
- module.exports.pcodeDefine = require('./lib/pcode.js');
12
- module.exports.chainDefine = require('./lib/chain.js');
@@ -0,0 +1,134 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ Test core PromiseTasks using Deferred - jquery style promises
5
+ */
6
+
7
+
8
+ var test = require('tap').test;
9
+ var Deferred = require('Deferred');
10
+ //var when = Deferred.when;
11
+
12
+
13
+ var react = require('../'); //require('react');
14
+
15
+ function multiply(x, y) {
16
+ var deferred = new Deferred();
17
+ setTimeout(function () {
18
+ deferred.resolve(x * y);
19
+ }, 10);
20
+ return deferred.promise();
21
+ }
22
+ function add(x, y) {
23
+ var deferred = new Deferred();
24
+ setTimeout(function () {
25
+ deferred.resolve(x + y);
26
+ }, 10);
27
+ return deferred.promise();
28
+ }
29
+
30
+ function badFunc(a, b) {
31
+ throw new Error('badFuncThrow');
32
+ }
33
+
34
+ function badF2(a, b) {
35
+ var deferred = new Deferred();
36
+ setTimeout(function () {
37
+ deferred.reject(new Error('my-error'));
38
+ }, 10);
39
+ return deferred.promise();
40
+ }
41
+
42
+
43
+ test('multi-step', function (t) {
44
+ t.plan(4);
45
+ var fn = react();
46
+ var errors = fn.setAndValidateAST({
47
+ inParams: ['a', 'b'],
48
+ tasks: [
49
+ { f: multiply, a: ['a', 'b'], out: ['c'], type: 'promise' },
50
+ { f: add, a: ['c', 'b'], out: ['d'], type: 'promise' }
51
+ ],
52
+ outTask: { a: ['c', 'd'] }
53
+ });
54
+ t.deepEqual(errors, [], 'no validation errors');
55
+
56
+ fn(2, 3, function (err, c, d) {
57
+ t.equal(err, null);
58
+ t.equal(c, 6);
59
+ t.equal(d, 9);
60
+ t.end();
61
+ });
62
+ });
63
+
64
+ test('using "this" in a cb function', function (t) {
65
+ t.plan(3);
66
+ function getA(cb) {
67
+ /*jshint validthis: true */
68
+ var deferred = new Deferred();
69
+ var self = this;
70
+ setTimeout(function () {
71
+ deferred.resolve(self.a);
72
+ }, 10);
73
+ return deferred.promise();
74
+ }
75
+
76
+ var fn = react();
77
+ var errors = fn.setAndValidateAST({
78
+ inParams: [],
79
+ tasks: [
80
+ { f: getA, a: [], out: ['a'], type: 'promise' }
81
+ ],
82
+ outTask: { a: ['a'] }
83
+ });
84
+ t.deepEqual(errors, [], 'no validation errors');
85
+
86
+ var obj = {
87
+ a: 100
88
+ };
89
+
90
+ fn.apply(obj, [function (err, a) {
91
+ t.equal(err, null);
92
+ t.equal(a, 100);
93
+ t.end();
94
+ }]);
95
+ });
96
+
97
+
98
+ test('throws error', function (t) {
99
+ t.plan(2);
100
+ var fn = react();
101
+ var errors = fn.setAndValidateAST({
102
+ inParams: ['a', 'b'],
103
+ tasks: [
104
+ { f: badFunc, a: ['a', 'b'], out: ['c'], type: 'promise' },
105
+ { f: add, a: ['c', 'b'], out: ['d'], type: 'promise' }
106
+ ],
107
+ outTask: { a: ['c', 'd'] }
108
+ });
109
+ t.deepEqual(errors, [], 'no validation errors');
110
+
111
+ fn(2, 3, function (err, c, d) {
112
+ t.equal(err.message, 'badFuncThrow');
113
+ t.end();
114
+ });
115
+ });
116
+
117
+ test('rejects with error', function (t) {
118
+ t.plan(2);
119
+ var fn = react();
120
+ var errors = fn.setAndValidateAST({
121
+ inParams: ['a', 'b'],
122
+ tasks: [
123
+ { f: badF2, a: ['a', 'b'], out: ['c'], type: 'promise' },
124
+ { f: add, a: ['c', 'b'], out: ['d'], type: 'promise' }
125
+ ],
126
+ outTask: { a: ['c', 'd'] }
127
+ });
128
+ t.deepEqual(errors, [], 'no validation errors');
129
+
130
+ fn(2, 3, function (err, c, d) {
131
+ t.equal(err.message, 'my-error');
132
+ t.end();
133
+ });
134
+ });
@@ -0,0 +1,132 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ Test core PromiseTasks using promised-io
5
+ */
6
+
7
+ var test = require('tap').test;
8
+ //var when = require('promised-io/promise');
9
+ var Deferred = require('promised-io/promise').Deferred;
10
+
11
+ var react = require('../'); //require('react');
12
+
13
+
14
+ function multiply(x, y) {
15
+ var deferred = new Deferred();
16
+ setTimeout(function () {
17
+ deferred.resolve(x * y);
18
+ }, 10);
19
+ return deferred.promise;
20
+ }
21
+ function add(x, y) {
22
+ var deferred = new Deferred();
23
+ setTimeout(function () {
24
+ deferred.resolve(x + y);
25
+ }, 10);
26
+ return deferred.promise;
27
+ }
28
+
29
+ function badFunc(a, b) {
30
+ throw new Error('badFuncThrow');
31
+ }
32
+
33
+ function badF2(a, b) {
34
+ var deferred = new Deferred();
35
+ setTimeout(function () {
36
+ deferred.reject(new Error('my-error'));
37
+ }, 10);
38
+ return deferred.promise;
39
+ }
40
+
41
+
42
+ test('multi-step', function (t) {
43
+ t.plan(4);
44
+ var fn = react();
45
+ var errors = fn.setAndValidateAST({
46
+ inParams: ['a', 'b'],
47
+ tasks: [
48
+ { f: multiply, a: ['a', 'b'], out: ['c'], type: 'promise' },
49
+ { f: add, a: ['c', 'b'], out: ['d'], type: 'promise' }
50
+ ],
51
+ outTask: { a: ['c', 'd'] }
52
+ });
53
+ t.deepEqual(errors, [], 'no validation errors');
54
+
55
+ fn(2, 3, function (err, c, d) {
56
+ t.equal(err, null);
57
+ t.equal(c, 6);
58
+ t.equal(d, 9);
59
+ t.end();
60
+ });
61
+ });
62
+
63
+ test('using "this" in a cb function', function (t) {
64
+ t.plan(3);
65
+ function getA(cb) {
66
+ /*jshint validthis: true */
67
+ var deferred = new Deferred();
68
+ var self = this;
69
+ setTimeout(function () {
70
+ deferred.resolve(self.a);
71
+ }, 10);
72
+ return deferred.promise;
73
+ }
74
+
75
+ var fn = react();
76
+ var errors = fn.setAndValidateAST({
77
+ inParams: [],
78
+ tasks: [
79
+ { f: getA, a: [], out: ['a'], type: 'promise' }
80
+ ],
81
+ outTask: { a: ['a'] }
82
+ });
83
+ t.deepEqual(errors, [], 'no validation errors');
84
+
85
+ var obj = {
86
+ a: 100
87
+ };
88
+
89
+ fn.apply(obj, [function (err, a) {
90
+ t.equal(err, null);
91
+ t.equal(a, 100);
92
+ t.end();
93
+ }]);
94
+ });
95
+
96
+ test('throws error', function (t) {
97
+ t.plan(2);
98
+ var fn = react();
99
+ var errors = fn.setAndValidateAST({
100
+ inParams: ['a', 'b'],
101
+ tasks: [
102
+ { f: badFunc, a: ['a', 'b'], out: ['c'], type: 'promise' },
103
+ { f: add, a: ['c', 'b'], out: ['d'], type: 'promise' }
104
+ ],
105
+ outTask: { a: ['c', 'd'] }
106
+ });
107
+ t.deepEqual(errors, [], 'no validation errors');
108
+
109
+ fn(2, 3, function (err, c, d) {
110
+ t.equal(err.message, 'badFuncThrow');
111
+ t.end();
112
+ });
113
+ });
114
+
115
+ test('rejects with error', function (t) {
116
+ t.plan(2);
117
+ var fn = react();
118
+ var errors = fn.setAndValidateAST({
119
+ inParams: ['a', 'b'],
120
+ tasks: [
121
+ { f: badF2, a: ['a', 'b'], out: ['c'], type: 'promise' },
122
+ { f: add, a: ['c', 'b'], out: ['d'], type: 'promise' }
123
+ ],
124
+ outTask: { a: ['c', 'd'] }
125
+ });
126
+ t.deepEqual(errors, [], 'no validation errors');
127
+
128
+ fn(2, 3, function (err, c, d) {
129
+ t.equal(err.message, 'my-error');
130
+ t.end();
131
+ });
132
+ });