react 0.0.0-f77c7b9d7 → 0.1.2
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 +5 -0
- package/Jakefile.js +8 -0
- package/LICENSE +5 -7
- package/README.md +242 -7
- package/examples/ast1.js +26 -0
- package/examples/chain-events1.js +34 -0
- package/examples/chain1.js +19 -0
- package/examples/fstr-events1.js +51 -0
- package/examples/fstr1.js +36 -0
- package/examples/pcode1.js +22 -0
- package/jake-tasks/jake-test.js +64 -0
- package/lib/base-task.js +115 -0
- package/lib/cb-task.js +67 -0
- package/lib/chain.js +148 -0
- package/lib/core.js +95 -0
- package/lib/error.js +37 -0
- package/lib/event-manager.js +57 -0
- package/lib/finalcb-first-task.js +59 -0
- package/lib/finalcb-task.js +54 -0
- package/lib/fstr.js +110 -0
- package/lib/id.js +10 -0
- package/lib/input-parser.js +44 -0
- package/lib/parse.js +28 -0
- package/lib/pcode.js +164 -0
- package/lib/ret-task.js +67 -0
- package/lib/status.js +5 -0
- package/lib/task.js +234 -0
- package/lib/validate.js +102 -0
- package/lib/vcon.js +76 -0
- package/oldExamples/analyze.js +29 -0
- package/oldExamples/analyze2.js +29 -0
- package/oldExamples/example10-dsl.js +63 -0
- package/oldExamples/example11.js +62 -0
- package/oldExamples/example12.js +63 -0
- package/oldExamples/example13.js +63 -0
- package/oldExamples/example14.js +63 -0
- package/oldExamples/example15.js +75 -0
- package/oldExamples/example6-ast.js +47 -0
- package/oldExamples/example6-dsl.js +49 -0
- package/oldExamples/example8-ast.js +55 -0
- package/oldExamples/example8-dsl.js +53 -0
- package/oldExamples/example9-ast.js +58 -0
- package/oldExamples/example9-dsl.js +57 -0
- package/oldExamples/function-str-ex1.js +33 -0
- package/oldExamples/function-str-ex2.js +67 -0
- package/oldExamples/trait1.js +41 -0
- package/oldExamples/trait2.js +44 -0
- package/package.json +18 -34
- package/react.js +12 -0
- package/test/ast.test.js +69 -0
- package/test/cb-task.test.js +197 -0
- package/test/chain.test.js +239 -0
- package/test/core.test.js +519 -0
- package/test/event-manager.test.js +102 -0
- package/test/exec-options.test.js +32 -0
- package/test/finalcb-task.test.js +37 -0
- package/test/fstr.test.js +288 -0
- package/test/input-parser.test.js +62 -0
- package/test/module-use.test.js +271 -0
- package/test/pcode.test.js +321 -0
- package/test/ret-task.test.js +199 -0
- package/test/task.test.js +21 -0
- package/test/validate-cb-task.test.js +74 -0
- package/test/validate-ret-task.test.js +83 -0
- package/test/validate.test.js +218 -0
- package/test/vcon.test.js +160 -0
- package/build-info.json +0 -8
- package/cjs/react-jsx-dev-runtime.development.js +0 -1200
- package/cjs/react-jsx-dev-runtime.production.min.js +0 -9
- package/cjs/react-jsx-dev-runtime.profiling.min.js +0 -9
- package/cjs/react-jsx-runtime.development.js +0 -1218
- package/cjs/react-jsx-runtime.production.min.js +0 -10
- package/cjs/react-jsx-runtime.profiling.min.js +0 -10
- package/cjs/react.development.js +0 -2330
- package/cjs/react.production.min.js +0 -23
- package/index.js +0 -7
- package/jsx-dev-runtime.js +0 -7
- package/jsx-runtime.js +0 -7
- package/umd/react.development.js +0 -3562
- package/umd/react.production.min.js +0 -31
- package/umd/react.profiling.min.js +0 -38
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
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/base-task.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var array = require('ensure-array');
|
|
4
|
+
var STATUS = require('./status.js');
|
|
5
|
+
var EventManager = require('./event-manager.js');
|
|
6
|
+
|
|
7
|
+
function BaseTask() {
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
Getter Fn to retrieveAn array of the output param names for this task.
|
|
12
|
+
*/
|
|
13
|
+
BaseTask.prototype.getOutParams = function () {
|
|
14
|
+
return array(this.out); // ensure array
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
BaseTask.prototype.isComplete = function () {
|
|
18
|
+
return (this.status === STATUS.COMPLETE);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
BaseTask.prototype.start = function (args) { // mark task as started with args and note time
|
|
22
|
+
this.args = args;
|
|
23
|
+
this.startTime = Date.now();
|
|
24
|
+
if (this.flowEmitter) this.flowEmitter.emitObject(EventManager.TYPES.TASK_BEGIN, this);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
BaseTask.prototype.complete = function (args) { //args that were used are available
|
|
28
|
+
this.results = args; // save the results
|
|
29
|
+
this.endTime = Date.now();
|
|
30
|
+
this.elapsedTime = this.endTime - this.startTime;
|
|
31
|
+
if (this.flowEmitter) this.flowEmitter.emitObject(EventManager.TYPES.TASK_COMPLETE, this);
|
|
32
|
+
this.status = STATUS.COMPLETE;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
BaseTask.prototype.functionExists = function (vCon) {
|
|
36
|
+
var fn = this.f;
|
|
37
|
+
if (!fn) return false;
|
|
38
|
+
if (fn instanceof Function) return true;
|
|
39
|
+
if (typeof(fn) === 'string') {
|
|
40
|
+
var f = vCon.getVar(fn); // fn/method by string
|
|
41
|
+
if (f && f instanceof Function) return true;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
BaseTask.prototype.areAllDepArgsDefined = function (vCon) {
|
|
47
|
+
return this.a.every(function (k) { return (vCon.getVar(k) !== undefined); });
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
BaseTask.prototype.depTasksAreDone = function (tasksByName) {
|
|
51
|
+
return (!this.after || !this.after.length || // no dep tasks OR
|
|
52
|
+
this.after.every(function (n) { return tasksByName[n].isComplete(); })); //all done
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
function isObjProperty(str) { return (str.indexOf('.') !== -1); }
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
check that obj parent is def and not null so writing to obj.prop
|
|
59
|
+
will not fail. ex: 'b.c' checks that b is def and not null.
|
|
60
|
+
Also returns true if not obj.prop but simple var ex: 'b'.
|
|
61
|
+
Tasks will implement outParentsExist() passing each out str
|
|
62
|
+
to this if they want to do this check.
|
|
63
|
+
*/
|
|
64
|
+
BaseTask.prototype.parentExists = function (objPropStr, vCon) {
|
|
65
|
+
if (!isObjProperty(objPropStr)) return true; // NOT obj prop, just simple arg, ret true
|
|
66
|
+
var nameAndProps = objPropStr.split('.');
|
|
67
|
+
nameAndProps.pop(); // pop off final prop
|
|
68
|
+
var parent = nameAndProps.reduce(function (accObj, prop) {
|
|
69
|
+
if (accObj === undefined || accObj === null) return undefined; // prevent exception
|
|
70
|
+
return accObj[prop];
|
|
71
|
+
}, vCon.values); // vCon['foo']['bar']
|
|
72
|
+
return (parent !== undefined && parent !== null);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
If params are obj property writes make sure the dst objects
|
|
77
|
+
are defined and not null. cb: ['b.c'] -> b is def and not null.
|
|
78
|
+
If null is specified then param is valid and will be ignored.
|
|
79
|
+
@returns true if all obj prop parents are def and non null
|
|
80
|
+
*/
|
|
81
|
+
BaseTask.prototype.outParentsExist = function (vCon) {
|
|
82
|
+
var self = this;
|
|
83
|
+
return this.getOutParams().every(function (x) {
|
|
84
|
+
if (x === null) return true;
|
|
85
|
+
return self.parentExists(x, vCon);
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
BaseTask.prototype.isReady = function (vCon, tasksByName) {
|
|
90
|
+
return !this.status && // not started AND
|
|
91
|
+
this.functionExists(vCon) && // function/method exists AND
|
|
92
|
+
this.areAllDepArgsDefined(vCon) && // all dep vars defined AND
|
|
93
|
+
this.depTasksAreDone(tasksByName) && // all dep tasks are done AND
|
|
94
|
+
(!this.outParentsExist || // (task does not implement outParentsExist method OR
|
|
95
|
+
this.outParentsExist(vCon)); // output parents exists (for obj property writes)
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
BaseTask.prototype.isMethodCall = function () {
|
|
99
|
+
return (typeof(this.f) === 'string' && /^.*\..*$/.test(this.f)); //str contains .
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
BaseTask.prototype.getMethodObj = function (vCon) { //obj.prop.prop2, returns obj.prop or undefined
|
|
103
|
+
var name = this.f;
|
|
104
|
+
if (!name) return undefined;
|
|
105
|
+
var nameAndProps = name.split('.');
|
|
106
|
+
nameAndProps.pop(); // pop off last one
|
|
107
|
+
if (!nameAndProps.length) return undefined;
|
|
108
|
+
var result = nameAndProps.reduce(function (accObj, prop) {
|
|
109
|
+
if (accObj === undefined || accObj === null) return undefined; // prevent exception
|
|
110
|
+
return accObj[prop];
|
|
111
|
+
}, vCon.values); // vCon['foo']['bar']
|
|
112
|
+
return result;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
module.exports = BaseTask;
|
package/lib/cb-task.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var util = require('util');
|
|
4
|
+
var sprintf = require('sprintf').sprintf;
|
|
5
|
+
|
|
6
|
+
var BaseTask = require('./base-task.js');
|
|
7
|
+
|
|
8
|
+
function format_error(errmsg, obj) {
|
|
9
|
+
return sprintf('%s - %s', errmsg, util.inspect(obj));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
var REQ = 'cbTask requires f, a, out';
|
|
13
|
+
var FN_REQ = 'cbTask requires f to be a function or string';
|
|
14
|
+
var A_REQ = 'cbTask requires a to be an array of string param names';
|
|
15
|
+
var CB_REQ = 'cbTask requires out to be an array of string param names';
|
|
16
|
+
|
|
17
|
+
function CbTask(taskDef) {
|
|
18
|
+
var self = this;
|
|
19
|
+
Object.keys(taskDef).forEach(function (k) { self[k] = taskDef[k]; });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
CbTask.prototype = new BaseTask();
|
|
23
|
+
CbTask.prototype.constructor = CbTask;
|
|
24
|
+
|
|
25
|
+
CbTask.validate = function (taskDef) {
|
|
26
|
+
var errors = [];
|
|
27
|
+
if (!taskDef.f || !taskDef.a || !taskDef.out) {
|
|
28
|
+
errors.push(format_error(REQ, taskDef));
|
|
29
|
+
} else {
|
|
30
|
+
var ftype = typeof(taskDef.f);
|
|
31
|
+
if (! ((taskDef.f instanceof Function) || (ftype === 'string'))) {
|
|
32
|
+
errors.push(format_error(FN_REQ, taskDef));
|
|
33
|
+
}
|
|
34
|
+
if (! (Array.isArray(taskDef.a) &&
|
|
35
|
+
taskDef.a.every(function (x) { return (typeof(x) === 'string'); }))) {
|
|
36
|
+
errors.push(format_error(A_REQ, taskDef));
|
|
37
|
+
}
|
|
38
|
+
if (! (Array.isArray(taskDef.out) &&
|
|
39
|
+
taskDef.out.every(function (x) { return (typeof(x) === 'string'); }))) {
|
|
40
|
+
errors.push(format_error(CB_REQ, taskDef));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return errors;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
CbTask.prototype.exec = function exec(vCon, handleError, contExec) {
|
|
47
|
+
try {
|
|
48
|
+
var args = this.a.map(function (k) { return vCon.getVar(k); }); //get args from vCon
|
|
49
|
+
//console.error('CbTask.exec.args=', args);
|
|
50
|
+
//console.error('CbTask.exec.vCon=', vCon);
|
|
51
|
+
this.start(args); //note the start time, args
|
|
52
|
+
args.push(this.cbFun); // push callback fn on end
|
|
53
|
+
var func = this.f;
|
|
54
|
+
var bindObj = null; //global space
|
|
55
|
+
if (this.isMethodCall()) { //if method call then reset func and bindObj
|
|
56
|
+
func = vCon.getVar(this.f);
|
|
57
|
+
bindObj = this.getMethodObj(vCon);
|
|
58
|
+
} else if (typeof(func) === 'string') {
|
|
59
|
+
func = vCon.getVar(func); // we want the actual fn from this string
|
|
60
|
+
}
|
|
61
|
+
func.apply(bindObj, args);
|
|
62
|
+
} catch (err) { //catch and handle the task error, calling final cb
|
|
63
|
+
handleError(this, err);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
module.exports = CbTask;
|
package/lib/chain.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
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;
|
package/lib/core.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var EventEmitter = require('events').EventEmitter;
|
|
4
|
+
|
|
5
|
+
var error = require('./error.js');
|
|
6
|
+
var validate = require('./validate.js');
|
|
7
|
+
var tskutil = require('./task.js');
|
|
8
|
+
var STATUS = require('./status.js');
|
|
9
|
+
var VContext = require('./vcon.js');
|
|
10
|
+
var FinalCbTask = require('./finalcb-task.js');
|
|
11
|
+
var EventManager = require('./event-manager.js');
|
|
12
|
+
var inputParser = require('./input-parser.js');
|
|
13
|
+
var idGenerator = require('./id.js');
|
|
14
|
+
|
|
15
|
+
var reactOptions = {
|
|
16
|
+
stackTraceLimitMin: 30
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
var reactEmitter = EventManager.create(); // the top emitter
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
Creates react function which the AST can be manipulated and then
|
|
23
|
+
is ready to be executed. Can be used directly or a DSL can wrap this
|
|
24
|
+
to provide the AST.
|
|
25
|
+
|
|
26
|
+
@example
|
|
27
|
+
var react = require('react');
|
|
28
|
+
var fn = react();
|
|
29
|
+
var valid2 = fn.setAndValidateAST({
|
|
30
|
+
name: 'optionalName',
|
|
31
|
+
inParams: ['a', 'b'],
|
|
32
|
+
tasks: [
|
|
33
|
+
{ type: 'cb', f: multiply, a: ['a', 'b'], out: ['c'] }
|
|
34
|
+
],
|
|
35
|
+
outTask: { a: ['c'] }
|
|
36
|
+
});
|
|
37
|
+
console.log(fn.ast); // view
|
|
38
|
+
fn(123, 456, cb);
|
|
39
|
+
*/
|
|
40
|
+
function reactFactory() {
|
|
41
|
+
if (arguments.length) throw new Error('react() takes no args, check API');
|
|
42
|
+
|
|
43
|
+
error.ensureStackTraceLimitSet(reactOptions.stackTraceLimitMin);
|
|
44
|
+
var flowEmitter = EventManager.create();
|
|
45
|
+
flowEmitter.parent = reactEmitter;
|
|
46
|
+
|
|
47
|
+
var ast = {
|
|
48
|
+
inParams: [],
|
|
49
|
+
tasks: [],
|
|
50
|
+
outTask: {},
|
|
51
|
+
locals: {}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function setAndValidateAST(newAST) { //set AST then validate, ret error[]
|
|
55
|
+
Object.keys(newAST).forEach(function (k) { ast[k] = newAST[k]; }); // copy all properties
|
|
56
|
+
var errors = validate(ast);
|
|
57
|
+
if (!errors.length) tskutil.nameTasks(ast.tasks); //run this so names can be checked in ast
|
|
58
|
+
return errors;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function exec(arg1, arg2, argN, cb) { // called to execute the flow
|
|
62
|
+
var parsedInput = inputParser(Array.prototype.slice.call(arguments), ast);
|
|
63
|
+
var args = parsedInput.args;
|
|
64
|
+
var cbFinal = parsedInput.cb;
|
|
65
|
+
var extraArgs = parsedInput.extraArgs; // we'll have these if we need them
|
|
66
|
+
var vCon = VContext.create(args, ast.inParams, ast.locals); // create var ctx with in args & locals
|
|
67
|
+
var tasks = ast.tasks.map(tskutil.create);
|
|
68
|
+
var tasksByName = tskutil.nameTasks(tasks); // map names to working tasks
|
|
69
|
+
var outTask = tskutil.createOutTask(ast.outTask, cbFinal, tasks, vCon);
|
|
70
|
+
var handleError = tskutil.createErrorHandler(vCon, outTask);
|
|
71
|
+
|
|
72
|
+
function contExec() {
|
|
73
|
+
if (!outTask.f) { return; } //stop execution, we already hit an error, f was cleared
|
|
74
|
+
if (outTask.isReady()) return outTask.exec(); // all tasks done, exec cb, return
|
|
75
|
+
tskutil.findReadyAndExec(vCon, tasks, tasksByName, handleError, contExec); //exec tasks that ready to run
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
tasks.forEach(function (t) {
|
|
79
|
+
t.id = idGenerator.createUniqueId();
|
|
80
|
+
t.flowEmitter = flowEmitter;
|
|
81
|
+
if (t.type === 'cb') t.cbFun = tskutil.createCallback(t, handleError, vCon, contExec, flowEmitter);
|
|
82
|
+
}); // create callbacks
|
|
83
|
+
contExec(); // start things off
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
var reactFn = exec; // make the exec() the function returned
|
|
87
|
+
reactFn.ast = ast; // put AST hanging off the fn so it can be inspected
|
|
88
|
+
reactFn.setAndValidateAST = setAndValidateAST; // call to set AST and then validate
|
|
89
|
+
reactFn.events = flowEmitter; // used to listen to execution events for this flow
|
|
90
|
+
return reactFn;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = reactFactory; // module returns reactFactory to create a react fn
|
|
94
|
+
module.exports.options = reactOptions; // global react options
|
|
95
|
+
module.exports.events = reactEmitter; // global react emitter
|