react 0.3.4 → 0.5.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.
Files changed (42) hide show
  1. package/.npmignore +2 -1
  2. package/README.md +68 -172
  3. package/doc/advanced.md +166 -0
  4. package/doc/color-def.graffle +938 -0
  5. package/doc/color-def.png +0 -0
  6. package/doc/simple.dot +25 -0
  7. package/doc/simple.png +0 -0
  8. package/examples/{default1.js → longer-example.js} +0 -0
  9. package/examples/simple.js +45 -0
  10. package/examples/{ast1.js → using-ast-directly.js} +4 -0
  11. package/examples/{default-events1.js → using-events1.js} +0 -0
  12. package/examples/{default-log-events.js → using-log-events.js} +1 -1
  13. package/lib/core.js +13 -1
  14. package/lib/event-collector.js +68 -0
  15. package/lib/event-manager.js +4 -0
  16. package/lib/id.js +1 -0
  17. package/lib/log-events.js +30 -15
  18. package/{promise-resolve.js → lib/promise-resolve.js} +1 -1
  19. package/lib/task.js +8 -3
  20. package/lib/track-tasks.js +5 -62
  21. package/lib/vcon.js +1 -1
  22. package/package.json +2 -2
  23. package/react.js +33 -1
  24. package/test/ast.test.js +50 -1
  25. package/test/core.test.js +27 -2
  26. package/test/dsl.test.js +2 -2
  27. package/test/module-use.test.js +5 -2
  28. package/test/promise-auto-resolve.test.js +2 -1
  29. package/Jakefile.js +0 -8
  30. package/doc/alternate-dsls.md +0 -103
  31. package/dsl/chain.js +0 -150
  32. package/dsl/fstr.js +0 -121
  33. package/dsl/pcode.js +0 -175
  34. package/examples/chain-events1.js +0 -55
  35. package/examples/chain1.js +0 -19
  36. package/examples/fstr-events1.js +0 -38
  37. package/examples/fstr1.js +0 -37
  38. package/examples/pcode1.js +0 -22
  39. package/jake-tasks/jake-test.js +0 -64
  40. package/test/dsl/chain.test.js +0 -324
  41. package/test/dsl/fstr.test.js +0 -300
  42. package/test/dsl/pcode.test.js +0 -448
Binary file
package/doc/simple.dot ADDED
@@ -0,0 +1,25 @@
1
+ digraph loadRender {
2
+ loadRender_input [ shape = box, style = filled, fillcolor = aquamarine ];
3
+ fooPath [ style = filled, fillcolor = gainsboro ];
4
+ barPath [ style = filled, fillcolor = gainsboro ];
5
+ barP2 [ style = filled, fillcolor = gainsboro ];
6
+ loadFoo [ shape = box, color = blue, fillcolor = beige, style = filled ];
7
+ foo [ style = filled, fillcolor = gainsboro ];
8
+ loadBar [ shape = box, color = blue, fillcolor = beige, style = filled ];
9
+ bar [ style = filled, fillcolor = gainsboro ];
10
+ render [ shape = box, color = blue, fillcolor = beige, style = filled ];
11
+ renderedOut [ style = filled, fillcolor = gainsboro ];
12
+ loadRender_output [ shape = box, style = filled, fillcolor = aquamarine ];
13
+ loadRender_input -> fooPath;
14
+ loadRender_input -> barPath;
15
+ loadRender_input -> barP2;
16
+ fooPath -> loadFoo;
17
+ loadFoo -> foo;
18
+ barPath -> loadBar;
19
+ barP2 -> loadBar;
20
+ loadBar -> bar;
21
+ foo -> render;
22
+ bar -> render;
23
+ render -> renderedOut;
24
+ renderedOut -> loadRender_output;
25
+ }
package/doc/simple.png ADDED
Binary file
File without changes
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ Simple example showing flow definition of two async functions feeding a
5
+ synchronous function.
6
+
7
+ First two async functions inputs are satisfied by the flow inputs, so
8
+ they will both run immediately in parallel.
9
+
10
+ The last function waits for the outputs of the previous ones, then
11
+ executes synchronously.
12
+
13
+ Finally the flow calls the callback with the output values once all
14
+ the tasks have completed.
15
+ */
16
+
17
+ var react = require('../'); // require('react');
18
+
19
+ function loadFoo(fooPath, cb) {
20
+ setTimeout(function () {
21
+ cb(null, [fooPath, 'data'].join(':'));
22
+ }, 10);
23
+ }
24
+
25
+ function loadBar(barPath, barP2, cb) {
26
+ setTimeout(function () {
27
+ cb(null, [barPath, barP2, 'data'].join(':'));
28
+ }, 10);
29
+ }
30
+
31
+ function render(foo, bar) {
32
+ return ['<html>', foo, '/', bar, '</html>'].join('');
33
+ }
34
+
35
+
36
+ var fn = react('loadRender', 'fooPath, barPath, barP2, cb -> err, renderedOut',
37
+ loadFoo, 'fooPath, cb -> err, foo',
38
+ loadBar, 'barPath, barP2, cb -> err, bar',
39
+ render, 'foo, bar -> renderedOut'
40
+ );
41
+
42
+
43
+ fn('foo.txt', 'bar.txt', 'BBB', function (err, renderedOut) {
44
+ console.error('results:', renderedOut);
45
+ });
@@ -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'); }
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  var react = require('../'); // require('react');
9
- require('../lib/log-events').logEvents(react); // require('react/lib/log-events').logEvents(react); // turn on logging
9
+ react.logEvents(); // turn on logging of all flow and task events for all react functions
10
10
 
