react 0.0.1 → 0.0.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/README.md +10 -0
- package/lib/react.js +18 -7
- package/package.json +1 -1
- package/test/example6-ast.js +2 -2
- package/test/example6-dsl.js +2 -2
- package/test/example8-ast.js +2 -2
- package/test/example8-dsl.js +2 -2
- package/test/example9-ast.js +57 -0
- package/test/example9-dsl.js +56 -0
package/README.md
CHANGED
|
@@ -12,6 +12,8 @@ It takes inspiration from several projects including:
|
|
|
12
12
|
- Tim Caswell and Elijah Insua's [conductor](https://github.com/creationix/conductor) - [Article](http://howtonode.org/step-of-conductor)
|
|
13
13
|
- Caolan McMahon's [async](https://github.com/caolan/async)
|
|
14
14
|
|
|
15
|
+
React gets its name from similarities with how "chain reactions" work in the physical world. You start the reaction and then it cascades and continues until complete.
|
|
16
|
+
|
|
15
17
|
## Goals
|
|
16
18
|
|
|
17
19
|
- Improved error and exception handling
|
|
@@ -40,6 +42,14 @@ To reduce the boilerplate code needed and improve error handling, React automati
|
|
|
40
42
|
- Validate the flow AST - determine if dependencies can all be met as defined such that flow will complete (TODO)
|
|
41
43
|
- Execute the flow AST
|
|
42
44
|
|
|
45
|
+
## Installing
|
|
46
|
+
|
|
47
|
+
npm install react
|
|
48
|
+
|
|
49
|
+
OR
|
|
50
|
+
|
|
51
|
+
Pull from github - http://github.com/jeffbski/react
|
|
52
|
+
|
|
43
53
|
## Examples
|
|
44
54
|
|
|
45
55
|
1. [Direct AST](#directAST)
|
package/lib/react.js
CHANGED
|
@@ -163,10 +163,15 @@ function react(inputDef){
|
|
|
163
163
|
});
|
|
164
164
|
tasksByName = nameTasks(tasks); //remap names to exec task copies instead of taskDefs
|
|
165
165
|
|
|
166
|
+
function getVar(name) { //get the name from the variable context, name might be simple or obj.prop
|
|
167
|
+
var nameAndProps = name.split('.');
|
|
168
|
+
return nameAndProps.reduce(function(accObj, prop){ return accObj[prop]; }, vCon); // vCon['foo']['bar']
|
|
169
|
+
}
|
|
170
|
+
|
|
166
171
|
|
|
167
172
|
function execTask(t){
|
|
168
173
|
t.status = STATUS.RUNNING;
|
|
169
|
-
var args = t.a.map(function(k){ return
|
|
174
|
+
var args = t.a.map(function(k){ return getVar(k); }); //get args from vCon
|
|
170
175
|
if (t.cbFun) args.push(t.cbFun); //push custom callback to back if fn uses cb
|
|
171
176
|
if (reactOptions.debugOutput) console.log('starting task: %s', fName(t.f), args);
|
|
172
177
|
try {
|
|
@@ -192,6 +197,17 @@ function react(inputDef){
|
|
|
192
197
|
}
|
|
193
198
|
} catch (e) { handleTaskError(t, e); } //catch and handle the task error, calling final cb
|
|
194
199
|
}
|
|
200
|
+
|
|
201
|
+
function stripProp(objectWithOptionalPropertyName) { //return only object if object.property
|
|
202
|
+
return ( /\w+/ ).exec(objectWithOptionalPropertyName)[0];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function isTaskReady(t, idx, arr){
|
|
206
|
+
return !t.status && // filter for not started AND
|
|
207
|
+
t.a.every(function(k){ return (vCon[stripProp(k)] !== undefined); }) && // all dep vars defined AND
|
|
208
|
+
(!t.after || // (no dep tasks OR
|
|
209
|
+
t.after.every( function(n){ return tasksByName[n].status === STATUS.COMPLETE; })); //alldone
|
|
210
|
+
}
|
|
195
211
|
|
|
196
212
|
contExec = function contExec(){
|
|
197
213
|
if (firstError) { return; } //stop execution, we already hit an error
|
|
@@ -202,12 +218,7 @@ function react(inputDef){
|
|
|
202
218
|
cbFinal.apply(null, finalArgs);
|
|
203
219
|
return;
|
|
204
220
|
}
|
|
205
|
-
var tasksReady = tasks.filter(
|
|
206
|
-
return !t.status && // filter for not started AND
|
|
207
|
-
t.a.every(function(k){ return (vCon[k] !== undefined); }) && // all dep vars defined AND
|
|
208
|
-
(!t.after || // (no dep tasks OR
|
|
209
|
-
t.after.every( function(n){ return tasksByName[n].status === STATUS.COMPLETE; })); //alldone
|
|
210
|
-
});
|
|
221
|
+
var tasksReady = tasks.filter(isTaskReady); //if we are here then we stil have tasks to run
|
|
211
222
|
tasksReady.forEach(function(t){ t.status = STATUS.READY; }); //set ready before call, no double exec
|
|
212
223
|
tasksReady.forEach(function(t){ execTask(t); });
|
|
213
224
|
};
|
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.0.
|
|
4
|
+
"version": "0.0.2",
|
|
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/example6-ast.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
Example setting the AST directly without using define
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
var react = require('
|
|
8
|
-
var reactOptions = require('react').reactOptions;
|
|
7
|
+
var react = require(__dirname+'/../lib/react.js').react;
|
|
8
|
+
var reactOptions = require(__dirname+'/../lib/react.js').reactOptions;
|
|
9
9
|
reactOptions.debugOutput = true;
|
|
10
10
|
|
|
11
11
|
function loadUser(uid, cb){ setTimeout(cb, 100, null, "User"+uid); }
|
package/test/example6-dsl.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
Example using functions with the simple DSL
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
var react = require('
|
|
8
|
-
var reactOptions = require('react').reactOptions;
|
|
7
|
+
var react = require(__dirname+'/../lib/react.js').react;
|
|
8
|
+
var reactOptions = require(__dirname+'/../lib/react.js').reactOptions;
|
|
9
9
|
reactOptions.debugOutput = true;
|
|
10
10
|
reactOptions.stackTraceLimitMin = 20;
|
|
11
11
|
|
package/test/example8-ast.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
AST directly without define, using object methods in addition to functions
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
var react = require('
|
|
8
|
-
var reactOptions = require('react').reactOptions;
|
|
7
|
+
var react = require(__dirname+'/../lib/react.js').react;
|
|
8
|
+
var reactOptions = require(__dirname+'/../lib/react.js').reactOptions;
|
|
9
9
|
reactOptions.debugOutput = true;
|
|
10
10
|
|
|
11
11
|
|
package/test/example8-dsl.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
Using object methods in addition to functions with simple DSL
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
var react = require('
|
|
8
|
-
var reactOptions = require('react').reactOptions;
|
|
7
|
+
var react = require(__dirname+'/../lib/react.js').react;
|
|
8
|
+
var reactOptions = require(__dirname+'/../lib/react.js').reactOptions;
|
|
9
9
|
reactOptions.debugOutput = true;
|
|
10
10
|
reactOptions.stackTraceLimitMin = 20;
|
|
11
11
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
AST directly without define, using object methods in addition to functions
|
|
5
|
+
also passing in an options object and referring to the properties.
|
|
6
|
+
The dependency is on the object existing, if it exists, it expects the values
|
|
7
|
+
to be there.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var react = require(__dirname+'/../lib/react.js').react;
|
|
11
|
+
var reactOptions = require(__dirname+'/../lib/react.js').reactOptions;
|
|
12
|
+
reactOptions.debugOutput = true;
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
var UserMgr = function(){ };
|
|
16
|
+
UserMgr.prototype = {};
|
|
17
|
+
UserMgr.prototype.constructor = UserMgr;
|
|
18
|
+
UserMgr.prototype.loadUser = function loadUser(uid, cb){ setTimeout(cb, 100, null, "User"+uid); };
|
|
19
|
+
|
|
20
|
+
function loadFile(filename, cb){ setTimeout(cb, 100, null, 'Filedata'+filename); }
|
|
21
|
+
function markdown(filedata) { return 'html'+filedata; }
|
|
22
|
+
function prepareDirectory(outDirname, cb){ setTimeout(cb, 200, null, 'dircreated-'+outDirname); }
|
|
23
|
+
function writeOutput(html, user, cb){ setTimeout(cb, 300, null, html+'_bytesWritten'); }
|
|
24
|
+
function loadEmailTemplate(cb) { setTimeout(cb, 50, null, 'emailmd'); }
|
|
25
|
+
function customizeEmail(user, emailHtml, cb) { return 'cust-'+user+emailHtml; }
|
|
26
|
+
function deliverEmail(custEmailHtml, cb) { setTimeout(cb, 100, null, 'delivered-'+custEmailHtml); }
|
|
27
|
+
|
|
28
|
+
function useHtml(err, html, user, bytesWritten) {
|
|
29
|
+
if(err) {
|
|
30
|
+
console.log('***Error: %s', err);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
console.log('final result: %s, user: %s, written:%s', html, user, bytesWritten);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
var r = react();
|
|
37
|
+
r.ast.inputNames = ['options', 'uid', 'anObj', 'cb'];
|
|
38
|
+
r.ast.taskDefs = [
|
|
39
|
+
{ f:'anObj.loadUser', a:['uid'], cb:['user'] },
|
|
40
|
+
{ f:loadFile, a:['options.filename'], cb:['filedata'] },
|
|
41
|
+
{ f:markdown, a:['filedata'], ret:['html'] },
|
|
42
|
+
{ f:prepareDirectory, a:['options.outDirname'],cb:['dircreated'] },
|
|
43
|
+
{ f:writeOutput, a:['html', 'user'], cb:['bytesWritten'], after:['prepareDirectory'] },
|
|
44
|
+
{ f:loadEmailTemplate, a:[], cb:['emailmd'] },
|
|
45
|
+
{ f:markdown, a:['emailmd'], ret:['emailHtml'] },
|
|
46
|
+
{ f:customizeEmail, a:['user', 'emailHtml'], ret:['custEmailHtml'] },
|
|
47
|
+
{ f:deliverEmail, a:['custEmailHtml'], cb:['deliveredEmail'], after:['writeOutput'] }
|
|
48
|
+
];
|
|
49
|
+
r.ast.finalOutputNames = ['html', 'user', 'bytesWritten'];
|
|
50
|
+
|
|
51
|
+
var myObj = new UserMgr();
|
|
52
|
+
r.exec({ filename: "hello.txt", outDirname: 'outHello' }, 100, myObj, useHtml);
|
|
53
|
+
r.exec({ filename: "small.txt", outDirname: 'outSmall' }, 200, myObj, useHtml);
|
|
54
|
+
r.exec({ filename: "world.txt", outDirname: 'outWorld' }, 300, myObj, useHtml);
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Using object methods in addition to functions with simple DSL
|
|
5
|
+
also passing in an options object and referring to the properties.
|
|
6
|
+
The dependency is on the object existing, if it exists, it expects the values
|
|
7
|
+
to be there.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var react = require(__dirname+'/../lib/react.js').react;
|
|
11
|
+
var reactOptions = require(__dirname+'/../lib/react.js').reactOptions;
|
|
12
|
+
reactOptions.debugOutput = true;
|
|
13
|
+
reactOptions.stackTraceLimitMin = 20;
|
|
14
|
+
|
|
15
|
+
var UserMgr = function(){ };
|
|
16
|
+
UserMgr.prototype = {};
|
|
17
|
+
UserMgr.prototype.constructor = UserMgr;
|
|
18
|
+
UserMgr.prototype.loadUser = function loadUser(uid, cb){ setTimeout(cb, 100, null, "User"+uid); };
|
|
19
|
+
|
|
20
|
+
function loadFile(filename, cb){ setTimeout(cb, 100, null, 'Filedata'+filename); }
|
|
21
|
+
function markdown(filedata) { return 'html'+filedata; }
|
|
22
|
+
function prepareDirectory(outDirname, cb){ setTimeout(cb, 200, null, 'dircreated-'+outDirname); }
|
|
23
|
+
function writeOutput(html, user, cb){ setTimeout(cb, 300, null, html+'_bytesWritten'); }
|
|
24
|
+
function loadEmailTemplate(cb) { setTimeout(cb, 50, null, 'emailmd'); }
|
|
25
|
+
function customizeEmail(user, emailHtml, cb) { return 'cust-'+user+emailHtml; }
|
|
26
|
+
function deliverEmail(custEmailHtml, cb) { setTimeout(cb, 100, null, 'delivered-'+custEmailHtml); }
|
|
27
|
+
|
|
28
|
+
function useHtml(err, html, user, bytesWritten) {
|
|
29
|
+
if(err) {
|
|
30
|
+
console.log('***Error: %s', err);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
console.log('final result: %s, user: %s, written: %s', html, user, bytesWritten);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
var r = react('options, uid, anObj, cb').define(
|
|
37
|
+
'anObj.loadUser', 'uid -> err, user',
|
|
38
|
+
loadFile, 'options.filename -> err, filedata',
|
|
39
|
+
markdown, 'filedata -> returns html',
|
|
40
|
+
prepareDirectory, 'options.outDirname -> err, dircreated',
|
|
41
|
+
writeOutput, 'html, user -> err, bytesWritten', { after:prepareDirectory },
|
|
42
|
+
loadEmailTemplate,' -> err, emailmd',
|
|
43
|
+
markdown, 'emailmd -> returns emailHtml',
|
|
44
|
+
customizeEmail, 'user, emailHtml -> returns custEmailHtml',
|
|
45
|
+
deliverEmail, 'custEmailHtml -> err, deliveredEmail', { after: writeOutput }
|
|
46
|
+
).callbackDef('err, html, user, bytesWritten');
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
//console.log(r.ast);
|
|
50
|
+
|
|
51
|
+
var myObj = new UserMgr();
|
|
52
|
+
r.exec({ filename: "hello.txt", outDirname: 'outHello' }, 100, myObj, useHtml);
|
|
53
|
+
r.exec({ filename: "small.txt", outDirname: 'outSmall' }, 200, myObj, useHtml);
|
|
54
|
+
r.exec({ filename: "world.txt", outDirname: 'outWorld' }, 300, myObj, useHtml);
|
|
55
|
+
|
|
56
|
+
|