@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 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.
@@ -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
- var call = jobs.nextJobCall(ctx.system && ctx.system.trigger, input.jobId, input.inputs, input.carry);
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;
@@ -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 = { startRun: startRun, resumeByKey: resumeByKey, resolveParams: resolveParams, collectParams: collectParams };
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.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",