11
11
 
12
12
  function loadUser(uid, cb){ setTimeout(cb, 100, null, "User"+uid); }
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) tskutil.nameTasks(ast.tasks); //run this so names can be checked in ast
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
 
@@ -0,0 +1,68 @@
1
+ 'use strict';
2
+
3
+ var react = require('../'); // require('react');
4
+ react.trackTasks(); // enable task tracking
5
+
6
+ var AST_EVENTS_RE = /^ast\./;
7
+ var TASK_EVENTS_RE = /^task\./;
8
+ var FLOW_EVENTS_RE = /^flow\./;
9
+
10
+ /**
11
+ Accumulator to make it easy to capture events
12
+
13
+ @example
14
+ var EventCollector = require('react/lib/event-collector');
15
+ var collector = new EventCollector();
16
+
17
+ collector.capture(); // capture all flow and task events for all react flows
18
+ collector.capture('flow.*'); // capture all flow events for all react flows
19
+ collector.capture(flowFn, 'task.*'); // capture task events on a flow
20
+ collector.capture(flowFn, 'flow.*'); // add capture flow events on a flow
21
+
22
+ var events = collector.list(); // retrieve the list of events
23
+ collector.clear(); // clear the list of events;
24
+ */
25
+ function EventCollector() {
26
+ this.events = [];
27
+ }
28
+
29
+ /**
30
+ register listener to capture events for a specific flow
31
+ @param flowFn the react flow function or can pass global react
32
+ @param eventId event id or wildcarded id
33
+ */
34
+ EventCollector.prototype.capture = function (flowFn, eventId) {
35
+ /*jshint validthis: true */
36
+ if (!eventId && typeof(flowFn) === 'string') { // only eventId provided
37
+ eventId = flowFn;
38
+ flowFn = react; // global react
39
+ } else if (!flowFn) flowFn = react; // global react
40
+ if (!eventId) eventId = '*'; // default to all
41
+ var emitter = flowFn.events;
42
+ var self = this;
43
+ function accumEvents(obj) {
44
+ var eventObject = {
45
+ event: this.event,
46
+ time: Date.now()
47
+ };
48
+ if (FLOW_EVENTS_RE.test(this.event)) {
49
+ eventObject.env = obj;
50
+ } else if (TASK_EVENTS_RE.test(this.event)) {
51
+ eventObject.task = obj;
52
+ } else if (AST_EVENTS_RE.test(this.event)) {
53
+ eventObject.ast = obj;
54
+ }
55
+ self.events.push(eventObject);
56
+ }
57
+ emitter.on(eventId, accumEvents);
58
+ };
59
+
60
+ EventCollector.prototype.list = function () {
61
+ return this.events;
62
+ };
63
+
64
+ EventCollector.prototype.clear = function () {
65
+ this.events = []; // clear
66
+ };
67
+
68
+ module.exports = EventCollector;
@@ -8,8 +8,11 @@ var EVENT_EMITTER2_CONFIG = {
8
8
  maxListeners: 30 // the max number of listeners that can be assigned to an event, defaults to 10.
9
9
  };
10
10
 
