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
Binary file
@@ -0,0 +1,19 @@
1
+ digraph simple {
2
+ inputs [shape=box];
3
+ loadFoo [shape=box];
4
+ loadBar [shape=box];
5
+ render [shape=box];
6
+ outputs[shape=box];
7
+ inputs -> fooPath;
8
+ inputs -> barPath;
9
+ inputs -> barP2;
10
+ fooPath -> loadFoo;
11
+ loadFoo -> foo;
12
+ barPath -> loadBar;
13
+ loadBar -> bar;
14
+ barP2 -> loadBar;
15
+ foo -> render;
16
+ bar -> render;
17
+ render -> renderedOut;
18
+ renderedOut -> outputs;
19
+ }
Binary file
@@ -1,22 +1,49 @@
1
1
  'use strict';
2
2
  /*jshint white: false */
3
3
 
4
+ /**
5
+ Default DSL, showing use of events
6
+ */
7
+
4
8
  var react = require('../'); // require('react');
9
+ require('../lib/track-tasks'); // require('react/lib/track-tasks'); // turn on tracking
5
10
 
6
11
  //output events as tasks start and complete
7
- react.events.on('*', function (obj) {
12
+ react.events.on('flow.*', function (obj) {
13
+ /*jshint validthis: true */
8
14
  var time = new Date();
9
15
  time.setTime(obj.time);
16
+ var argsNoCb = obj.args.filter(function (a) { return (typeof(a) !== 'function'); });
10
17
  var eventTimeStr = time.toISOString();
18
+ if (this.event === 'flow.complete') {
19
+ var env = obj;
20
+ console.error('%s: %s \tmsecs:(%s) \n\targs:(%s) \n\tresults:(%s)\n',
21
+ this.event, env.name, env.elapsedTime, argsNoCb, env.results);
22
+ } else {
23
+ var name = obj.name;
24
+ var args = obj.args;
25
+ console.error('%s: %s \n\targs:(%s)\n', this.event, name, argsNoCb);
26
+ }
27
+ });
28
+
29
+ react.events.on('task.*', function (obj) {
30
+ /*jshint validthis: true */
31
+ var time = new Date();
32
+ time.setTime(obj.time);
11
33
  var argsNoCb = obj.args.filter(function (a) { return (typeof(a) !== 'function'); });
12
- if (obj.event === 'task.complete') {
34
+ var eventTimeStr = time.toISOString();
35
+ if (this.event === 'task.complete') {
36
+ var task = obj;
13
37
  console.error('%s: %s \tmsecs:(%s) \n\targs:(%s) \n\tresults:(%s)\n',
14
- obj.event, obj.name, obj.elapsedTime, argsNoCb, obj.results);
38
+ this.event, task.name, task.elapsedTime, argsNoCb, task.results);
15
39
  } else {
16
- console.error('%s: %s \n\targs:(%s)\n', obj.event, obj.name, argsNoCb);
40
+ var name = obj.name;
41
+ var args = obj.args;
42
+ console.error('%s: %s \n\targs:(%s)\n', this.event, name, argsNoCb);
17
43
  }
18
44
  });
19
-
45
+
46
+
20
47
 
21
48
  function loadUser(uid, cb){ setTimeout(cb, 100, null, "User"+uid); }
22
49
  function loadFile(filename, cb){ setTimeout(cb, 100, null, 'Filedata'+filename); }
@@ -43,7 +70,7 @@ var loadAndSave = react('loadAndSave', 'filename, uid, outDirname, cb -> err, ht
43
70
  writeOutput, 'html, user, cb -> err, bytesWritten', { after: prepareDirectory }, // only after prepareDirectory done
44
71
  loadEmailTemplate, 'cb -> err, emailmd',
45
72
  markdown, 'emailmd -> emailHtml', // using a sync function
46
- customizeEmail, 'user, emailHtml -> err, custEmailHtml', // sync fn
73
+ customizeEmail, 'user, emailHtml -> custEmailHtml', // sync fn
47
74
  deliverEmail, 'custEmailHtml, cb -> err, deliveredEmail', { after: writeOutput } // only after writeOutput is done
48
75
  );
49
76
 
@@ -1,6 +1,13 @@
1
1
  'use strict';
2
+ /*jshint white: false */
3
+
4
+ /**
5
+ Default DSL, showing use of events
6
+ */
2
7
 
3
8
  var react = require('../'); // require('react');
9
+ react.logEvents(); // turn on logging of all flow and task events for all react functions
10
+
4
11
 
5
12
  function loadUser(uid, cb){ setTimeout(cb, 100, null, "User"+uid); }
6
13
  function loadFile(filename, cb){ setTimeout(cb, 100, null, 'Filedata'+filename); }
@@ -8,28 +15,28 @@ function markdown(filedata) { return 'html'+filedata; }
8
15
  function prepareDirectory(outDirname, cb){ setTimeout(cb, 200, null, 'dircreated-'+outDirname); }
9
16
  function writeOutput(html, user, cb){ setTimeout(cb, 300, null, html+'_bytesWritten'); }
10
17
  function loadEmailTemplate(cb) { setTimeout(cb, 50, null, 'emailmd'); }
11
- function customizeEmail(user, emailHtml, cb) { return 'cust-'+user+emailHtml; }
18
+ function customizeEmail(user, emailHtml) { return 'cust-'+user+emailHtml; }
12
19
  function deliverEmail(custEmailHtml, cb) { setTimeout(cb, 100, null, 'delivered-'+custEmailHtml); }
13
20
 
14
21
  function useHtml(err, html, user, bytesWritten) {
15
- if(err) {
22
+ if (err) {
16
23
  console.log('***Error: %s', err);
17
24
  return;
18
25
  }
19
26
  console.log('final result: %s, user: %s, written:%s', html, user, bytesWritten);
20
27
  }
21
28
 
22
- var loadAndSave = react.fstrDefine('filename, uid, outDirname, cb', [ // input params
23
- loadUser, 'uid -> err, user', // calling async fn loadUser with uid, callback is called with err and user
24
- loadFile, 'filename -> err, filedata',
25
- markdown, 'filedata -> returns html', // using a sync function
26
- prepareDirectory, 'outDirname -> err, dircreated',
27
- writeOutput, 'html, user -> err, bytesWritten', { after: prepareDirectory }, // only after prepareDirectory done
28
- loadEmailTemplate, ' -> err, emailmd',
29
- markdown, 'emailmd -> returns emailHtml', // using a sync function
30
- customizeEmail, 'user, emailHtml -> returns custEmailHtml',
31
- deliverEmail, 'custEmailHtml -> err, deliveredEmail', { after: writeOutput } // only after writeOutput is done
32
- ], 'err, html, user, bytesWritten'); // callback output params
29
+ var loadAndSave = react('loadAndSave', 'filename, uid, outDirname, cb -> err, html, user, bytesWritten', // name, in/out params
30
+ loadUser, 'uid, cb -> err, user', // calling async fn loadUser with uid, callback is called with err and user
31
+ loadFile, 'filename, cb -> err, filedata',
32
+ markdown, 'filedata -> html', // using a sync function
33
+ prepareDirectory, 'outDirname, cb -> err, dircreated',
34
+ writeOutput, 'html, user, cb -> err, bytesWritten', { after: prepareDirectory }, // only after prepareDirectory done
35
+ loadEmailTemplate, 'cb -> err, emailmd',
36
+ markdown, 'emailmd -> emailHtml', // using a sync function
37
+ customizeEmail, 'user, emailHtml -> custEmailHtml', // sync fn
38
+ deliverEmail, 'custEmailHtml, cb -> err, deliveredEmail', { after: writeOutput } // only after writeOutput is done
39
+ );
33
40
 
34
41
  loadAndSave('file.md', 100, '/tmp/foo', useHtml); // executing the flow
35
42
 
@@ -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
+ });
package/lib/base-task.js CHANGED
@@ -19,17 +19,18 @@ BaseTask.prototype.isComplete = function () {
19
19
  };
20
20
 
21
21
  BaseTask.prototype.start = function (args) { // mark task as started with args and note time
22
+ /*jshint validthis: true */
22
23
  this.args = args;
23
- this.startTime = Date.now();
24
- if (this.flowEmitter) this.flowEmitter.emitObject(EventManager.TYPES.TASK_BEGIN, this);
24
+ this.env.currentTask = this;
25
+ this.env.flowEmitter.emit(EventManager.TYPES.EXEC_TASK_START, this);
25
26
  };
26
27
 
27
28
  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);
