Comparing version 0.2.0 to 1.0.0
343
ordu.js
@@ -1,118 +0,239 @@ | ||
/* Copyright (c) 2016 Richard Rodger and other contributors, MIT License */ | ||
'use strict' | ||
var Assert = require('assert') | ||
module.exports = function(opts) { | ||
return new Ordu(opts) | ||
/* Copyright (c) 2016-2020 Richard Rodger and other contributors, MIT License */ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const Hoek = require("@hapi/hoek"); | ||
const Topo = require("@hapi/topo"); | ||
class Task { | ||
constructor(taskdef) { | ||
this.id = | ||
null == taskdef.id ? ('' + Math.random()).substring(2) : taskdef.id; | ||
this.name = taskdef.name || 'task' + Task.count; | ||
this.before = strarr(taskdef.before); | ||
this.after = strarr(taskdef.after); | ||
this.exec = taskdef.exec || ((_) => { }); | ||
this.if = taskdef.if || void 0; | ||
this.meta = { | ||
order: Task.count++, | ||
when: Date.now(), | ||
// TODO: auto generate call point stacktrace? | ||
from: taskdef.from || {}, | ||
}; | ||
} | ||
} | ||
var orduI = -1 | ||
function Ordu(opts) { | ||
var self = this | ||
++orduI | ||
opts = opts || {} | ||
Assert('object' === typeof opts) | ||
opts.name = opts.name || 'ordu' + orduI | ||
self.add = api_add | ||
self.process = api_process | ||
self.tasknames = api_tasknames | ||
self.taskdetails = api_taskdetails | ||
self.toString = api_toString | ||
var tasks = [] | ||
function api_add(spec, task) { | ||
task = task || spec | ||
Assert('function' === typeof task) | ||
if (!task.name) { | ||
Object.defineProperty(task, 'name', { | ||
value: opts.name + '_task' + tasks.length | ||
}) | ||
Task.count = 0; | ||
// Use the constructor to normalize task result | ||
class TaskResult { | ||
constructor(log, raw) { | ||
raw = null == raw ? {} : raw; | ||
this.log = log; | ||
this.out = null == raw.out ? {} : raw.out; | ||
this.err = raw instanceof Error ? raw : void 0; | ||
this.op = | ||
null != this.err ? 'stop' : 'string' === typeof raw.op ? raw.op : 'next'; | ||
} | ||
task.tags = spec.tags || [] | ||
tasks.push(task) | ||
return self | ||
} | ||
// Valid calls: | ||
// * process(spec, ctxt, data) | ||
// * process(ctxt, data) | ||
// * process(data) | ||
// * process() | ||
function api_process() { | ||
var i = arguments.length | ||
var data = 0 < i && arguments[--i] | ||
var ctxt = 0 < i && arguments[--i] | ||
var spec = 0 < i && arguments[--i] | ||
data = data || {} | ||
ctxt = ctxt || {} | ||
spec = spec || {} | ||
spec.tags = spec.tags || [] | ||
for (var tI = 0; tI < tasks.length; ++tI) { | ||
var task = tasks[tI] | ||
if (0 < spec.tags.length && !contains(task.tags, spec.tags)) { | ||
continue | ||
} | ||
var index$ = tI | ||
var taskname$ = task.name | ||
ctxt.index$ = index$ | ||
ctxt.taskname$ = taskname$ | ||
var res = task(ctxt, data) | ||
if (res) { | ||
res.index$ = index$ | ||
res.taskname$ = taskname$ | ||
res.ctxt$ = ctxt | ||
res.data$ = data | ||
return res | ||
} | ||
} | ||
class Self { | ||
constructor() { | ||
this.topo = new Topo.Sorter(); | ||
this.operator_map = { | ||
next: () => ({ stop: false }), | ||
skip: () => ({ stop: false }), | ||
stop: (tr) => ({ stop: true, err: tr.err }), | ||
merge: (tr, _, data) => { | ||
Hoek.merge(data, tr.out); | ||
return { stop: false }; | ||
}, | ||
}; | ||
} | ||
return null | ||
} | ||
function api_tasknames() { | ||
return tasks.map(function(v) { | ||
return v.name | ||
}) | ||
} | ||
function api_taskdetails() { | ||
return tasks.map(function(v) { | ||
return v.name + ':{tags:' + v.tags + '}' | ||
}) | ||
} | ||
function api_toString() { | ||
return opts.name + ':[' + self.tasknames() + ']' | ||
} | ||
return self | ||
operator(name, opr) { | ||
this.operator_map[name] = opr; | ||
} | ||
operators() { | ||
return this.operator_map; | ||
} | ||
add(taskdef) { | ||
let t = new Task(taskdef); | ||
this.topo.add(t, { | ||
group: t.name, | ||
before: t.before, | ||
after: t.after, | ||
}); | ||
} | ||
// TODO: execSync version when promises not needed | ||
async exec(ctx, data) { | ||
let start = Date.now(); | ||
let tasks = this.topo.nodes; | ||
let spec = { | ||
ctx: ctx || {}, | ||
data: data || {}, | ||
}; | ||
let operate = { stop: false, err: void 0 }; | ||
let tasklog = []; | ||
let task_count = 0; | ||
let taskI = 0; | ||
for (; taskI < tasks.length; taskI++) { | ||
let task = tasks[taskI]; | ||
let taskout = null; | ||
let tasklogentry = { | ||
task, | ||
start: Date.now(), | ||
end: Number.MAX_SAFE_INTEGER, | ||
}; | ||
if (this.task_if(task, spec.data)) { | ||
try { | ||
task_count++; | ||
taskout = task.exec(spec); | ||
taskout = taskout instanceof Promise ? await taskout : taskout; | ||
} | ||
catch (task_ex) { | ||
taskout = task_ex; | ||
} | ||
} | ||
else { | ||
taskout = { op: 'skip' }; | ||
} | ||
tasklogentry.end = Date.now(); | ||
let result = new TaskResult(tasklogentry, taskout); | ||
try { | ||
operate = this.operate(result, spec.ctx, spec.data); | ||
operate = (operate instanceof Promise | ||
? await operate | ||
: operate); | ||
} | ||
catch (operate_ex) { | ||
operate = { | ||
stop: true, | ||
err: operate_ex, | ||
}; | ||
} | ||
tasklog.push({ name: task.name, op: result.op, task, result, operate }); | ||
if (operate.stop) { | ||
break; | ||
} | ||
} | ||
return { | ||
tasklog: tasklog, | ||
task: operate.err ? tasks[taskI] : void 0, | ||
task_count: task_count, | ||
task_total: tasks.length, | ||
start: start, | ||
end: Date.now(), | ||
err: operate.err, | ||
data: spec.data, | ||
}; | ||
} | ||
tasks() { | ||
return this.topo.nodes; | ||
} | ||
operate(r, ctx, data) { | ||
let operator = this.operator_map[r.op]; | ||
if (operator) { | ||
return operator(r, ctx, data); | ||
} | ||
else { | ||
return { | ||
stop: true, | ||
err: new Error('Unknown operation: ' + r.op), | ||
}; | ||
} | ||
} | ||
task_if(task, data) { | ||
if (task.if) { | ||
let task_if = task.if; | ||
return Object.keys(task_if).reduce((proceed, k) => { | ||
let part = Hoek.reach(data, k); | ||
return (proceed && | ||
Hoek.contain({ $: part }, { $: task_if[k] }, { deep: true })); | ||
}, true); | ||
} | ||
else { | ||
return true; | ||
} | ||
} | ||
} | ||
exports.Ordu = Self; | ||
function strarr(x) { | ||
return null == x ? [] : 'string' === typeof x ? [x] : x; | ||
} | ||
function LegacyOrdu(opts) { | ||
var orduI = -1; | ||
var self = {}; | ||
++orduI; | ||
opts = opts || {}; | ||
opts.name = opts.name || 'ordu' + orduI; | ||
self.add = api_add; | ||
self.process = api_process; | ||
self.tasknames = api_tasknames; | ||
self.taskdetails = api_taskdetails; | ||
self.toString = api_toString; | ||
var tasks = []; | ||
function api_add(spec, task) { | ||
task = task || spec; | ||
if (!task.name) { | ||
Object.defineProperty(task, 'name', { | ||
value: opts.name + '_task' + tasks.length, | ||
}); | ||
} | ||
task.tags = spec.tags || []; | ||
tasks.push(task); | ||
return self; | ||
} | ||
// Valid calls: | ||
// * process(spec, ctxt, data) | ||
// * process(ctxt, data) | ||
// * process(data) | ||
// * process() | ||
function api_process() { | ||
var i = arguments.length; | ||
var data = 0 < i && arguments[--i]; | ||
var ctxt = 0 < i && arguments[--i]; | ||
var spec = 0 < i && arguments[--i]; | ||
data = data || {}; | ||
ctxt = ctxt || {}; | ||
spec = spec || {}; | ||
spec.tags = spec.tags || []; | ||
for (var tI = 0; tI < tasks.length; ++tI) { | ||
var task = tasks[tI]; | ||
if (0 < spec.tags.length && !contains(task.tags, spec.tags)) { | ||
continue; | ||
} | ||
var index$ = tI; | ||
var taskname$ = task.name; | ||
ctxt.index$ = index$; | ||
ctxt.taskname$ = taskname$; | ||
var res = task(ctxt, data); | ||
if (res) { | ||
res.index$ = index$; | ||
res.taskname$ = taskname$; | ||
res.ctxt$ = ctxt; | ||
res.data$ = data; | ||
return res; | ||
} | ||
} | ||
return null; | ||
} | ||
function api_tasknames() { | ||
return tasks.map(function (v) { | ||
return v.name; | ||
}); | ||
} | ||
function api_taskdetails() { | ||
return tasks.map(function (v) { | ||
return v.name + ':{tags:' + v.tags + '}'; | ||
}); | ||
} | ||
function api_toString() { | ||
return opts.name + ':[' + self.tasknames() + ']'; | ||
} | ||
return self; | ||
} | ||
exports.LegacyOrdu = LegacyOrdu; | ||
function contains(all, some) { | ||
for (var i = 0; i < some.length; ++i) { | ||
if (-1 === all.indexOf(some[i])) { | ||
return false | ||
for (var i = 0; i < some.length; ++i) { | ||
if (-1 === all.indexOf(some[i])) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true | ||
return true; | ||
} | ||
//# sourceMappingURL=ordu.js.map |
{ | ||
"name": "ordu", | ||
"version": "0.2.0", | ||
"version": "1.0.0", | ||
"description": "Execute functions in a configurable order, modifying a shared data structure.", | ||
@@ -19,5 +19,7 @@ "homepage": "https://github.com/rjrodger/ordu", | ||
"scripts": { | ||
"test": "lab -L -v -P test -t 100 -r console -o stdout -r html -o test/coverage.html", | ||
"watch": "tsc -w -d", | ||
"build": "tsc -d", | ||
"test": "lab -L -v -P test -t 100 --sourcemaps --transform node_modules/lab-transform-typescript -r console -o stdout -r html -o test/coverage.html", | ||
"coveralls": "lab -s -P test -r lcov | coveralls", | ||
"prettier": "prettier --write *.js lib/*.js test/*.js", | ||
"prettier": "prettier --write *.ts", | ||
"clean": "rm -rf node_modules package-lock.json yarn.lock", | ||
@@ -31,13 +33,20 @@ "reset": "npm run clean && npm i && npm test", | ||
"files": [ | ||
"ordu.js", | ||
"ordu.*", | ||
"*.json", | ||
"LICENSE", | ||
"README.md" | ||
], | ||
"dependencies": {}, | ||
"dependencies": { | ||
"@hapi/hoek": "^9.0.4", | ||
"@hapi/topo": "^5.0.0" | ||
}, | ||
"devDependencies": { | ||
"@hapi/code": "^8.0.1", | ||
"@hapi/lab": "^22.0.3", | ||
"coveralls": "^3.0.9", | ||
"prettier": "^1.19.1" | ||
"@hapi/lab": "^22.0.4", | ||
"@types/node": "^13.13.5", | ||
"coveralls": "^3.1.0", | ||
"lab-transform-typescript": "^3.0.1", | ||
"prettier": "^2.0.5", | ||
"typescript": "^3.8.3" | ||
} | ||
} |
@@ -7,2 +7,4 @@ # ordu | ||
[![Dependency Status][david-badge]][david-url] | ||
[![DeepScan grade](https://deepscan.io/api/teams/5016/projects/11434/branches/170370/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=5016&pid=11434&bid=170370) | ||
[![Maintainability](https://api.codeclimate.com/v1/badges/47fe47f0b317507cb120/maintainability)](https://codeclimate.com/github/rjrodger/ordu/maintainability) | ||
@@ -58,10 +60,4 @@ | ||
### Support | ||
If you're using this library, feel free to contact me on twitter if | ||
you have any questions! :) [@rjrodger](http://twitter.com/rjrodger) | ||
[![Build Status](https://travis-ci.org/rjrodger/ordu.png?branch=master)](https://travis-ci.org/rjrodger/ordu) | ||
## Install | ||
@@ -68,0 +64,0 @@ |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
110662
10
2718
0
2
7
86
1
+ Added@hapi/hoek@^9.0.4
+ Added@hapi/topo@^5.0.0
+ Added@hapi/hoek@9.3.0(transitive)
+ Added@hapi/topo@5.1.0(transitive)