11
+ var PASS_EVENTS_PROCESS_RE = /^ast.defined$/; // events to pass up to global process
12
+
11
13
  var TYPES = {
12
14
  // Flow monitoring events and their params
15
+ AST_DEFINED: 'ast.defined', // ast
13
16
  FLOW_BEGIN: 'flow.begin', // env
14
17
  TASK_BEGIN: 'task.begin', // task
15
18
  TASK_COMPLETE: 'task.complete', // task
@@ -60,6 +63,7 @@ EventManager.prototype.emit = function (event, arg1, arg2, argN) {
60
63
  if (event === undefined) throw new Error('event is undefined');
61
64
  if (this.emitter) this.emitter.emit.apply(this.emitter, arguments);
62
65
  if (this.parent && this.parent.isEnabled()) this.parent.emit.apply(this.parent, arguments);
66
+ if (PASS_EVENTS_PROCESS_RE.test(event) && process) process.emit.apply(process, arguments); // pass some to process
63
67
  };
64
68
 
65
69
  EventManager.prototype.removeListener = function (event, listener) {
package/lib/id.js CHANGED
@@ -4,6 +4,7 @@ var startingId = 0;
4
4
 
5
5
  function createUniqueId() {
6
6
  startingId += 1;
7
+ if (startingId === Number.MAX_VALUE) startingId = 0; // if hits this start over //TODO need something better?
7
8
  return startingId;
8
9
  }
9
10
 
package/lib/log-events.js CHANGED
@@ -5,13 +5,20 @@
5
5
 
6
6
  @example
7
7
  var react = require('react');
8
- require('react/lib/log-events').logEvent(react);
8
+ react.logEvents(); // log all task and flow events on all react functions
9
+ react.logEvents('task.*'); // log all task events on all react functions
10
+ react.logEvents(flowFn); // log all task and flow events on flowFn only
11
+ react.logEvents(flowFn, 'flow.*'); // log all flow events on flowFn only
9
12
  */
10
13
 
11
- var react = require('../lib/track-tasks'); // require('react/lib/track-tasks'); // turn on tracking
14
+ var util = require('util'); // TODO replace inspect with something portable to browser
15
+
16
+ var react = require('../'); // require('react');
17
+ react.trackTasks(); // enable task and flow tracking
12
18
 
13
19
  var ALL_FLOW_EVENTS = 'flow.*';
14
20
  var ALL_TASK_EVENTS = 'task.*';
21
+ var FLOW_RE = /^flow\./;
15
22
 
16
23
  function flowLog(obj) {
17
24
  /*jshint validthis: true */
@@ -21,12 +28,12 @@ function flowLog(obj) {
21
28
  var eventTimeStr = time.toISOString();
22
29
  if (this.event === 'flow.complete') {
23
30
  var env = obj;
24
- console.error('%s: %s \tmsecs:(%s) \n\targs:(%s) \n\tresults:(%s)\n',
25
- this.event, env.name, env.elapsedTime, argsNoCb, env.results);
31
+ console.error('%s: %s \tmsecs: %s \n\targs: %s \n\tresults: %s\n',
32
+ this.event, env.name, env.elapsedTime, util.inspect(argsNoCb), util.inspect(env.results));
26
33
  } else {
27
34
  var name = obj.name;
28
35
  var args = obj.args;
29
- console.error('%s: %s \n\targs:(%s)\n', this.event, name, argsNoCb);
36
+ console.error('%s: %s \n\targs: %s\n', this.event, name, util.inspect(argsNoCb));
30
37
  }
31
38
  }
32
39
 
@@ -38,12 +45,12 @@ function taskLog(obj) {
38
45
  var eventTimeStr = time.toISOString();
39
46
  if (this.event === 'task.complete') {
40
47
  var task = obj;
41
- console.error('%s: %s \tmsecs:(%s) \n\targs:(%s) \n\tresults:(%s)\n',
42
- this.event, task.name, task.elapsedTime, argsNoCb, 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));
43
50
  } else {
44
51
  var name = obj.name;
45
52
  var args = obj.args;
46
- console.error('%s: %s \n\targs:(%s)\n', this.event, name, argsNoCb);
53
+ console.error('%s: %s:%s \n\targs: %s\n', this.event, obj.env.name, obj.name, util.inspect(argsNoCb));
47
54
  }
48
55
 
49
56
  }
@@ -55,16 +62,24 @@ function taskLog(obj) {
55
62
 
56
63
  @example
57
64
  var react = require('react');
58
- require('react/lib/log-events').logEvents(flowFn); // pass flowFn or react
65
+ react.logEvents(flowFn, eventWildcard); //log events on flowfn matching wildcard
59
66
 
60
67
  @param flowFn Flow function or global react object
68
+ @param eventWildcard wildcarded event type, if not provided use flow.* and task.*
61
69
  */
62
- function logEvents(flowFn) {
63
- //output events as tasks start and complete
64
- flowFn.events.removeListener(ALL_FLOW_EVENTS, flowLog);
65
- flowFn.events.on(ALL_FLOW_EVENTS, flowLog);
66
- flowFn.events.removeListener(ALL_TASK_EVENTS, taskLog);
67
- flowFn.events.on(ALL_TASK_EVENTS, taskLog);
70
+ function logEvents(flowFn, eventWildcard) {
71
+ if (!flowFn) flowFn = react; // use global
72
+ if (eventWildcard && eventWildcard !== '*') {
73
+ var logFn = (FLOW_RE.test(eventWildcard)) ? flowLog : taskLog;
74
+ flowFn.events.removeListener(eventWildcard, logFn);
75
+ flowFn.events.on(eventWildcard, logFn);
76
+ } else { // none provided, use flow.* and task.*
77
+ //output events as tasks start and complete
78
+ flowFn.events.removeListener(ALL_FLOW_EVENTS, flowLog);
79
+ flowFn.events.on(ALL_FLOW_EVENTS, flowLog);
80
+ flowFn.events.removeListener(ALL_TASK_EVENTS, taskLog);
81
+ flowFn.events.on(ALL_TASK_EVENTS, taskLog);
82
+ }
68
83
  }
69
84
 
70
85
  module.exports = react;
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
 
13
- var react = require('./'); // require('react');
13
+ var react = require('../'); // require('react');
14
14
 
15
15
  var PROMISE_SUFFIX = '__promise'; // added to param names that are promises
16
16
 
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
- return (fn) ?
131
- ((fn.name) ? fn.name : fn) : // if defined, try name, otherwise toString()
132
- 'undefined'; // not defined, use undefined
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
  }
@@ -13,70 +13,16 @@
13
13
  - emits task.complete with task
14
14
  - emits flow complete with flowEnv
15
15
  - emits flow errored with flowEnv
16
- */
17
-
18
-
19
- var react = require('../'); // require('react');
20
-
21
- var TASK_EVENTS_RE = /^task\./;
22
- var FLOW_EVENTS_RE = /^flow\./;
23
-
24
- /**
25
- Accumulator to make it easy to capture events
26
-
27
- @example
28
- var EventCollector = require('react/lib/track-tasks').EventCollector;
29
- var collector = new EventCollector();
30
-
31
- collector.captureGlobal('*'); // capture all react events for all flows
32
-
33
- // OR
34
-
35
- collector.capture(flowFn, 'task.'); // capture task events on a flow
36
- collector.capture(flowFn, 'flow.'); // add capture flow events on a flow
37
16
 
38
- var events = collector.list(); // retrieve the list of events
17
+ @example
18
+ var react = require('react');
19
+ react.trackTasks(); // enable task and flow tracking
39
20
  */
40
- function EventCollector() {
41
- this.events = [];
42
- }
43
21
 
44
- /**
45
- register listener to capture all events
46
- @param eventId event id or wildcarded id
47
- */
48
- EventCollector.prototype.captureGlobal = function (eventId) {
49
- this.capture(react, eventId);
50
- };
51
-
52
- /**
53
- register listener to capture events for a specific flow
54
- @param flowFn the react flow function or can pass global react
55
- @param eventId event id or wildcarded id
56
- */
57
- EventCollector.prototype.capture = function (flowFn, eventId) {
58
- var emitter = flowFn.events;
59
- var self = this;
60
- function accumEvents(obj) {
61
- var eventObject = {
62
- event: this.event,
63
- time: Date.now()
64
- };
65
- if (FLOW_EVENTS_RE.test(this.event)) {
66
- eventObject.env = obj;
67
- } else if (TASK_EVENTS_RE.test(this.event)) {
68
- eventObject.task = obj;
69
- }
70
- self.events.push(eventObject);
71
- }
72
- emitter.on(eventId, accumEvents);
73
- };
74
22
 
75
- EventCollector.prototype.list = function () {
76
- return this.events;
77
- };
23
+ var react = require('../'); // require('react');
78
24
 
79
- react.events.on(react.events.TYPES.EXEC_FLOW_START, function (env){
25
+ react.events.on(react.events.TYPES.EXEC_FLOW_START, function (env) {
80
26
  env.startTime = Date.now();
81
27
  env.flowEmitter.emit(react.events.TYPES.FLOW_BEGIN, env); //fire public ev
82
28
  });
@@ -111,7 +57,4 @@ react.events.on(react.events.TYPES.EXEC_FLOW_ERRORED, function (env) {
111
57
  });
112
58
 
113
59
 
114
-
115
-
116
60
  module.exports = react; // return react
117
- module.exports.EventCollector = EventCollector;