29
+ /*jshint validthis: true */
32
30
  this.status = STATUS.COMPLETE;
31
+ this.results = args;
32
+ this.env.currentTask = this;
33
+ this.env.flowEmitter.emit(EventManager.TYPES.EXEC_TASK_COMPLETE, this);
33
34
  };
34
35
 
35
36
  BaseTask.prototype.functionExists = function (vCon) {
@@ -96,6 +97,7 @@ BaseTask.prototype.isReady = function (vCon, tasksByName) {
96
97
  };
97
98
 
98
99
  BaseTask.prototype.isMethodCall = function () {
100
+ /*jshint regexp: false */
99
101
  return (typeof(this.f) === 'string' && /^.*\..*$/.test(this.f)); //str contains .
100
102
  };
101
103
 
package/lib/cb-task.js CHANGED
@@ -43,6 +43,19 @@ CbTask.validate = function (taskDef) {
43
43
  return errors;
44
44
  };
45
45
 
46
+ CbTask.prototype.prepare = function prepare(handleTaskError, vCon, contExec) {
47
+ var self = this;
48
+ this.cbFun = function (err, arg0, arg1, argn) {
49
+ var args = Array.prototype.slice.call(arguments, 1);
50
+ if (err) { handleTaskError(self, err); return; } //handle error and return, we are done
51
+
52
+ //no error, save callback args to vCon context, then continue execution
53
+ vCon.saveResults(self.out, args);
54
+ self.complete(args);
55
+ contExec();
56
+ };
57
+ };
58
+
46
59
  CbTask.prototype.exec = function exec(vCon, handleError, contExec) {
47
60
  try {
48
61
  var args = this.a.map(function (k) { return vCon.getVar(k); }); //get args from vCon
@@ -51,7 +64,7 @@ CbTask.prototype.exec = function exec(vCon, handleError, contExec) {
51
64
  this.start(args); //note the start time, args
52
65
  args.push(this.cbFun); // push callback fn on end
53
66
  var func = this.f;
54
- var bindObj = null; //global space
67
+ var bindObj = vCon.getVar('this'); //global space or the original this
55
68
  if (this.isMethodCall()) { //if method call then reset func and bindObj
56
69
  func = vCon.getVar(this.f);
57
70
  bindObj = this.getMethodObj(vCon);
package/lib/core.js CHANGED
@@ -7,7 +7,6 @@ var validate = require('./validate.js');
7
7
  var tskutil = require('./task.js');
8
8
  var STATUS = require('./status.js');
9
9
  var VContext = require('./vcon.js');
10
- var FinalCbTask = require('./finalcb-task.js');
11
10
  var EventManager = require('./event-manager.js');
12
11
  var inputParser = require('./input-parser.js');
13
12
  var idGenerator = require('./id.js');
@@ -16,7 +15,17 @@ var reactOptions = {
16
15
  stackTraceLimitMin: 30
17
16
  };
18
17
 
19
- var reactEmitter = EventManager.globalEventManager; // the top emitter
18
+ var reactEmitter = EventManager.global; // the top emitter
19
+
20
+ /**
21
+ merge global react options with parsed options
22
+ */
23
+ function mergeOptions(parsedOptions) {
24
+ return Object.keys(reactOptions).reduce(function (accum, k) {
25
+ if (!accum[k]) accum[k] = reactOptions[k];
26
+ return accum;
27
+ }, parsedOptions);
28
+ }
20
29
 
21
30
  /**
22
31
  Creates react function which the AST can be manipulated and then
@@ -56,32 +65,54 @@ function reactFactory() {
56
65
  Object.keys(newAST).forEach(function (k) { ast[k] = newAST[k]; }); // copy all properties
57
66
  var errors = validate(ast);
58
67
  if (!errors.length) tskutil.nameTasks(ast.tasks); //run this so names can be checked in ast
68
+ if (Object.freeze) { //lets freeze the AST so plugin writers don't accidentally manip the ast
69
+ Object.keys(newAST).forEach(function (k) {
70
+ if (typeof(newAST[k]) === 'object') Object.freeze(newAST[k]);
71
+ });
72
+ Object.freeze(newAST);
73
+ }
59
74
  return errors;
60
75
  }
61
76
 
62
77
  function exec(arg1, arg2, argN, cb) { // called to execute the flow
63
- var parsedInput = inputParser(Array.prototype.slice.call(arguments), ast);
64
- var args = parsedInput.args;
65
- var cbFinal = parsedInput.cb;
66
- var extraArgs = parsedInput.extraArgs; // we'll have these if we need them
67
- var vCon = VContext.create(args, ast.inParams, ast.locals); // create var ctx with in args & locals
68
- var tasks = ast.tasks.map(tskutil.create);
78
+ /*jshint validthis: true */
79
+ var args = Array.prototype.slice.call(arguments);
80
+ var env = {
81
+ execId: idGenerator.createUniqueId(),
82
+ args: args,
83
+ ast: ast,
84
+ flowEmitter: flowEmitter
85
+ };
86
+ env.name = ast.name || env.execId;
87
+ flowEmitter.emit(EventManager.TYPES.EXEC_FLOW_START, env); // hook
88
+ var parsedInput = inputParser(args, ast);
89
+ var vCon = VContext.create(parsedInput.args, ast.inParams, ast.locals, this); // create var ctx with in args & locals
90
+
91
+ env.parsedInput = parsedInput;
92
+ env.options = mergeOptions(parsedInput.options);
93
+ env.vCon = vCon;
94
+ env.taskDefs = ast.tasks.slice(); // create copy
95
+ env.outTaskDef = Object.create(ast.outTask); // create copy
96
+ reactEmitter.emit(EventManager.TYPES.EXEC_TASKS_PRECREATE, env); // hook
97
+
98
+ var tasks = env.taskDefs.map(tskutil.create);
69
99
  var tasksByName = tskutil.nameTasks(tasks); // map names to working tasks
70
- var outTask = tskutil.createOutTask(ast.outTask, cbFinal, tasks, vCon);
100
+ var outTask = tskutil.createOutTask(env.outTaskDef, parsedInput.cb, tasks, vCon, env.options, env);
71
101
  var handleError = tskutil.createErrorHandler(vCon, outTask);
72
102
 
73
103
  function contExec() {
74
104
  if (!outTask.f) { return; } //stop execution, we already hit an error, f was cleared
75
105
  if (outTask.isReady()) return outTask.exec(); // all tasks done, exec cb, return
76
- tskutil.findReadyAndExec(vCon, tasks, tasksByName, handleError, contExec); //exec tasks that ready to run
106
+ tskutil.findReadyAndExec(vCon, tasks, tasksByName, handleError, contExec, env); //exec tasks that ready to run
77
107
  }
78
108
 
79
109
  tasks.forEach(function (t) {
80
110
  t.id = idGenerator.createUniqueId();
81
- t.flowEmitter = flowEmitter;
82
- if (t.type === 'cb') t.cbFun = tskutil.createCallback(t, handleError, vCon, contExec, flowEmitter);
111
+ t.env = env;
112
+ if (t.prepare) t.prepare(handleError, vCon, contExec, flowEmitter);
83
113
  }); // create callbacks
84
114
  contExec(); // start things off
115
+ return outTask.retValue; // could return promise
85
116
  }
86
117
 
87
118
  var reactFn = exec; // make the exec() the function returned
package/lib/dsl.js CHANGED
@@ -6,8 +6,10 @@ var core = require('./core.js');
6
6
  var parse = require('./parse.js');
7
7
  var tutil = require('./task.js');
8
8
 
9
- var MISSING_NAME = 'param[0] should be the flow name, instead found in/out def: %s';
10
- var INOUT_PARAMS_NO_MATCH = 'params in wrong format, wanted "foo, bar cb -> err, baz" - found: %s';
9
+ var MISSING_NAME = 'first flow parameter should be the flow name, but found in/out def: %s';
10
+ var INOUT_PARAMS_NO_MATCH = 'params in wrong format, wanted "foo, bar, cb -> err, baz" - found: %s';
11
+ var MISSING_ERR = 'callback specified, but first out param was not "err", use for clarity. Found in/out def: %s';
12
+ var MISSING_CB = 'found err param, but cb/callback is not specified, is this cb-style async or sync function? Found in/out def: %s';
11
13
  var EXTRA_TASKARG = 'extra unmatched task arg: %s';
12
14
 
13
15
  var INOUT_RE = /\->/; // used to detect missing name, in/out as first arg
@@ -25,12 +27,18 @@ function filterOutLeadingErrParam(args) { // if leading err param, filter it out
25
27
  }
26
28
 
27
29
  var inOutDefParse = {
28
- regex: /^([^\-]*)(->\s*(.*))?$/i,
29
- fn: function (m) {
30
- var inParams = parse.splitTrimFilterArgs(m[1]);
30
+ splitStr: '->',
31
+ fn: function (m, origStr) {
32
+ var inParams = parse.splitTrimFilterArgs(m[0]);
31
33
  var lastParam = inParams[inParams.length - 1];
32
34
  var type = (lastParam && CB_NAMES_RE.test(lastParam)) ? 'cb' : 'ret';
33
- var outParams = parse.splitTrimFilterArgs(m[3]);
35
+ var outParams = parse.splitTrimFilterArgs(m[1]);
36
+ var firstOutParam = outParams[0];
37
+ if (type === 'cb' && (!firstOutParam || !ERR_NAMES_RE.test(firstOutParam))) {
38
+ throw new Error(sprintf(MISSING_ERR, origStr)); // found cb, but no err param
39
+ } else if (type === 'ret' && firstOutParam && ERR_NAMES_RE.test(firstOutParam)) {
40
+ throw new Error(sprintf(MISSING_CB, origStr)); // found err but not cb param
41
+ }
34
42
  return {
35
43
  type: type,
36
44
  inDef: filterOutTrailingCbParam(inParams),
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ var react = require('../'); // require('react');
4
+ react.trackTasks(); // enable task tracking
5
+
6
+ var TASK_EVENTS_RE = /^task\./;
7
+ var FLOW_EVENTS_RE = /^flow\./;
8
+
9
+ /**
10
+ Accumulator to make it easy to capture events
11
+
12
+ @example
13
+ var EventCollector = require('react/lib/event-collector');
14
+ var collector = new EventCollector();
15
+
16
+ collector.capture(); // capture all flow and task events for all react flows
17
+ collector.capture('flow.*'); // capture all flow events for all react flows
18
+ collector.capture(flowFn, 'task.*'); // capture task events on a flow
19
+ collector.capture(flowFn, 'flow.*'); // add capture flow events on a flow
20
+
21
+ var events = collector.list(); // retrieve the list of events
22
+ collector.clear(); // clear the list of events;
23
+ */
24
+ function EventCollector() {
25
+ this.events = [];
26
+ }
27
+
28
+ /**
29
+ register listener to capture events for a specific flow
30
+ @param flowFn the react flow function or can pass global react
31
+ @param eventId event id or wildcarded id
32
+ */
33
+ EventCollector.prototype.capture = function (flowFn, eventId) {
34
+ /*jshint validthis: true */
35
+ if (!eventId && typeof(flowFn) === 'string') { // only eventId provided
36
+ eventId = flowFn;
37
+ flowFn = react; // global react
38
+ } else if (!flowFn) flowFn = react; // global react
39
+ if (!eventId) eventId = '*'; // default to all
40
+ var emitter = flowFn.events;
41
+ var self = this;
42
+ function accumEvents(obj) {
43
+ var eventObject = {
44
+ event: this.event,
45
+ time: Date.now()
46
+ };
47
+ if (FLOW_EVENTS_RE.test(this.event)) {
48
+ eventObject.env = obj;
49
+ } else if (TASK_EVENTS_RE.test(this.event)) {
50
+ eventObject.task = obj;
51
+ }
52
+ self.events.push(eventObject);
53
+ }
54
+ emitter.on(eventId, accumEvents);
55
+ };
56
+
57
+ EventCollector.prototype.list = function () {
58
+ return this.events;
59
+ };
60
+
61
+ EventCollector.prototype.clear = function () {
62
+ this.events = []; // clear
63
+ };
64
+
65
+ module.exports = EventCollector;