Comparing version 0.1.13 to 0.2.0
@@ -0,56 +1,66 @@ | ||
var util = require('util'); | ||
var async = require('async'); | ||
var us = require('underscore'); | ||
var errors = require('errors'); | ||
var FlowTaskError = require('./flowTaskError'); | ||
var FlowTaskArgumentNullError = require('./flowTaskArgumentNullError'); | ||
var Task = require('./flowTask').Task; | ||
var AsyncTask = require('./flowTask').AsyncTask; | ||
var SyncTask = require('./flowTask').SyncTask; | ||
module.exports = { | ||
flow: function flow(data, tasks, callback){ | ||
if(arguments.length == 2){ | ||
if(typeof tasks == 'function'){ | ||
callback = tasks; | ||
tasks = data; | ||
data = undefined; | ||
} | ||
} else if(arguments.length == 1){ | ||
var workflow = new Workflow(data, tasks, callback); | ||
workflow.execute(); | ||
} | ||
} | ||
var Workflow = function Workflow(data, tasks, callback){ | ||
if(arguments.length == 2){ | ||
if(typeof tasks == 'function'){ | ||
callback = tasks; | ||
tasks = data; | ||
callback = undefined; | ||
data = undefined; | ||
} | ||
} else if(arguments.length == 1){ | ||
tasks = data; | ||
callback = undefined; | ||
data = undefined; | ||
} | ||
flowExec(data, tasks, null, callback); | ||
} | ||
this.data = data; | ||
this.tasks = tasks; | ||
this.callback = callback || function(){}; | ||
} | ||
var flowExec = function flowExec(data, tasks, contextName, callback) { | ||
if (data instanceof Array) { | ||
return async.map(data, function (dataItem, cb) { | ||
var context; | ||
if(contextName) context = dataItem[contextName] | ||
flowGo(dataItem, tasks, context, function(err, results){ | ||
if(contextName) cb(err, us.pick(results, Object.keys(tasks))); | ||
else cb(err, results); | ||
}) | ||
}, callback); | ||
} else { | ||
Workflow.prototype.execute = function execute(contextName) { | ||
var self = this; | ||
self.contextName = contextName; | ||
var exec = function(data, cb){ | ||
var context; | ||
if(contextName) context = data[contextName]; | ||
return flowGo(data, tasks, context, function(err, results){ | ||
if(contextName) callback(err, us.pick(results, Object.keys(tasks))); | ||
else callback(err, results); | ||
var newTasks; | ||
if(data) newTasks = us.object(Object.keys(data), us.map(Object.keys(data), function(key){ return function(cb){ cb(null, data[key]); } })) | ||
if(context) us.extend(newTasks, us.object(Object.keys(context), us.map(Object.keys(context), function(key){ return function(cb){ cb(null, context[key]); } }))); | ||
if(self.tasks) us.extend(newTasks, us.object(Object.keys(self.tasks), us.map(Object.keys(self.tasks), function(taskName){ | ||
var taskPlan = self.interpretTask(taskName, data, context); | ||
return self.executeTaskPlan(taskPlan, taskName); | ||
} ))); | ||
return async.auto(newTasks, function(err, results){ | ||
if(contextName) cb(err, us.pick(results, Object.keys(self.tasks))); | ||
else cb(err, results); | ||
}); | ||
} | ||
} | ||
}; | ||
var flowGo = function flowGo(data, tasks, context, callback) { | ||
var newTasks; | ||
if(data) newTasks = us.object(Object.keys(data), us.map(Object.keys(data), function(key){ return function(cb){ cb(null, data[key]); } })) | ||
if(context) us.extend(newTasks, us.object(Object.keys(context), us.map(Object.keys(context), function(key){ return function(cb){ cb(null, context[key]); } }))); | ||
if(tasks) us.extend(newTasks, us.object(Object.keys(tasks), us.map(Object.keys(tasks), function(key){ | ||
var taskPlan = interpretTask(tasks[key], key, tasks, data, context); | ||
return flowCall(taskPlan, key); | ||
} ))); | ||
return async.auto(newTasks, callback); | ||
if (this.data instanceof Array) async.map(this.data, exec, this.callback); | ||
else exec(this.data, this.callback); | ||
} | ||
var interpretTask = function interpretTask(taskArgs, taskName, tasks, data, context) { | ||
Workflow.prototype.interpretTask = function interpretTask(taskName, data, context) { | ||
var self = this; | ||
var taskArgs = Array.isArray(self.tasks[taskName]) ? new AsyncTask(self.tasks[taskName]) : self.tasks[taskName]; | ||
this.tasks[taskName] = taskArgs; | ||
var tasks = self.tasks; | ||
var fn; //function to call within each async.auto task (does the work). | ||
@@ -60,10 +70,11 @@ var fnIndex; //index where fn was found. | ||
var autoTask = []; //array value for each async.auto task | ||
var task = taskArgs instanceof Task ? taskArgs : null; | ||
var interpretSubFlow = function(subFlow){ | ||
if(fn) throw new FlowTaskError(taskName, "A task may have a SubFlow (index " + i + ") or a function call (index " + i + "), but not both. " + fnIndex + " and " + i + ")."); | ||
if(Array.isArray(taskArgs) && i < taskArgs.length - 1) throw new FlowTaskError(taskName, "SubFlows must be the at the last index."); | ||
if(taskArgs instanceof Task && i < taskArgs.task_array.length - 1) throw new FlowTaskError(taskName, "SubFlows must be at the last index."); | ||
if(!tasks.hasOwnProperty(subFlow.dataName) && (!data || !data.hasOwnProperty(subFlow.dataName)) || subFlow.dataName == taskName) throw new FlowTaskError(taskName, "SubFlow data '" + subFlow.dataName + "' does not exist. Provide the name of a task or data from the parent flow. Possible values include: " + Object.keys(tasks).concat(Object.keys(data)).filter(function(name){ return name != taskName }).join(', ')); | ||
fn = { receiverName: subFlow.dataName, tasks: subFlow.tasks }; | ||
var prereqs = scanForPrereqs(subFlow.tasks, us.extend({}, data, tasks)); | ||
autoTask.push(subFlow.dataName); | ||
autoTask.push(subFlow.dataName); | ||
autoTask = autoTask.concat(Object.keys(prereqs)); | ||
@@ -76,5 +87,10 @@ } | ||
fn = taskArgs; | ||
} else if(Array.isArray(taskArgs)) { | ||
for(var i in taskArgs) { | ||
var taskArg = taskArgs[i]; | ||
} else if(task) { | ||
task.name = taskName; | ||
task.workflow = self; | ||
task.task_requirements = []; | ||
task.data_requirements = []; | ||
// task.context_requirements = []; | ||
for(var i in task.task_array) { | ||
var taskArg = task.task_array[i]; | ||
if(typeof taskArg == 'function') { | ||
@@ -90,15 +106,15 @@ if(fn) throw new FlowTaskError(taskName, "More than one function specified (at index " + fnIndex + " and " + i + ")."); | ||
taskArg = taskArgParts[0]; | ||
if((tasks.hasOwnProperty(taskArg) || data && data.hasOwnProperty(taskArg) || context && context.hasOwnProperty(taskArg) && typeof context[taskArg] != 'function') && taskArg != taskName) { | ||
if(fn) args.push(taskArgParts); | ||
var auto_task_type = tasks.hasOwnProperty(taskArg) && 'task' || data && data.hasOwnProperty(taskArg) && 'data' || context && context.hasOwnProperty(taskArg) && typeof context[taskArg] != 'function' && 'context'; | ||
if(taskArg == taskName) auto_task_type = null; | ||
if(auto_task_type) { | ||
if(fn) args.push(taskArgParts); //there's already a fn, so assume that 'foo.bar.baz' must be a parameter to fn. | ||
else if(taskArgParts.length > 1) { | ||
fn = { name: taskArgParts.pop(), receiverName: taskArgParts }; | ||
fn = { name: taskArgParts.pop(), receiverName: taskArgParts }; //there's no fn yet, so assume that 'foo.bar.baz' means baz must be a function to execute on foo.bar | ||
fnIndex = i; | ||
} | ||
if(auto_task_type == 'task') task.task_requirements.push(taskArg); | ||
else if(auto_task_type == 'data' || auto_task_type == 'context') task.data_requirements.push(taskArg); | ||
//else if(auto_task_type == 'context') task.context_requirements.push(taskArg); | ||
autoTask.push(taskArg); | ||
} else if(fn) throw new FlowTaskError(taskName, "More than one function specified (at index " + fnIndex + " and " + i + ")."); | ||
else if(taskArgParts.length > 1 || !taskArgs[i - 1]) throw new FlowTaskError(taskName, "Unknown symbol at index '" + i + "' must be either the name of a task, the name of data, or be the name of a function on the result of a task or data"); | ||
else { | ||
fn = { name: taskArg, receiverName: taskArgs[i - 1] }; | ||
fnIndex = i; | ||
} | ||
} else throw new FlowTaskError(taskName, "Unknown string '" + taskArg + "' must be either the name of a task or the name of data"); | ||
} else throw new FlowTaskError(taskName, "Unknown symbol at index '" + i + "' must be either the name of a task, the name of data, or be the name of a function on the result of a task or data"); | ||
@@ -108,12 +124,14 @@ } | ||
} else { | ||
throw new FlowTaskError(taskName, "Invalid flow type. Must be function, or array."); | ||
throw new FlowTaskError(taskName, "Invalid flow type. Must be function, subFlow, or array."); | ||
} | ||
return { fn: fn, args: args, autoTask: autoTask }; | ||
return { fn: fn, args: args, autoTask: autoTask, task: task, isSync: (task instanceof SyncTask) }; | ||
} | ||
var flowCall = function flowCall(taskPlan, taskName) { | ||
Workflow.prototype.executeTaskPlan = function executeTaskPlan(taskPlan, taskName){ | ||
var self = this; | ||
var fn = taskPlan.fn; | ||
var args = taskPlan.args; | ||
var autoTask = taskPlan.autoTask; | ||
var task = taskPlan.task; | ||
@@ -135,26 +153,46 @@ if(typeof fn == 'object' && fn.tasks) { //subflows | ||
} | ||
flowExec(newData, fn.tasks, fn.receiverName, cb); | ||
var sub_workflow = new Workflow(newData, fn.tasks, cb); | ||
sub_workflow.parent = self; | ||
sub_workflow.execute(fn.receiverName); | ||
}); | ||
} else { | ||
autoTask.push(function(cb, results){ | ||
var fnArgs = []; | ||
for(var i in args) { | ||
var arg = args[i]; | ||
if(Array.isArray(arg)) { | ||
var result = results; | ||
for(var j in arg) { | ||
if(result === undefined) return cb(new FlowTaskArgumentNullError(taskName, arg[j-1], arg[j])); | ||
result = result[arg[j]]; | ||
} | ||
fnArgs[i] = result; | ||
} else fnArgs[i] = results[arg]; | ||
autoTask.push(function(callback, results){ | ||
var cb = function(err, result){ | ||
if(err && err.name == "ArgumentNullError" && self.tasks[err.argumentName]) err.message = "Not Found: " + self.tasks[err.argumentName].toString(results) | ||
if(err) return callback(err); | ||
if(arguments.length > 2) result = Array.prototype.slice.call(arguments, 1); | ||
if(task) return Task.complete.call(task, result, results, callback); | ||
else callback(null, result); | ||
}; | ||
var fnArgs; | ||
try { | ||
//we will generate the list of args to apply to the fn. | ||
fnArgs = args.map(function(arg){ | ||
return evalMessages(results, arg, taskName); | ||
}); | ||
} catch(e) { | ||
if(e.name == "FlowTaskArgumentNullError") { | ||
e = new errors.ArgumentNull(e.argumentName); | ||
e.message = "Not Found: " + self.tasks[taskName].toString(results, e.argumentName); | ||
} | ||
return callback(e); | ||
} | ||
fnArgs.push(cb); | ||
if(!taskPlan.isSync) fnArgs.push(cb); | ||
var receiver; | ||
if(typeof fn != 'function') { | ||
var fnName = fn.name; | ||
var receiverName = fn.receiverName; | ||
receiver = results[receiverName]; | ||
var fnName = fn.name; | ||
if(!receiver) return cb(new FlowTaskArgumentNullError(taskName, receiverName, fnName)); | ||
try { | ||
receiver = evalMessages(results, receiverName, taskName); | ||
} catch(e) { | ||
if(e.name == "FlowTaskArgumentNullError") e.message = "Not Found: " + self.tasks[taskName].toString(results, e.argumentName); | ||
return callback(e); | ||
} | ||
if(!receiver) { | ||
var err = new errors.ArgumentNull(receiverName.join('.')); | ||
if(self.tasks[receiverName[0]]) err.message = "Not Found: " + self.tasks[receiverName[0]].toString(results, err.argumentName); | ||
return callback(err) | ||
} | ||
fn = receiver[fnName]; | ||
@@ -165,3 +203,4 @@ if(!fn) throw new FlowTaskError(taskName, "Unknown symbol '" + fnName + "' must be either the name of a task, the name of data, or the name of a function on '" + receiverName + "'"); | ||
try { | ||
fn.apply(receiver, fnArgs); | ||
var return_value = fn.apply(receiver, fnArgs); | ||
if(taskPlan.isSync) cb(null, return_value); | ||
} catch(e){ | ||
@@ -176,2 +215,17 @@ throw new FlowTaskError(taskName, "Error during execution of function.", e); | ||
var evalMessages = function evalMessages(receiver, messages, taskName){ | ||
if(Array.isArray(messages)) { | ||
for(var i in messages) { | ||
if(receiver === undefined) { | ||
var receiverName = messages.slice(1,i).join('.'); | ||
var err = new FlowTaskArgumentNullError(taskName, messages[i-1], messages[i]); | ||
err.argumentName = receiverName; | ||
throw err; | ||
} | ||
receiver = receiver[messages[i]]; | ||
} | ||
return receiver; | ||
} else return receiver[messages]; | ||
} | ||
var scanForPrereqs = function scanForPrereqs(tasks, allTasks) { | ||
@@ -183,5 +237,5 @@ var prereqs = {}; | ||
us.extend(prereqs, scanForPrereqs(taskArgs.tasks, us.extend({}, allTasks, tasks))); | ||
} else if(Array.isArray(taskArgs)){ | ||
for(var i in taskArgs) { | ||
var taskArg = taskArgs[i]; | ||
} else if(taskArgs instanceof Task){ | ||
for(var i in taskArgs.task_array) { | ||
var taskArg = taskArgs.task_array[i]; | ||
if(taskArg instanceof SubFlow) { | ||
@@ -210,5 +264,20 @@ us.extend(prereqs, scanForPrereqs(taskArg.tasks, us.extend({}, allTasks, tasks))); | ||
if(!tasks) throw new Error("SubFlow error: No tasks given for subFlow."); | ||
if(typeof tasks == 'object') { | ||
for(var name in tasks) if(Array.isArray(tasks[name])) tasks[name] = new AsyncTask(tasks[name]); | ||
} | ||
}; | ||
module.exports.flow.subFlow = function(dataName, tasks) { | ||
return new SubFlow(dataName, tasks); | ||
}; | ||
}; | ||
module.exports.flow.asyncTask = function(task_array) { | ||
if(!(task_array instanceof Array)) task_array = us.values(arguments); | ||
return new AsyncTask(task_array); | ||
} | ||
module.exports.flow.syncTask = function(task_array) { | ||
if(!(task_array instanceof Array)) task_array = us.values(arguments); | ||
return new SyncTask(task_array); | ||
} | ||
@@ -6,3 +6,3 @@ { | ||
"author": "David Fenster <david@dfenster.com>", | ||
"version": "0.1.13", | ||
"version": "0.2.0", | ||
"repository": { | ||
@@ -9,0 +9,0 @@ "type": "git", |
@@ -1,5 +0,10 @@ | ||
var util = require('util'); | ||
var flow = require('../lib/fnFlow').flow; | ||
var us = require('underscore'); | ||
var test_data = require('../support/test-data'); | ||
Book = test_data.Book; | ||
Author = test_data.Author; | ||
Genre = test_data.Genre; | ||
BookSeries = test_data.BookSeries; | ||
module.exports.setUp = function(cb){ | ||
@@ -12,104 +17,2 @@ cb(); | ||
var bindFunctions = function(C){ | ||
for(var name in C){ | ||
var fn = C[name]; | ||
if(typeof fn == 'function') C[name] = fn.bind(C); | ||
} | ||
} | ||
BaseClass = function BaseClass(){}; | ||
BaseClass.getAll = function(cb){ return cb(null, this.all); } | ||
BaseClass.getByAttribute = function(attribute, value, cb){ | ||
var self = this; | ||
var o = self.all[us.find(Object.keys(self.all), function(id){ return self.all[id][attribute] == value; })]; | ||
return cb(null, o); | ||
} | ||
BaseClass.findByAttribute = function(attribute, value, cb){ | ||
var self = this; | ||
value = value && value.id || value; | ||
var results = us.map(us.filter(Object.keys(self.all), function(id){ return self.all[id][attribute] == value; }), function(o){ return self.all[o]; }); | ||
return cb(null, results); | ||
} | ||
BaseClass.getById = function(id, cb){ | ||
id = id && id.id || id; | ||
return cb(null, this.all[id]); | ||
} | ||
BaseClass.assertExistence = function(object, cb){ | ||
if(!object) return cb(new Error(this.name + " did not exist")); | ||
return cb(null, true); | ||
}; | ||
Genre = us.extend(function Genre(){}, BaseClass); | ||
util.inherits(Genre, BaseClass); | ||
Genre.getByName = function(name, cb){ return this.getByAttribute('name', name, cb); }; | ||
Genre.prototype.findBooksByAuthor = function(author, cb) { return Book.findByGenreAndAuthor(this, author, cb); } | ||
Genre.prototype.getBooks = function(cb){ return Book.findByGenreId(this.id, cb); } | ||
Genre.prototype.getGenre = function(cb){ return cb(null, this.id); } | ||
bindFunctions(Genre); | ||
Author = us.extend(function Author(){}, BaseClass); | ||
util.inherits(Author, BaseClass); | ||
Author.getByName = function(name, cb){ return this.getByAttribute('name', name, cb); }; | ||
Author.prototype.getBooks = function(cb){ return Book.findByAuthorId(this.id, cb); }; | ||
bindFunctions(Author); | ||
BookSeries = us.extend(function BookSeries(){}, BaseClass); | ||
util.inherits(BookSeries, BaseClass); | ||
BookSeries.getByName = function(name, cb){ return this.getByAttribute('name', name, cb); }; | ||
BookSeries.findByAuthorId = function(authorId, cb){ return BookSeries.findByAttribute('authorId', authorId, cb); }; | ||
bindFunctions(BookSeries); | ||
Book = us.extend(function Book(){}, BaseClass); | ||
util.inherits(Book, BaseClass); | ||
Book.getByTitle = function(title, cb){ return Book.getByAttribute('title', title, cb); }; | ||
Book.findBySeriesId = function(seriesId, cb){ return Book.findByAttribute('bookSeriesId', seriesId, cb); }; | ||
Book.findByAuthorId = function(authorId, cb){ return Book.findByAttribute('authorId', authorId, cb); }; | ||
Book.findByGenreId = function(genreId, cb){ return Book.findByAttribute('genreId', genreId, cb); }; | ||
Book.findByGenreAndAuthor = function(genreId, authorId, cb){ | ||
genreId = genreId && genreId.id || genreId; | ||
authorId = authorId && authorId.id || authorId; | ||
if(genreId == 5) return cb(new Error("this was a test")); | ||
cb(null, us.where(Book.all, {genreId: genreId, authorId: authorId})); | ||
}; | ||
Book.prototype.getAuthor = function(cb){ return Author.getById(this.authorId, cb); } | ||
bindFunctions(Book); | ||
Genre.all = { | ||
1: us.extend(new Genre(), {id: 1, name: "Fantasy", book_ids: [7,8,9,10,11]}), | ||
2: us.extend(new Genre(), {id: 2, name: "Romance"}), | ||
3: us.extend(new Genre(), {id: 3, name: "Fiction"}), | ||
4: us.extend(new Genre(), {id: 4, name: "Sports"}), | ||
5: us.extend(new Genre(), {id: 5, name: "???"}) | ||
} | ||
Author.all = { | ||
1: us.extend(new Author(), {id: 1, name: "Patricia Briggs"}), | ||
2: us.extend(new Author(), {id: 2, name: "Clive Cussler"}), | ||
3: us.extend(new Author(), {id: 3, name: "Tom Coughlin"}), | ||
4: us.extend(new Author(), {id: 4, name: "Dan Brown"}), | ||
5: us.extend(new Author(), {id: 5, name: "Robert Jordan"}), | ||
6: us.extend(new Author(), {id: 6, name: "Barbara Hambly"}) | ||
} | ||
BookSeries.all = { | ||
1: us.extend(new BookSeries(), {id: 1, name: "Mercy Thompson", authorId: 1}), | ||
2: us.extend(new BookSeries(), {id: 2, name: "The Wheel of Time", authorId: 5}), | ||
3: us.extend(new BookSeries(), {id: 3, name: "Sun-Cross", authorId: 6}) | ||
} | ||
Book.all = { | ||
1: us.extend(new Book(), {id: 1, title: "Frost Burned", authorId: 1, bookSeriesId: 1, genreId: 2}), | ||
2: us.extend(new Book(), {id: 2, title: "Moon Called", authorId: 1, bookSeriesId: 1, genreId: 2}), | ||
3: us.extend(new Book(), {id: 3, title: "River Marked", authorId: 1, bookSeriesId: 1, genreId: 2}), | ||
4: us.extend(new Book(), {id: 4, title: "The Striker", authorId: 2, genreId: 3}), | ||
5: us.extend(new Book(), {id: 5, title: "Earn the Right to Win", authorId: 3, genreId: 4}), | ||
6: us.extend(new Book(), {id: 6, title: "Inferno", authorId: 4, genreId: 3}), | ||
7: us.extend(new Book(), {id: 7, title: "The Rainbow Abyss", authorId: 6, bookSeriesId: 3, genreId: 1}), | ||
8: us.extend(new Book(), {id: 8, title: "The Magicians of Night", authorId: 6, bookSeriesId: 3, genreId: 1}), | ||
9: us.extend(new Book(), {id: 9, title: "The Eye of the World", authorId: 5, bookSeriesId: 2, genreId: 1}), | ||
10: us.extend(new Book(), {id: 10, title: "The Gathering Storm", authorId: 5, bookSeriesId: 2, genreId: 1}), | ||
11: us.extend(new Book(), {id: 11, title: "The Towers of Midnight", authorId: 5, bookSeriesId: 2, genreId: 1}) | ||
} | ||
module.exports["flow data"] = function(test){ | ||
@@ -199,3 +102,3 @@ flow({ | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooks: ['getGenre', 'findBooksByAuthor', 'getAuthor'] | ||
getBooks: ['getGenre.findBooksByAuthor', 'getAuthor'] | ||
}, function(err, results){ | ||
@@ -270,3 +173,3 @@ test.ok(!err); | ||
assertGenreExistence: [Genre.assertExistence, 'getGenre'], | ||
getBooks: ['assertGenreExistence', 'getGenre', 'findBooksByAuthor', 'getAuthor'] | ||
getBooks: ['assertGenreExistence', 'getGenre.findBooksByAuthor', 'getAuthor'] | ||
}, function(err, results){ | ||
@@ -295,3 +198,3 @@ test.ok(!err); | ||
assertGenreExistence: [Genre.assertExistence, 'getGenre'], | ||
getBooks: ['assertGenreExistence', 'getGenre', 'findBooksByAuthor', 'getAuthor'] | ||
getBooks: ['assertGenreExistence', 'getGenre.findBooksByAuthor', 'getAuthor'] | ||
}, function(err, results){ | ||
@@ -311,25 +214,38 @@ test.ok(err); | ||
module.exports["instance task execution with dot notation parameter"] = function(test){ | ||
module.exports["multiple instance parameter"] = function(test){ | ||
flow({ | ||
authorName: 'Dan Brown', | ||
genreName: 'Fiction' | ||
page: { | ||
number: 1, | ||
chapter: { | ||
number: 2, | ||
book: Book.all[5] | ||
} | ||
} | ||
}, { | ||
getAuthor: [Author.getByName, 'authorName'], | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooks: ['getGenre', 'findBooksByAuthor', 'getAuthor.id'] | ||
getGenre: [Genre.getById, 'page.chapter.book.genreId'] | ||
}, function(err, results){ | ||
test.ok(!err); | ||
test.deepEqual(results, { | ||
authorName: 'Dan Brown', | ||
genreName: 'Fiction', | ||
getAuthor: Author.all[4], | ||
getGenre: Genre.all[3], | ||
getBooks: [Book.all[6]] | ||
}); | ||
test.deepEqual(results.getGenre, Genre.all[4]); | ||
test.done(); | ||
}); | ||
}); | ||
} | ||
module.exports["instance task execution with dot notation function"] = function(test){ | ||
module.exports["result multi instance function"] = function(test){ | ||
flow({ | ||
page: { | ||
number: 1, | ||
chapter: { | ||
number: 2, | ||
book: Book.all[5] | ||
} | ||
} | ||
}, { | ||
getAuthor: ['page.chapter.book.getAuthor'] | ||
}, function(err, results){ | ||
test.deepEqual(results.getAuthor, Author.all[3]); | ||
test.done(); | ||
}); | ||
} | ||
module.exports["instance task execution with result instance parameter"] = function(test){ | ||
flow({ | ||
authorName: 'Dan Brown', | ||
@@ -340,3 +256,3 @@ genreName: 'Fiction' | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooks: ['getGenre.findBooksByAuthor', 'getAuthor'] | ||
getBooks: ['getGenre.findBooksByAuthor', 'getAuthor.id'] | ||
}, function(err, results){ | ||
@@ -355,18 +271,2 @@ test.ok(!err); | ||
module.exports["instance task execution with undefined dot notation function"] = function(test){ | ||
flow({ | ||
authorName: 'Dan Brown', | ||
genreName: 'Superfiction' | ||
}, { | ||
getAuthor: [Author.getByName, 'authorName'], | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooks: ['getGenre.findBooksByAuthor', 'getAuthor'] | ||
}, function(err, results){ | ||
test.ok(err); | ||
test.equals(err.message, 'Flow error in \'getBooks\': Cannot call function \'findBooksByAuthor\' on null/undefined \'getGenre\'') | ||
test.done(); | ||
}); | ||
} | ||
module.exports["multiple asyncronus tasks with prerequisite task execution"] = function(test){ | ||
@@ -444,3 +344,3 @@ flow( [ | ||
assertGenreExistence: [Genre.assertExistence, 'getGenre'], | ||
getBooks: ['assertGenreExistence', 'getGenre', 'findBooksByAuthor', 'getAuthor'] | ||
getBooks: ['assertGenreExistence', 'getGenre.findBooksByAuthor', 'getAuthor'] | ||
}, function(err, results){ | ||
@@ -479,3 +379,3 @@ test.ok(!err); | ||
assertGenreExistence: [Genre.assertExistence, 'getGenre'], | ||
getBooks: ['assertGenreExistence', 'getGenre', 'findBooksByAuthor', 'getAuthor'] | ||
getBooks: ['assertGenreExistence', 'getGenre.findBooksByAuthor', 'getAuthor'] | ||
}, function(err, results){ | ||
@@ -502,3 +402,3 @@ test.ok(err); | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooks: ['getGenre', 'getBooks'] | ||
getBooks: ['getGenre.getBooks'] | ||
}, function(err, results){ | ||
@@ -515,33 +415,26 @@ test.ok(!err); | ||
module.exports["different task name same as instance method"] = function(test){ | ||
try { | ||
flow({ | ||
genreName: 'Fantasy' | ||
}, { | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooks: ['getBooksByGenre', Book.findByGenreId, 'getGenre'] | ||
}, function(err, results){ | ||
test.fail(null, null, "no error received"); | ||
test.done(); | ||
}); | ||
} catch(e) { | ||
module.exports["undefined instance error"] = function(test){ | ||
flow({ | ||
genreName: 'Fictiony' | ||
}, { | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooks: ['getGenre.getBooks'] | ||
}, function(e, results){ | ||
test.ok(e, 'got an error'); | ||
test.equals(e.name, "FlowTaskError", "got FlowTaskError"); | ||
test.equals(e.message, "Flow error in 'getBooksByGenre': Function required.", "error message match") | ||
test.equals(e.name, "ArgumentNullError", "got proper error"); | ||
test.equals(e.message, 'Not Found: "getGenre" with genreName "Fictiony"') | ||
test.done(); | ||
} | ||
}); | ||
} | ||
module.exports["undefined instance error"] = function(test){ | ||
module.exports["undefined instance error 2"] = function(test){ | ||
flow({ | ||
genreName: 'Fictiony' | ||
genreName: 'Fiction' | ||
}, { | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooks: ['getGenre', 'getBooks'] | ||
getBooks: [Book.findByGenreId, 'getGenre.id.undef_value.err'] | ||
}, function(e, results){ | ||
test.ok(e, 'got an error'); | ||
test.equals(e.name, "FlowTaskArgumentNullError", "got FlowTaskError"); | ||
test.equals(e.message, "Flow error in 'getBooks': Cannot call function 'getBooks' on null/undefined 'getGenre'", "error message match") | ||
test.equals(e.name, "ArgumentNullError", "got proper error"); | ||
test.equals(e.message, 'Not Found: "id.undef_value" for getGenre with genreName "Fiction"') | ||
test.done(); | ||
@@ -569,20 +462,20 @@ }); | ||
module.exports["multiple instance functions error"] = function(test){ | ||
try { | ||
flow({ | ||
bookId: 1 | ||
}, { | ||
getBook: [Book.getById, 'bookId'], | ||
getBookAuthor: ['getBook', 'getAuthor', 'getAuthor'] | ||
}, function(err, results){ | ||
test.fail(null, null, "no error received"); | ||
test.done(); | ||
}); | ||
} catch(e) { | ||
test.ok(e, 'got an error'); | ||
test.equals(e.name, "FlowTaskError", "got FlowTaskError"); | ||
test.equals(e.message, "Flow error in 'getBookAuthor': More than one function specified (at index 1 and 2).", "error message match") | ||
test.done(); | ||
} | ||
} | ||
// module.exports["multiple instance functions error"] = function(test){ | ||
// try { | ||
// flow({ | ||
// bookId: 1 | ||
// }, { | ||
// getBook: [Book.getById, 'bookId'], | ||
// getBookAuthor: ['getBook.getAuthor', 'getBook.getAuthor'] | ||
// }, function(err, results){ | ||
// test.fail(null, null, "no error received"); | ||
// test.done(); | ||
// }); | ||
// } catch(e) { | ||
// test.ok(e, 'got an error'); | ||
// test.equals(e.name, "FlowTaskError", "got FlowTaskError"); | ||
// test.equals(e.message, "Flow error in 'getBookAuthor': More than one function specified (at index 1 and 2).", "error message match") | ||
// test.done(); | ||
// } | ||
// } | ||
@@ -595,3 +488,3 @@ module.exports["unknown symbol error"] = function(test){ | ||
getBook: [Book.getById, 'bookId'], | ||
getAuthor: ['getBook', 'notafunction'] | ||
getAuthor: ['getBook.notafunction'] | ||
}, function(err, results){ | ||
@@ -623,3 +516,3 @@ test.fail(null, null, "no error received"); | ||
test.equals(e.name, 'FlowTaskError') | ||
test.equals(e.message, "Flow error in 'getAuthor': Unknown symbol at index '0' must be either the name of a task, the name of data, or be the name of a function on the result of a task or data", "error message match") | ||
test.equals(e.message, "Flow error in 'getAuthor': Unknown string 'notafunction' must be either the name of a task or the name of data", "error message match") | ||
test.done(); | ||
@@ -687,3 +580,3 @@ } | ||
module.exports["missing function in task args error"] = function(test){ | ||
module.exports["invalid flow type task"] = function(test){ | ||
try { | ||
@@ -702,3 +595,3 @@ flow({ | ||
test.equals(e.name, "FlowTaskError", "got FlowTaskError"); | ||
test.equals(e.message, "Flow error in 'getAuthor': Invalid flow type. Must be function, or array.", "error message match") | ||
test.equals(e.message, "Flow error in 'getAuthor': Invalid flow type. Must be function, subFlow, or array.", "error message match") | ||
test.done(); | ||
@@ -730,3 +623,3 @@ } | ||
module.exports["array result data execution"] = function(test){ | ||
module.exports["subFlow execution"] = function(test){ | ||
flow({ | ||
@@ -736,5 +629,5 @@ genreName: 'Fantasy' | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: flow.subFlow('getBooksByGenre', { | ||
getBookAuthor: ['getBooksByGenre', 'getAuthor'] | ||
getBookAuthor: ['getBooksByGenre.getAuthor'] | ||
}) | ||
@@ -764,3 +657,3 @@ }, function(err, results){ | ||
module.exports["array result data execution with context"] = function(test){ | ||
module.exports["subFlow execution with context"] = function(test){ | ||
flow({ | ||
@@ -770,3 +663,3 @@ genreName: 'Fantasy' | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: flow.subFlow('getBooksByGenre', { | ||
@@ -798,3 +691,3 @@ getBookAuthor: [Author.getById, 'authorId'] | ||
module.exports["array result data execution using subFlow"] = function(test){ | ||
module.exports["subFlow execution using subFlow"] = function(test){ | ||
flow({ | ||
@@ -804,5 +697,5 @@ genreName: 'Fantasy' | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: flow.subFlow('getBooksByGenre', { | ||
getBookAuthor: ['getBooksByGenre', 'getAuthor'] | ||
getBookAuthor: ['getBooksByGenre.getAuthor'] | ||
}) | ||
@@ -833,3 +726,3 @@ }, function(err, results){ | ||
module.exports["array result data execution with prereqs using subFlow"] = function(test){ | ||
module.exports["subFlow execution with prereqs"] = function(test){ | ||
flow({ | ||
@@ -840,3 +733,3 @@ genreName: 'Fantasy', | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: flow.subFlow('getBooksByGenre', { | ||
@@ -877,5 +770,5 @@ getHambly2: [Author.getById, 'getHambly'] | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: flow.subFlow('getBooksByGenre', { | ||
getBookAuthor: ['getBooksByGenre', 'getAuthor'], | ||
getBookAuthor: ['getBooksByGenre.getAuthor'], | ||
getBooksByAuthor: [Book.findByAuthorId, 'getBookAuthor'], | ||
@@ -947,3 +840,3 @@ getManyHamblies: flow.subFlow('getBooksByAuthor', { | ||
module.exports["subflow with prereqs and dot notation"] = function(test){ | ||
module.exports["subflow with prereqs and result instance parameter"] = function(test){ | ||
flow({ | ||
@@ -954,3 +847,3 @@ genreName: 'Fantasy', | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: flow.subFlow('getBooksByGenre', { | ||
@@ -990,5 +883,5 @@ getHambly2: [Author.getById, 'getHambly.id'] | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: flow.subFlow('', { | ||
getBookAuthor: ['getBooksByGenre', 'getAuthor'] | ||
getBookAuthor: ['getBooksByGenre.getAuthor'] | ||
}) | ||
@@ -1013,3 +906,3 @@ }, function(err, results){ | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: flow.subFlow('getBooksByGenre', null) | ||
@@ -1035,5 +928,5 @@ }, function(err, results){ | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: flow.subFlow('asdf', { | ||
getBookAuthor: ['getBooksByGenre', 'getAuthor'] | ||
getBookAuthor: ['getBooksByGenre.getAuthor'] | ||
}) | ||
@@ -1058,5 +951,5 @@ }, function(err, results){ | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: flow.subFlow('getAuthors', { | ||
getBookAuthor: ['getBooksByGenre', 'getAuthor'] | ||
getBookAuthor: ['getBooksByGenre.getAuthor'] | ||
}) | ||
@@ -1082,3 +975,3 @@ }, function(err, results){ | ||
assertGenreExistence: [Genre.assertExistence, 'getGenre'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: ['assertGenreExistence', flow.subFlow('getBooksByGenre', { | ||
@@ -1117,3 +1010,3 @@ getBookAuthor: [Author.getById, 'authorId'] | ||
assertGenreExistence: [Genre.assertExistence, 'getGenre'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: [flow.subFlow('getBooksByGenre', { | ||
@@ -1129,3 +1022,3 @@ getBookAuthor: [Author.getById, 'authorId'] | ||
test.equals(e.name, "FlowTaskError", "got Error"); | ||
test.equals(e.message, "Flow error in 'getAuthors': SubFlows must be the at the last index.", "error message match") | ||
test.equals(e.message, "Flow error in 'getAuthors': SubFlows must be at the last index.", "error message match") | ||
test.done(); | ||
@@ -1143,3 +1036,3 @@ } | ||
assertGenreExistence: [Genre.assertExistence, 'getGenre'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: ['assertGenreExistence', flow.subFlow('asdf', { | ||
@@ -1168,3 +1061,3 @@ getBookAuthor: [Author.getById, 'authorId'] | ||
assertGenreExistence: [Genre.assertExistence, 'getGenre'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: ['assertGenreExistence', flow.subFlow('getAuthors', { | ||
@@ -1230,3 +1123,3 @@ getBookAuthor: [Author.getById, 'authorId'] | ||
module.exports["subflow with dot notation for parameter"] = function(test){ | ||
module.exports["subflow with result instance parameter"] = function(test){ | ||
flow({ | ||
@@ -1236,3 +1129,3 @@ genreName: 'Fantasy' | ||
getGenre: [Genre.getByName, 'genreName'], | ||
getBooksByGenre: ['getGenre', 'getBooks'], | ||
getBooksByGenre: ['getGenre.getBooks'], | ||
getAuthors: flow.subFlow('getBooksByGenre', { | ||
@@ -1263,3 +1156,75 @@ getBookAuthor: [Author.getById, 'getBooksByGenre.authorId'] | ||
module.exports["asynchronous task execution"] = function(test){ | ||
flow({ | ||
id: 3, | ||
}, { | ||
getBook: flow.asyncTask(Book.getById, 'id'), | ||
getAuthor: flow.asyncTask(Author.getById, 'getBook.authorId'), | ||
}, function(err, results){ | ||
test.deepEqual({ | ||
id: 3, | ||
getBook: Book.all[3], | ||
getAuthor: Author.all[1], | ||
}, results); | ||
test.done(); | ||
}); | ||
} | ||
module.exports["asynchronous task execution with array"] = function(test){ | ||
flow({ | ||
id: 3, | ||
}, { | ||
getBook: flow.asyncTask([Book.getById, 'id']), | ||
getAuthor: flow.asyncTask([Author.getById, 'getBook.authorId']), | ||
}, function(err, results){ | ||
test.deepEqual({ | ||
id: 3, | ||
getBook: Book.all[3], | ||
getAuthor: Author.all[1], | ||
}, results); | ||
test.done(); | ||
}); | ||
} | ||
module.exports["synchronous task execution"] = function(test){ | ||
flow({ | ||
id: 3, | ||
new_object: {} | ||
}, { | ||
getBook: [Book.getById, 'id'], | ||
getAuthor: [Author.getById, 'getBook.authorId'], | ||
getBookAuthorData: flow.syncTask(us.extend, 'new_object', 'getBook', 'getAuthor') | ||
}, function(err, results){ | ||
test.deepEqual({ | ||
id: 3, | ||
new_object: us.extend({}, Book.all[3], Author.all[1]), | ||
getBook: Book.all[3], | ||
getAuthor: Author.all[1], | ||
getBookAuthorData: us.extend({}, Book.all[3], Author.all[1]) | ||
}, results); | ||
test.done(); | ||
}); | ||
} | ||
module.exports["synchronous task execution with array"] = function(test){ | ||
flow({ | ||
id: 3, | ||
new_object: {} | ||
}, { | ||
getBook: [Book.getById, 'id'], | ||
getAuthor: [Author.getById, 'getBook.authorId'], | ||
getBookAuthorData: flow.syncTask([us.extend, 'new_object', 'getBook', 'getAuthor']) | ||
}, function(err, results){ | ||
test.deepEqual({ | ||
id: 3, | ||
new_object: us.extend({}, Book.all[3], Author.all[1]), | ||
getBook: Book.all[3], | ||
getAuthor: Author.all[1], | ||
getBookAuthorData: us.extend({}, Book.all[3], Author.all[1]) | ||
}, results); | ||
test.done(); | ||
}); | ||
} | ||
// module.exports["array result data execution"] = function(test){ | ||
@@ -1299,1 +1264,8 @@ // var authors, fantasyAuthors; | ||
// flow({ | ||
// some_data: 2, | ||
// some_value: '3.2', | ||
// }, { | ||
// test1: flow.asyncTask([Class.doSomething, 'some_data']), | ||
// test3: flow.syncTask([parseInt, 'some_value']) | ||
// }) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
71188
10
1769