@xeplr/workflow-engine 3.0.0 → 3.0.1
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 +1 -0
- package/lib/actions/jobRun.js +8 -1
- package/lib/workflowRunner.js +33 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -207,6 +207,7 @@ Branch on how a job ended with a `decide` step: it does nothing itself, and the
|
|
|
207
207
|
- **The period flows.** The next job gets the finished job's `window` unless the step's `inputs` set one, so a chain of workflows covers one period from its first job to its last.
|
|
208
208
|
- **The next job is offered both earlier ranges**, as `@xeplr/jobs`' `previous.given` / `previous.used`.
|
|
209
209
|
- **`carry`** (a `job-run` input) adds values for the jobs after it.
|
|
210
|
+
- **`inputs` and `carry` keep their types.** A binding that is the whole value (`"{trigger.output.totalRows}"`) passes `7`, not `"7"`, and an object stays an object. Every other step's input is text, as bindings make it.
|
|
210
211
|
- **Loops stop.** A job already on the path, or a path 25 jobs long, fails the step with a message.
|
|
211
212
|
|
|
212
213
|
The next job takes only `window` and the inputs it lists in `acceptsInputs`; `@xeplr/jobs` refuses the rest, naming them.
|
package/lib/actions/jobRun.js
CHANGED
|
@@ -77,7 +77,14 @@ module.exports = {
|
|
|
77
77
|
// this job unless the step sets one, carried values and the path travel
|
|
78
78
|
// with it, and a job already on the path is refused as a loop
|
|
79
79
|
// (jobs.nextJobCall). Any other run passes the step's inputs as they are.
|
|
80
|
-
|
|
80
|
+
// Inputs and carry KEEP THEIR TYPES ("{trigger.output.totalRows}" is 7,
|
|
81
|
+
// not "7"): they are handed on to a job, not printed.
|
|
82
|
+
var sys = ctx.system || {};
|
|
83
|
+
var raw = sys.rawValues || {};
|
|
84
|
+
var typed = typeof sys.resolveTyped === 'function';
|
|
85
|
+
var call = jobs.nextJobCall(sys.trigger, input.jobId,
|
|
86
|
+
typed && raw.inputs !== undefined ? sys.resolveTyped(raw.inputs) : input.inputs,
|
|
87
|
+
typed && raw.carry !== undefined ? sys.resolveTyped(raw.carry) : input.carry);
|
|
81
88
|
var startJob = jobs.jobStarter();
|
|
82
89
|
if (startJob) {
|
|
83
90
|
call.chain.resumeKey = (ctx.system && ctx.system.resumeKey) || null;
|
package/lib/workflowRunner.js
CHANGED
|
@@ -112,6 +112,30 @@ async function finishRun(run, status, error) {
|
|
|
112
112
|
* the two can differ), params/item are the run's own, resumeKey is injected
|
|
113
113
|
* separately, only for the specific step that needs it.
|
|
114
114
|
*/
|
|
115
|
+
/**
|
|
116
|
+
* Resolve `{path}` bindings KEEPING TYPES: a string that is exactly one
|
|
117
|
+
* binding takes the bound value as it is (an object stays an object, a number
|
|
118
|
+
* a number); anything else is text, as interpolate makes it.
|
|
119
|
+
*/
|
|
120
|
+
function resolveTyped(value, context) {
|
|
121
|
+
if (value == null) return value;
|
|
122
|
+
if (typeof value === 'string') {
|
|
123
|
+
var whole = /^\{([^{}]+)\}$/.exec(value.trim());
|
|
124
|
+
if (whole) {
|
|
125
|
+
var v = getPath(context, whole[1].trim());
|
|
126
|
+
return v === undefined ? null : v;
|
|
127
|
+
}
|
|
128
|
+
return interpolateAll(value, context);
|
|
129
|
+
}
|
|
130
|
+
if (Array.isArray(value)) return value.map(function(v) { return resolveTyped(v, context); });
|
|
131
|
+
if (typeof value === 'object') {
|
|
132
|
+
var out = {};
|
|
133
|
+
Object.keys(value).forEach(function(k) { out[k] = resolveTyped(value[k], context); });
|
|
134
|
+
return out;
|
|
135
|
+
}
|
|
136
|
+
return value;
|
|
137
|
+
}
|
|
138
|
+
|
|
115
139
|
// What started a run, as {trigger.*} reads it — in bindings AND in the
|
|
116
140
|
// conditions on arrows. A run started by hand has just its kind.
|
|
117
141
|
function triggerOf(run) {
|
|
@@ -359,8 +383,14 @@ async function executeFrom(workflow, steps, run, startStepKey) {
|
|
|
359
383
|
// started in-process reports back through jobs.jobFinished).
|
|
360
384
|
// trigger: what started the run, for an action that carries it on
|
|
361
385
|
// (job-run passes a job's period to the next job).
|
|
386
|
+
// resolveTyped: a binding that is the WHOLE value keeps its type
|
|
387
|
+
// ("{trigger.output.totalRows}" stays 7, "{trigger.window}" an object),
|
|
388
|
+
// for an action that passes values on rather than printing them
|
|
389
|
+
// (job-run's inputs and carry). Every other action takes `input`, as
|
|
390
|
+
// resolved above, unchanged.
|
|
362
391
|
system: { runId: run.id, stepId: step.id, stepKey: step.stepKey, resumeKey: resumeKey,
|
|
363
|
-
trigger: triggerOf(run) }
|
|
392
|
+
trigger: triggerOf(run), rawValues: step.values || {},
|
|
393
|
+
resolveTyped: function(value) { return resolveTyped(value, context); } }
|
|
364
394
|
});
|
|
365
395
|
|
|
366
396
|
if (result.status !== 'success') {
|
|
@@ -664,4 +694,5 @@ async function resumeByKey(key, output, opts) {
|
|
|
664
694
|
// resolveParams and collectParams are exported for their own sake: they are
|
|
665
695
|
// the pieces of the engine that are pure — rows in, a schema or a resolved
|
|
666
696
|
// set out, or a throw — and testing them needs no database.
|
|
667
|
-
module.exports = {
|
|
697
|
+
module.exports = {
|
|
698
|
+
resolveTyped: resolveTyped, startRun: startRun, resumeByKey: resumeByKey, resolveParams: resolveParams, collectParams: collectParams };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xeplr/workflow-engine",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "The workflow engine — workflow's own database and tables, the action catalog, starting and resuming runs, and the flows facade. No HTTP: @xeplr/workflow-api puts the routes on top.",
|
|
6
6
|
"main": "index.js",
|