@blokjs/shared 0.2.1 → 0.4.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.
- package/__tests__/unit/BlokError.test.ts +294 -0
- package/__tests__/unit/NodeBase.test.ts +4 -1
- package/__tests__/unit/utils/Mapper.test.ts +299 -31
- package/__tests__/unit/utils/MapperResolutionError.test.ts +64 -0
- package/dist/BlokError.d.ts +196 -0
- package/dist/BlokError.js +328 -0
- package/dist/BlokError.js.map +1 -0
- package/dist/NodeBase.d.ts +96 -2
- package/dist/NodeBase.js +120 -2
- package/dist/NodeBase.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/types/Context.d.ts +91 -0
- package/dist/types/StateContext.d.ts +21 -0
- package/dist/types/StateContext.js +2 -0
- package/dist/types/StateContext.js.map +1 -0
- package/dist/types/VarsContext.d.ts +15 -2
- package/dist/utils/Mapper.d.ts +111 -2
- package/dist/utils/Mapper.js +256 -23
- package/dist/utils/Mapper.js.map +1 -1
- package/dist/utils/MapperResolutionError.d.ts +84 -0
- package/dist/utils/MapperResolutionError.js +61 -0
- package/dist/utils/MapperResolutionError.js.map +1 -0
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/package.json +2 -5
package/dist/types/Context.d.ts
CHANGED
|
@@ -6,20 +6,111 @@ import type FunctionContext from "./FunctionContext";
|
|
|
6
6
|
import type LoggerContext from "./LoggerContext";
|
|
7
7
|
import type RequestContext from "./RequestContext";
|
|
8
8
|
import type ResponseContext from "./ResponseContext";
|
|
9
|
+
import type StateContext from "./StateContext";
|
|
9
10
|
import type VarsContext from "./VarsContext";
|
|
11
|
+
/**
|
|
12
|
+
* The runtime context for a single workflow execution. One Context object
|
|
13
|
+
* is created per run and threaded through every step.
|
|
14
|
+
*
|
|
15
|
+
* **The two-tier read model:**
|
|
16
|
+
*
|
|
17
|
+
* - `ctx.prev` — the previous step's full result envelope ({ data, success,
|
|
18
|
+
* error }). Overwritten on every step. Use for adjacent-step access.
|
|
19
|
+
* Aliased by `ctx.response` for back-compat with v1.
|
|
20
|
+
*
|
|
21
|
+
* - `ctx.state[stepId]` — each step's `result.data` is automatically
|
|
22
|
+
* persisted here under the step's `id` (or its `as` override). Use
|
|
23
|
+
* for any-distance access. Aliased by `ctx.vars` for back-compat.
|
|
24
|
+
*
|
|
25
|
+
* **Side-channel publication:**
|
|
26
|
+
*
|
|
27
|
+
* - `ctx.publish(name, value)` — explicitly publish a value into state
|
|
28
|
+
* from inside a node. Logged in Studio's trace tab. Use sparingly —
|
|
29
|
+
* most nodes should just `return` their output and let the runner
|
|
30
|
+
* persist it.
|
|
31
|
+
*
|
|
32
|
+
* **Request envelope aliases:**
|
|
33
|
+
*
|
|
34
|
+
* - `ctx.req` — alias for `ctx.request`. Read query, body, params,
|
|
35
|
+
* headers, etc. via either form.
|
|
36
|
+
*/
|
|
10
37
|
type Context = {
|
|
11
38
|
id: string;
|
|
12
39
|
workflow_name?: string;
|
|
13
40
|
workflow_path?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Request envelope. Body, query, params, headers, etc.
|
|
43
|
+
*
|
|
44
|
+
* Also accessible as `ctx.req` (alias).
|
|
45
|
+
*/
|
|
14
46
|
request: RequestContext;
|
|
47
|
+
/**
|
|
48
|
+
* Alias for `ctx.request` — same object, read-only getter. v2
|
|
49
|
+
* authoring uses `req`; v1 authoring used `request`. Both work.
|
|
50
|
+
*/
|
|
51
|
+
readonly req?: RequestContext;
|
|
52
|
+
/**
|
|
53
|
+
* Previous step's full result envelope. **Overwritten every step.**
|
|
54
|
+
* Use for adjacent-step access only; for cross-step access use
|
|
55
|
+
* `ctx.state[stepId]`.
|
|
56
|
+
*
|
|
57
|
+
* Aliased by `ctx.response` for v1 back-compat.
|
|
58
|
+
*/
|
|
15
59
|
response: ResponseContext;
|
|
60
|
+
/**
|
|
61
|
+
* Alias for `ctx.response` — same object. v2 authoring uses `prev`;
|
|
62
|
+
* v1 authoring used `response.data`. Both work.
|
|
63
|
+
*/
|
|
64
|
+
readonly prev?: ResponseContext;
|
|
16
65
|
error: ErrorContext;
|
|
17
66
|
logger: LoggerContext;
|
|
18
67
|
config: ConfigContext;
|
|
19
68
|
func?: FunctionContext;
|
|
69
|
+
/**
|
|
70
|
+
* Accumulated step outputs by step `id`. Filled automatically when
|
|
71
|
+
* a step completes (unless `ephemeral: true`).
|
|
72
|
+
*
|
|
73
|
+
* Aliased by `ctx.vars` for v1 back-compat — both fields point at
|
|
74
|
+
* the same underlying object.
|
|
75
|
+
*
|
|
76
|
+
* Always initialized to `{}` by `TriggerBase.createContext`. Marked
|
|
77
|
+
* optional only so legacy code paths that hand-construct a Context
|
|
78
|
+
* (some tests, internal utilities) keep type-checking; production
|
|
79
|
+
* runs always have `state` defined.
|
|
80
|
+
*/
|
|
81
|
+
state?: StateContext;
|
|
82
|
+
/**
|
|
83
|
+
* Alias for `ctx.state` — same underlying object. v2 authoring
|
|
84
|
+
* uses `state`; v1 authoring used `vars`. Both work.
|
|
85
|
+
*
|
|
86
|
+
* @deprecated Prefer `ctx.state` (or `$.state.<id>` from inputs).
|
|
87
|
+
*/
|
|
20
88
|
vars?: VarsContext;
|
|
21
89
|
env?: EnvContext;
|
|
22
90
|
eventLogger: GlobalLogger | unknown;
|
|
91
|
+
/**
|
|
92
|
+
* Explicit side-channel publication. Writes to state under `name`
|
|
93
|
+
* and emits a Studio trace event. Use only when a node needs to
|
|
94
|
+
* publish something other than its return value (most nodes don't).
|
|
95
|
+
*/
|
|
96
|
+
publish?: (name: string, value: unknown) => void;
|
|
97
|
+
/**
|
|
98
|
+
* Tier 2 follow-up · cooperative cancellation. AbortSignal whose
|
|
99
|
+
* `aborted` flips to true when an operator cancels the run via
|
|
100
|
+
* `POST /__blok/runs/:runId/cancel` while it's in `running` status.
|
|
101
|
+
*
|
|
102
|
+
* Nodes that perform long-running work (loops, fetch, db queries)
|
|
103
|
+
* should consult `ctx.signal.aborted` periodically and abort early
|
|
104
|
+
* — or pass the signal to fetch/abort-aware APIs:
|
|
105
|
+
*
|
|
106
|
+
* await fetch(url, { signal: ctx.signal });
|
|
107
|
+
* if (ctx.signal?.aborted) throw new Error("aborted");
|
|
108
|
+
*
|
|
109
|
+
* Always present on contexts created by `TriggerBase.createContext`.
|
|
110
|
+
* Optional on the type for back-compat with hand-built contexts in
|
|
111
|
+
* tests.
|
|
112
|
+
*/
|
|
113
|
+
signal?: AbortSignal;
|
|
23
114
|
_PRIVATE_: unknown;
|
|
24
115
|
};
|
|
25
116
|
export default Context;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StateContext — accumulated step outputs for a single workflow run.
|
|
3
|
+
*
|
|
4
|
+
* Every step's `result.data` lands here under the step's `id` (or its
|
|
5
|
+
* `as` override) automatically. Steps marked `ephemeral: true` skip
|
|
6
|
+
* persistence; steps marked `spread: true` shallow-merge their result
|
|
7
|
+
* keys into state.
|
|
8
|
+
*
|
|
9
|
+
* Read via `ctx.state[stepId]` or `$.state[stepId]` from a workflow's
|
|
10
|
+
* `inputs`. Always initialized to `{}` at run start — never undefined.
|
|
11
|
+
*
|
|
12
|
+
* Aliased by `ctx.vars` for backward compatibility with v1 workflows.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ctx.state["fetch-users"] // the data returned by the fetch-users step
|
|
16
|
+
* ctx.state.user // when a step has `as: "user"`
|
|
17
|
+
*/
|
|
18
|
+
type StateContext = {
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
export default StateContext;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StateContext.js","sourceRoot":"","sources":["../../src/types/StateContext.ts"],"names":[],"mappings":""}
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* VarsContext — accumulated step outputs for a single workflow run.
|
|
3
|
+
*
|
|
4
|
+
* **Legacy alias for {@link StateContext}.** The two types describe the
|
|
5
|
+
* same underlying object (`ctx.state` and `ctx.vars` are aliases). v2
|
|
6
|
+
* code should prefer `ctx.state` / `StateContext`.
|
|
7
|
+
*
|
|
8
|
+
* Values can be any JSON-serializable shape — a step's output is whatever
|
|
9
|
+
* its node returned. The strict `ParamsDictionary` shape from earlier
|
|
10
|
+
* versions of Blok was inaccurate; real workflows have always stored
|
|
11
|
+
* arbitrary objects, arrays, primitives, etc. here.
|
|
12
|
+
*
|
|
13
|
+
* @deprecated Prefer {@link StateContext}.
|
|
14
|
+
*/
|
|
2
15
|
type VarsContext = {
|
|
3
|
-
[key: string]:
|
|
16
|
+
[key: string]: unknown;
|
|
4
17
|
};
|
|
5
18
|
export default VarsContext;
|
package/dist/utils/Mapper.d.ts
CHANGED
|
@@ -1,10 +1,119 @@
|
|
|
1
1
|
import type Context from "../types/Context";
|
|
2
2
|
import type ParamsDictionary from "../types/ParamsDictionary";
|
|
3
|
+
/**
|
|
4
|
+
* Mapper — the workflow input resolver.
|
|
5
|
+
*
|
|
6
|
+
* Every step's `inputs` object is walked by `replaceObjectStrings`
|
|
7
|
+
* before the step runs (see `NodeBase.process` → `blueprintMapper`).
|
|
8
|
+
* Two template syntaxes are recognised:
|
|
9
|
+
*
|
|
10
|
+
* 1. **`${path.to.value}`** — interpolated string placeholder.
|
|
11
|
+
* Resolved via lodash `_.get(data, key)` first, with a JS-eval
|
|
12
|
+
* fallback when the key is not in `data`. Multiple placeholders
|
|
13
|
+
* in one string are concatenated.
|
|
14
|
+
*
|
|
15
|
+
* 2. **`"js/..."`** — full-string JS expression. The string is
|
|
16
|
+
* replaced ENTIRELY by the result of evaluating the expression
|
|
17
|
+
* (after stripping the `js/` prefix) against the live `ctx`.
|
|
18
|
+
* Returns whatever value the expression produces (string, number,
|
|
19
|
+
* object, array, etc.) — preserves type fidelity end-to-end.
|
|
20
|
+
*
|
|
21
|
+
* Both syntaxes evaluate inside a sandboxed `Function` with these
|
|
22
|
+
* names in scope: `ctx`, `data`, `func`, `vars`. (Symmetric scope
|
|
23
|
+
* across both syntaxes since v0.3.x — pre-v0.3.x `${...}` evaluator
|
|
24
|
+
* lacked `func`+`vars`, leading to surprising scope mismatches.)
|
|
25
|
+
*
|
|
26
|
+
* ## Failure modes — see {@link MapperResolutionError}
|
|
27
|
+
*
|
|
28
|
+
* Resolution failures (typo, undefined access, syntax error) used to
|
|
29
|
+
* be swallowed silently with a noisy `console.log("Mapper Error N", e)`
|
|
30
|
+
* — and worse, the unresolved expression string passed through to the
|
|
31
|
+
* node, producing silent miscompiles downstream. Since v0.3.x the
|
|
32
|
+
* Mapper packages every failure in a `MapperResolutionError` with full
|
|
33
|
+
* context (workflow, step, expression, underlying cause + heuristic
|
|
34
|
+
* hint) and routes it according to `BLOK_MAPPER_MODE`:
|
|
35
|
+
*
|
|
36
|
+
* - `"warn"` (default) — log via `ctx.logger.logLevel("warn", ...)`,
|
|
37
|
+
* pass through the original string. Backward-compatible diagnostics.
|
|
38
|
+
* - `"strict"` — throw the error, fail the step fast. **Recommended
|
|
39
|
+
* for production.**
|
|
40
|
+
* - `"silent"` — full suppression. Tests / opt-out only.
|
|
41
|
+
*
|
|
42
|
+
* ## Bug fixes shipped alongside the diagnostic upgrade (v0.3.x)
|
|
43
|
+
*
|
|
44
|
+
* - **Falsy values now preserved** — `_.get(data, key) || runJs(...)`
|
|
45
|
+
* used to fall through to `runJs` when the lookup returned `0`,
|
|
46
|
+
* `false`, `null`, or `""` (all valid values incorrectly treated
|
|
47
|
+
* as missing). Now uses an explicit `=== undefined` check.
|
|
48
|
+
* - **Object interpolation now JSON-encodes** — `value as string`
|
|
49
|
+
* used to produce `"[object Object]"` for object values. Now
|
|
50
|
+
* round-trips via `JSON.stringify`.
|
|
51
|
+
* - **`js/` prefix stripping** uses `slice(3)` instead of
|
|
52
|
+
* `replace("js/", "")` (the latter only strips the FIRST
|
|
53
|
+
* occurrence — fragile if the expression itself contained `js/`).
|
|
54
|
+
*/
|
|
55
|
+
/**
|
|
56
|
+
* How the Mapper reacts to expression resolution failures. Read from
|
|
57
|
+
* the `BLOK_MAPPER_MODE` env var at every call (no caching) so unit
|
|
58
|
+
* tests can flip the mode between cases.
|
|
59
|
+
*/
|
|
60
|
+
export type MapperMode = "warn" | "strict" | "silent";
|
|
3
61
|
declare class Mapper {
|
|
62
|
+
/**
|
|
63
|
+
* Walk an object recursively, resolving every string value via
|
|
64
|
+
* `replaceString`. Mutates in place. Used by `NodeBase.process` to
|
|
65
|
+
* resolve a step's `inputs` against the live `ctx` before the
|
|
66
|
+
* step runs.
|
|
67
|
+
*
|
|
68
|
+
* Object/array values are recursed into; primitive non-string
|
|
69
|
+
* values are left untouched. Null values are NOT recursed (avoids
|
|
70
|
+
* a TypeError on `for (const k in null)`).
|
|
71
|
+
*/
|
|
4
72
|
replaceObjectStrings(obj: ParamsDictionary, ctx: Context, data: ParamsDictionary): void;
|
|
5
|
-
|
|
6
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Resolve a single string. Returns `unknown` because a `js/...`
|
|
75
|
+
* expression may yield any value (number, object, array, etc.) —
|
|
76
|
+
* type fidelity is preserved across the resolver boundary.
|
|
77
|
+
*
|
|
78
|
+
* Pre-v0.3.x return was typed as `string` via `as string` cast
|
|
79
|
+
* which was a type lie; downstream consumers received the actual
|
|
80
|
+
* runtime value but couldn't see it through the type system.
|
|
81
|
+
*/
|
|
82
|
+
replaceString: (strData: string, ctx: Context, data: ParamsDictionary) => unknown;
|
|
83
|
+
/**
|
|
84
|
+
* Resolve a `${path}` expression. Lodash lookup first; JS-eval
|
|
85
|
+
* fallback when the path is not in `data`. Returns the resolved
|
|
86
|
+
* value OR the failure sentinel.
|
|
87
|
+
*/
|
|
88
|
+
private resolveTemplateExpression;
|
|
89
|
+
/**
|
|
90
|
+
* Evaluate a `js/...` full-string expression. Returns whatever the
|
|
91
|
+
* expression produces (any type), or — in warn/silent mode on
|
|
92
|
+
* failure — the original literal `js/...` string.
|
|
93
|
+
*
|
|
94
|
+
* Strict-mode failures throw `MapperResolutionError`.
|
|
95
|
+
*/
|
|
7
96
|
private jsMapper;
|
|
97
|
+
/**
|
|
98
|
+
* Apply the configured mode (`BLOK_MAPPER_MODE`) to a resolution
|
|
99
|
+
* failure. In strict mode, the error escapes here and propagates
|
|
100
|
+
* up through `replaceString` → `NodeBase.blueprintMapper` →
|
|
101
|
+
* `NodeBase.process` → step error envelope.
|
|
102
|
+
*/
|
|
103
|
+
private handleResolutionError;
|
|
104
|
+
/**
|
|
105
|
+
* Sandboxed JS evaluation. Compiles the expression as a function
|
|
106
|
+
* body returning the expression value; binds `ctx`, `data`, `func`,
|
|
107
|
+
* `vars` as positional arguments; runs in `"use strict"` mode.
|
|
108
|
+
*
|
|
109
|
+
* Throws on any evaluation error (typo, undefined access, syntax,
|
|
110
|
+
* unknown identifier). Callers wrap in try/catch and translate to
|
|
111
|
+
* `MapperResolutionError`.
|
|
112
|
+
*
|
|
113
|
+
* Public via the prototype but documented as internal — the only
|
|
114
|
+
* supported call sites are inside this class.
|
|
115
|
+
*/
|
|
116
|
+
private runJs;
|
|
8
117
|
}
|
|
9
118
|
declare const _default: Mapper;
|
|
10
119
|
export default _default;
|
package/dist/utils/Mapper.js
CHANGED
|
@@ -1,55 +1,288 @@
|
|
|
1
1
|
import _ from "lodash";
|
|
2
|
+
import { MapperResolutionError } from "./MapperResolutionError";
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// Internal sentinels + helpers
|
|
5
|
+
// =============================================================================
|
|
6
|
+
/**
|
|
7
|
+
* Returned by the template-resolution path to signal "this placeholder
|
|
8
|
+
* could not be resolved; leave the literal `${...}` in place". Using a
|
|
9
|
+
* Symbol avoids ambiguity with the legitimate `undefined` value an
|
|
10
|
+
* expression might produce.
|
|
11
|
+
*/
|
|
12
|
+
const TEMPLATE_RESOLUTION_FAILED = Symbol("TEMPLATE_RESOLUTION_FAILED");
|
|
13
|
+
function readMode() {
|
|
14
|
+
const raw = process.env.BLOK_MAPPER_MODE;
|
|
15
|
+
if (raw === "strict")
|
|
16
|
+
return "strict";
|
|
17
|
+
if (raw === "silent")
|
|
18
|
+
return "silent";
|
|
19
|
+
return "warn";
|
|
20
|
+
}
|
|
21
|
+
function readStepContext(ctx) {
|
|
22
|
+
const ctxAny = ctx;
|
|
23
|
+
const stepInfo = ctxAny._stepInfo;
|
|
24
|
+
const stepName = typeof stepInfo?.name === "string" ? stepInfo.name : undefined;
|
|
25
|
+
const workflowName = typeof ctx.workflow_name === "string" ? ctx.workflow_name : undefined;
|
|
26
|
+
return { workflowName, stepName };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build the actionable error message — every line carries information
|
|
30
|
+
* a developer can act on: WHERE it failed, WHAT failed, WHY it likely
|
|
31
|
+
* failed, and HOW to fix it.
|
|
32
|
+
*/
|
|
33
|
+
function buildErrorMessage(opts) {
|
|
34
|
+
const wf = opts.workflowName ?? "<unknown workflow>";
|
|
35
|
+
const step = opts.stepName ?? "<unknown step>";
|
|
36
|
+
const literal = opts.syntax === "js" ? `js/${opts.expression}` : `\${${opts.expression}}`;
|
|
37
|
+
const causeMsg = opts.cause instanceof Error ? opts.cause.message : String(opts.cause);
|
|
38
|
+
const hint = guessHint(opts.expression, causeMsg);
|
|
39
|
+
const lines = [
|
|
40
|
+
`[blok][mapper] Failed to resolve \`${literal}\` in step "${step}" of workflow "${wf}"`,
|
|
41
|
+
` underlying: ${causeMsg}`,
|
|
42
|
+
];
|
|
43
|
+
if (hint)
|
|
44
|
+
lines.push(` hint: ${hint}`);
|
|
45
|
+
lines.push(" fix: verify the referenced ctx path exists at run time. Set BLOK_MAPPER_MODE=strict in production to fail fast on these errors.");
|
|
46
|
+
return lines.join("\n");
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Heuristic — translate common JS evaluation errors into actionable
|
|
50
|
+
* developer hints. Returns `null` when the error doesn't match any
|
|
51
|
+
* known pattern (the underlying message is still surfaced).
|
|
52
|
+
*/
|
|
53
|
+
function guessHint(expression, errorMessage) {
|
|
54
|
+
// Most common case — `Cannot read properties of undefined (reading 'X')`
|
|
55
|
+
// or the older `Cannot read property 'X' of undefined`. Both forms
|
|
56
|
+
// appear depending on Node/Bun version.
|
|
57
|
+
const undefMatch = errorMessage.match(/Cannot read propert(?:y '(\w+)' of undefined|ies of undefined \(reading '(\w+)'\))/);
|
|
58
|
+
if (undefMatch) {
|
|
59
|
+
const prop = undefMatch[1] ?? undefMatch[2];
|
|
60
|
+
const segments = expression.split(".");
|
|
61
|
+
const parent = segments.slice(0, -1).join(".") || expression;
|
|
62
|
+
return `the path \`${parent}\` is undefined or doesn't have a "${prop}" field at run time. Check the trigger payload (ctx.req.body) or the upstream step's output (ctx.state.<id>).`;
|
|
63
|
+
}
|
|
64
|
+
// Identifier not in scope — only `ctx`, `data`, `func`, `vars` are
|
|
65
|
+
// available inside expressions.
|
|
66
|
+
const refMatch = errorMessage.match(/(\w+) is not defined/);
|
|
67
|
+
if (refMatch) {
|
|
68
|
+
return `\`${refMatch[1]}\` is not in scope. Available identifiers inside expressions: ctx, data, func, vars.`;
|
|
69
|
+
}
|
|
70
|
+
// Syntax error.
|
|
71
|
+
if (/SyntaxError/.test(errorMessage) || /Unexpected token/.test(errorMessage)) {
|
|
72
|
+
return "the expression is not valid JavaScript. Check for typos, unmatched parentheses, or stray characters.";
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Route a warn-mode log line to the best available sink. Prefers
|
|
78
|
+
* `ctx.logger.logLevel("warn", ...)` so the warning lands in BOTH the
|
|
79
|
+
* console (via DefaultLogger) AND Studio's log viewer (via
|
|
80
|
+
* TracingLogger.normalizeLevel → addLog). Falls back to console.warn
|
|
81
|
+
* when no logger is attached (early-boot or hand-rolled test ctx).
|
|
82
|
+
*/
|
|
83
|
+
function logViaCtxOrConsole(ctx, message) {
|
|
84
|
+
const logger = ctx.logger;
|
|
85
|
+
if (logger?.logLevel) {
|
|
86
|
+
try {
|
|
87
|
+
logger.logLevel("warn", message);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// fall through to console.warn — never let logging itself crash a step.
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (logger?.log) {
|
|
95
|
+
try {
|
|
96
|
+
logger.log(message);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// fall through
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
console.warn(message);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Coerce a resolved value to its string form for `${...}` interpolation.
|
|
107
|
+
*
|
|
108
|
+
* Pre-v0.3.x used `value as string` which fell back to `String(value)`
|
|
109
|
+
* via implicit coercion — producing `"[object Object]"` for any object/
|
|
110
|
+
* array. Now JSON-encodes complex values so interpolated strings
|
|
111
|
+
* preserve information instead of silently miscompiling.
|
|
112
|
+
*
|
|
113
|
+
* - `null` / `undefined` → empty string (matches user intent for
|
|
114
|
+
* missing optional fields)
|
|
115
|
+
* - `string` → identity
|
|
116
|
+
* - `number` / `boolean` / `bigint` → `String(value)`
|
|
117
|
+
* - everything else → `JSON.stringify(value)` with a defensive fallback
|
|
118
|
+
* to `String(value)` for circular structures.
|
|
119
|
+
*/
|
|
120
|
+
function toInterpolatedString(value) {
|
|
121
|
+
if (value === null || value === undefined)
|
|
122
|
+
return "";
|
|
123
|
+
if (typeof value === "string")
|
|
124
|
+
return value;
|
|
125
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
126
|
+
return String(value);
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
return JSON.stringify(value) ?? String(value);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// JSON.stringify throws on circular references — degrade gracefully.
|
|
133
|
+
return String(value);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// =============================================================================
|
|
137
|
+
// Mapper
|
|
138
|
+
// =============================================================================
|
|
2
139
|
class Mapper {
|
|
140
|
+
/**
|
|
141
|
+
* Walk an object recursively, resolving every string value via
|
|
142
|
+
* `replaceString`. Mutates in place. Used by `NodeBase.process` to
|
|
143
|
+
* resolve a step's `inputs` against the live `ctx` before the
|
|
144
|
+
* step runs.
|
|
145
|
+
*
|
|
146
|
+
* Object/array values are recursed into; primitive non-string
|
|
147
|
+
* values are left untouched. Null values are NOT recursed (avoids
|
|
148
|
+
* a TypeError on `for (const k in null)`).
|
|
149
|
+
*/
|
|
3
150
|
replaceObjectStrings(obj, ctx, data) {
|
|
4
151
|
for (const key in obj) {
|
|
5
152
|
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
6
153
|
const value = obj[key];
|
|
7
154
|
if (typeof value === "string") {
|
|
155
|
+
// `ParamsDictionary[key]` is typed `string`, but the
|
|
156
|
+
// runtime contract has always been "the resolved value
|
|
157
|
+
// keeps its actual type" (so `js/ctx.req.body.count`
|
|
158
|
+
// produces a number, not the string "42"). The
|
|
159
|
+
// `as unknown as string` boundary cast acknowledges
|
|
160
|
+
// that the type system can't express this widening
|
|
161
|
+
// without changing the global ParamsDictionary shape
|
|
162
|
+
// (a much larger refactor).
|
|
8
163
|
obj[key] = this.replaceString(value, ctx, data);
|
|
9
164
|
}
|
|
10
|
-
else if (typeof value === "object") {
|
|
165
|
+
else if (value !== null && typeof value === "object") {
|
|
11
166
|
this.replaceObjectStrings(value, ctx, data);
|
|
12
167
|
}
|
|
13
168
|
}
|
|
14
169
|
}
|
|
15
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Resolve a single string. Returns `unknown` because a `js/...`
|
|
173
|
+
* expression may yield any value (number, object, array, etc.) —
|
|
174
|
+
* type fidelity is preserved across the resolver boundary.
|
|
175
|
+
*
|
|
176
|
+
* Pre-v0.3.x return was typed as `string` via `as string` cast
|
|
177
|
+
* which was a type lie; downstream consumers received the actual
|
|
178
|
+
* runtime value but couldn't see it through the type system.
|
|
179
|
+
*/
|
|
16
180
|
replaceString = (strData, ctx, data) => {
|
|
17
181
|
let str = strData;
|
|
18
|
-
//
|
|
19
|
-
// throw new Error("Input too long");
|
|
20
|
-
// }
|
|
182
|
+
// === 1. `${path}` template interpolation ===
|
|
21
183
|
const regex = /\${(.*?)}/g;
|
|
22
184
|
const matches = str.match(regex);
|
|
23
185
|
if (matches) {
|
|
24
186
|
for (const match of matches) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
str = str.replace(match, value);
|
|
30
|
-
}
|
|
31
|
-
catch (e) {
|
|
32
|
-
console.log("Mapper Error 1", e);
|
|
187
|
+
const key = match.slice(2, -1); // strip `${` and `}`
|
|
188
|
+
const value = this.resolveTemplateExpression(key, ctx, data);
|
|
189
|
+
if (value !== TEMPLATE_RESOLUTION_FAILED) {
|
|
190
|
+
str = str.replace(match, toInterpolatedString(value));
|
|
33
191
|
}
|
|
192
|
+
// On failure: leave the literal `${...}` placeholder in
|
|
193
|
+
// place. The failure was already reported per the active
|
|
194
|
+
// mode (warn/strict/silent).
|
|
34
195
|
}
|
|
35
196
|
}
|
|
36
|
-
|
|
37
|
-
return
|
|
197
|
+
// === 2. `js/...` full-string evaluation ===
|
|
198
|
+
return this.jsMapper(str, ctx, data);
|
|
38
199
|
};
|
|
39
|
-
|
|
40
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Resolve a `${path}` expression. Lodash lookup first; JS-eval
|
|
202
|
+
* fallback when the path is not in `data`. Returns the resolved
|
|
203
|
+
* value OR the failure sentinel.
|
|
204
|
+
*/
|
|
205
|
+
resolveTemplateExpression(key, ctx, data) {
|
|
206
|
+
// Lodash lookup. Use explicit `=== undefined` instead of `||`
|
|
207
|
+
// so falsy-but-valid values (0, false, "", null) are preserved.
|
|
208
|
+
const lookupValue = _.get(data, key);
|
|
209
|
+
if (lookupValue !== undefined)
|
|
210
|
+
return lookupValue;
|
|
211
|
+
// Fallback to JS evaluation against ctx. Symmetric with jsMapper:
|
|
212
|
+
// pass `ctx.func` and `ctx.vars` so `${func.X}` and `${vars.X}`
|
|
213
|
+
// have the same scope as `js/func.X` / `js/vars.X`.
|
|
214
|
+
try {
|
|
215
|
+
return this.runJs(key, ctx, data, (ctx.func ?? {}), (ctx.vars ?? {}));
|
|
216
|
+
}
|
|
217
|
+
catch (cause) {
|
|
218
|
+
const stepCtx = readStepContext(ctx);
|
|
219
|
+
const error = new MapperResolutionError(buildErrorMessage({ expression: key, syntax: "template", ...stepCtx, cause }), { expression: key, syntax: "template", ...stepCtx, cause });
|
|
220
|
+
this.handleResolutionError(ctx, error);
|
|
221
|
+
return TEMPLATE_RESOLUTION_FAILED;
|
|
222
|
+
}
|
|
41
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Evaluate a `js/...` full-string expression. Returns whatever the
|
|
226
|
+
* expression produces (any type), or — in warn/silent mode on
|
|
227
|
+
* failure — the original literal `js/...` string.
|
|
228
|
+
*
|
|
229
|
+
* Strict-mode failures throw `MapperResolutionError`.
|
|
230
|
+
*/
|
|
42
231
|
jsMapper(str, ctx, data) {
|
|
232
|
+
if (typeof str !== "string" || !str.startsWith("js/"))
|
|
233
|
+
return str;
|
|
234
|
+
// `slice(3)` strips exactly the leading `js/` prefix.
|
|
235
|
+
// Pre-v0.3.x used `replace("js/", "")` which only strips the
|
|
236
|
+
// FIRST occurrence — fragile if the expression itself contained
|
|
237
|
+
// the substring `js/` (e.g., a URL like `https://js/foo`).
|
|
238
|
+
const expression = str.slice(3);
|
|
43
239
|
try {
|
|
44
|
-
|
|
45
|
-
const fn = str.replace("js/", "");
|
|
46
|
-
return this.runJs(fn, ctx, data, ctx.func, ctx.vars);
|
|
47
|
-
}
|
|
240
|
+
return this.runJs(expression, ctx, data, (ctx.func ?? {}), (ctx.vars ?? {}));
|
|
48
241
|
}
|
|
49
|
-
catch (
|
|
50
|
-
|
|
242
|
+
catch (cause) {
|
|
243
|
+
const stepCtx = readStepContext(ctx);
|
|
244
|
+
const error = new MapperResolutionError(buildErrorMessage({ expression, syntax: "js", ...stepCtx, cause }), {
|
|
245
|
+
expression,
|
|
246
|
+
syntax: "js",
|
|
247
|
+
...stepCtx,
|
|
248
|
+
cause,
|
|
249
|
+
});
|
|
250
|
+
this.handleResolutionError(ctx, error);
|
|
251
|
+
return str; // pre-v0.3.x behavior — pass through the literal string
|
|
51
252
|
}
|
|
52
|
-
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Apply the configured mode (`BLOK_MAPPER_MODE`) to a resolution
|
|
256
|
+
* failure. In strict mode, the error escapes here and propagates
|
|
257
|
+
* up through `replaceString` → `NodeBase.blueprintMapper` →
|
|
258
|
+
* `NodeBase.process` → step error envelope.
|
|
259
|
+
*/
|
|
260
|
+
handleResolutionError(ctx, error) {
|
|
261
|
+
const mode = readMode();
|
|
262
|
+
if (mode === "strict")
|
|
263
|
+
throw error;
|
|
264
|
+
if (mode === "silent")
|
|
265
|
+
return;
|
|
266
|
+
// mode === "warn"
|
|
267
|
+
logViaCtxOrConsole(ctx, error.message);
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Sandboxed JS evaluation. Compiles the expression as a function
|
|
271
|
+
* body returning the expression value; binds `ctx`, `data`, `func`,
|
|
272
|
+
* `vars` as positional arguments; runs in `"use strict"` mode.
|
|
273
|
+
*
|
|
274
|
+
* Throws on any evaluation error (typo, undefined access, syntax,
|
|
275
|
+
* unknown identifier). Callers wrap in try/catch and translate to
|
|
276
|
+
* `MapperResolutionError`.
|
|
277
|
+
*
|
|
278
|
+
* Public via the prototype but documented as internal — the only
|
|
279
|
+
* supported call sites are inside this class.
|
|
280
|
+
*/
|
|
281
|
+
runJs(str, ctx, data = {}, func = {}, vars = {}) {
|
|
282
|
+
// Function constructor (NOT eval) — creates a fresh function
|
|
283
|
+
// scope without lexical access to the surrounding module. Same
|
|
284
|
+
// security profile as the v1 implementation.
|
|
285
|
+
return Function("ctx", "data", "func", "vars", `"use strict";return (${str});`)(ctx, data, func, vars);
|
|
53
286
|
}
|
|
54
287
|
}
|
|
55
288
|
export default new Mapper();
|
package/dist/utils/Mapper.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Mapper.js","sourceRoot":"","sources":["../../src/utils/Mapper.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"Mapper.js","sourceRoot":"","sources":["../../src/utils/Mapper.ts"],"names":[],"mappings":"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"}
|