@uipath/maestro-builder-sdk 6.17.5 → 6.18.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/dist/bindings-v2.js +15 -17
- package/dist/bpmn/bpmn-sdk.js +3 -2
- package/dist/bpmn/check.js +3 -2
- package/dist/bpmn/decompile.js +123 -137
- package/dist/bpmn/intsvc.js +7 -2
- package/dist/bpmn/serialize.js +1 -1
- package/dist/bpmn/typed-node.js +5 -4
- package/dist/case/compile-cli.js +1 -3
- package/dist/case/decompile.js +103 -109
- package/dist/case/entry-points.js +2 -1
- package/dist/case/merge.js +3 -5
- package/dist/case/serialize.js +1 -1
- package/dist/check.js +26 -10
- package/dist/core/ceql.js +5 -2
- package/dist/core/connector-inputs.js +4 -4
- package/dist/core/event-checks.js +17 -2
- package/dist/core/event-filters.d.ts +38 -4
- package/dist/core/event-filters.js +63 -7
- package/dist/core/expr.d.ts +1 -1
- package/dist/core/expr.js +3 -3
- package/dist/core/json-file.d.ts +2 -0
- package/dist/core/json-file.js +4 -0
- package/dist/core/library.js +2 -1
- package/dist/core/node-envelope.d.ts +1 -0
- package/dist/core/node-envelope.js +1 -1
- package/dist/core/own-entry.d.ts +9 -0
- package/dist/core/own-entry.js +11 -0
- package/dist/core/ts-literal.d.ts +22 -0
- package/dist/core/ts-literal.js +37 -0
- package/dist/core/typed-raw-node.js +4 -3
- package/dist/decompile.js +272 -300
- package/dist/merge.js +10 -12
- package/dist/registry/compat/pystr.d.ts +2 -0
- package/dist/registry/compat/pystr.js +35 -0
- package/dist/registry/compat/pyvalue.d.ts +16 -0
- package/dist/registry/compat/pyvalue.js +35 -0
- package/dist/registry/generators/markdown/pyvalue.d.ts +1 -4
- package/dist/registry/generators/markdown/pyvalue.js +2 -30
- package/dist/registry/generators/markdown/sections/inputs.js +3 -2
- package/dist/registry/generators/type-tree.d.ts +1 -7
- package/dist/registry/generators/type-tree.js +5 -22
- package/dist/registry/library-build/build.js +6 -6
- package/dist/registry/library-build/canonical.js +25 -25
- package/dist/registry/library-build/context.js +5 -5
- package/dist/registry/library-build/enrich.js +18 -18
- package/dist/registry/library-build/events.js +25 -24
- package/dist/registry/library-build/generic-expand.js +21 -20
- package/dist/registry/library-build/plan.js +8 -8
- package/dist/registry/library-build/py.d.ts +3 -10
- package/dist/registry/library-build/py.js +9 -52
- package/dist/registry/library-build/schema-action.js +6 -6
- package/dist/registry/prepare/event.js +2 -2
- package/dist/registry/prepare/source-import.js +2 -9
- package/dist/registry/prepare/source-labels.js +2 -9
- package/dist/registry/prepare/support.d.ts +2 -6
- package/dist/registry/prepare/support.js +3 -58
- package/dist/registry/pull-cli.js +6 -14
- package/dist/registry/search-cli.js +2 -2
- package/dist/schema-version.js +0 -1
- package/dist/serialize.js +86 -76
- package/package.json +2 -2
package/dist/case/merge.js
CHANGED
|
@@ -48,9 +48,7 @@
|
|
|
48
48
|
*/
|
|
49
49
|
import { collectPreservation } from './decompile.js';
|
|
50
50
|
import { applyPreservation } from './serialize.js';
|
|
51
|
-
|
|
52
|
-
return JSON.parse(JSON.stringify(value));
|
|
53
|
-
}
|
|
51
|
+
import { jsonClone } from '../core/json-file.js';
|
|
54
52
|
/** Stage labels in a document, in order. */
|
|
55
53
|
function stageLabels(document) {
|
|
56
54
|
return (document.nodes ?? [])
|
|
@@ -102,11 +100,11 @@ function warnOrphanedIdentities(preservation, edited, warn) {
|
|
|
102
100
|
export function mergeCase(original, edited, options = {}) {
|
|
103
101
|
const preservation = collectPreservation(original);
|
|
104
102
|
if (!preservation)
|
|
105
|
-
return
|
|
103
|
+
return jsonClone(edited);
|
|
106
104
|
if (options.warn)
|
|
107
105
|
warnOrphanedIdentities(preservation, edited, options.warn);
|
|
108
106
|
// `applyPreservation` is what `compile` runs with the payload a source
|
|
109
107
|
// carries. Handing it the ORIGINAL's payload and the EDITED graph is the whole
|
|
110
108
|
// merge: same operation, different provenance.
|
|
111
|
-
return applyPreservation(
|
|
109
|
+
return applyPreservation(jsonClone(edited), preservation, { overwrite: true });
|
|
112
110
|
}
|
package/dist/case/serialize.js
CHANGED
|
@@ -1414,7 +1414,7 @@ function emitCaseExit(c, i, ids, resolver) {
|
|
|
1414
1414
|
}
|
|
1415
1415
|
/** One `slaRules[]` entry: the deadline + its escalations. `id` (+ `displayName`
|
|
1416
1416
|
* when named) is preallocated so a `sla-status-change` rule can reference it. */
|
|
1417
|
-
function emitSla(sla, index, count,
|
|
1417
|
+
function emitSla(sla, index, count, _ids, resolver) {
|
|
1418
1418
|
const displayName = sla.displayName ?? (index === count - 1 ? 'Default SLA' : `Conditional SLA ${count - index - 1}`);
|
|
1419
1419
|
const out = {
|
|
1420
1420
|
id: resolver.slaId.get(sla),
|
package/dist/check.js
CHANGED
|
@@ -25,6 +25,7 @@ import { stopsAtEnd } from './flow-step-tree.js';
|
|
|
25
25
|
import { FLOW_SCHEMA_VERSIONS } from './format-profile.js';
|
|
26
26
|
import { compareSchemaVersions, schemaVersionRefusal } from './schema-version.js';
|
|
27
27
|
import { planFlowGlobals, planSharedInputs, sharedInputRoots } from './flow-variables.js';
|
|
28
|
+
import { ownEntry } from './core/own-entry.js';
|
|
28
29
|
export function check(built, opts = {}) {
|
|
29
30
|
let diags = [];
|
|
30
31
|
const uses = collectConnectionUses(() => { diags = checkFlow(built, [], opts); });
|
|
@@ -1094,7 +1095,7 @@ function checkFlow(built, ancestors, opts = {}) {
|
|
|
1094
1095
|
// per-family rules below, because the envelope carries the same fields
|
|
1095
1096
|
// whatever the node publishes on its success path; which VARIABLE holds it
|
|
1096
1097
|
// is a per-family runtime boundary `serialize` rewrites, not something the
|
|
1097
|
-
// author writes (`
|
|
1098
|
+
// author writes (`ERROR_ENVELOPE_VAR`).
|
|
1098
1099
|
if (field === 'error') {
|
|
1099
1100
|
const tail = rest ? rest.slice(1).split('.')[0] : undefined;
|
|
1100
1101
|
if (tail !== undefined)
|
|
@@ -2394,14 +2395,16 @@ function checkVoice(step, kind, inputs, diags) {
|
|
|
2394
2395
|
'gpt-realtime-2': ['alloy', 'ash', 'ballad', 'coral', 'echo', 'sage', 'shimmer', 'verse'],
|
|
2395
2396
|
};
|
|
2396
2397
|
const model = typeof v.model === 'string' ? v.model : undefined;
|
|
2397
|
-
|
|
2398
|
+
// An own-key read: `in` also matched 'toString', and `PERSONAS[model].includes` then threw.
|
|
2399
|
+
const personas = model !== undefined ? ownEntry(PERSONAS, model) : undefined;
|
|
2400
|
+
if (model !== undefined && personas === undefined) {
|
|
2398
2401
|
at('VOICE_MODEL_UNKNOWN', `voiceAgent step "${step}" names the voice model ${JSON.stringify(model)}. The platform's catalog `
|
|
2399
2402
|
+ `today is ${Object.keys(PERSONAS).map((m) => `'${m}'`).join(' and ')} — a voice model, not one of `
|
|
2400
2403
|
+ `the text models an inline agent takes.`);
|
|
2401
2404
|
}
|
|
2402
|
-
else if (typeof v.persona === 'string' &&
|
|
2405
|
+
else if (typeof v.persona === 'string' && personas !== undefined && !personas.includes(v.persona)) {
|
|
2403
2406
|
at('VOICE_PERSONA_UNKNOWN', `voiceAgent step "${step}"'s persona ${JSON.stringify(v.persona)} is not one of `
|
|
2404
|
-
+ `${JSON.stringify(model)}'s voices (${
|
|
2407
|
+
+ `${JSON.stringify(model)}'s voices (${personas.join(', ')}). A persona belongs to its model.`);
|
|
2405
2408
|
}
|
|
2406
2409
|
}
|
|
2407
2410
|
}
|
|
@@ -2813,7 +2816,7 @@ function checkAgenticProcess(step, inputs, diags) {
|
|
|
2813
2816
|
+ `\`form: 'flow'\` if the sibling is a Flow.`, `location: 'published', folderPath: 'Shared/<folder>'`);
|
|
2814
2817
|
}
|
|
2815
2818
|
if (inSolution && blank(inputs?.projectId)) {
|
|
2816
|
-
const folder = (AGENTIC_PROCESS_FORMS
|
|
2819
|
+
const folder = (ownEntry(AGENTIC_PROCESS_FORMS, inputs?.form ?? 'bpmn') ?? AGENTIC_PROCESS_FORMS.bpmn).solutionFolder;
|
|
2817
2820
|
at('AGENTIC_LOCAL_NO_PROJECT_ID', `In-solution agentic process step "${step}" has no \`projectId\`. Read \`resource.projectKey\` from `
|
|
2818
2821
|
+ `\`resources/solution_folder/process/${folder}/<project>.json\`.`, `projectId: '<resource.projectKey>'`);
|
|
2819
2822
|
}
|
|
@@ -3605,6 +3608,13 @@ function checkInlineAgent(step, inputs, diags, opts = {}) {
|
|
|
3605
3608
|
at('INLINE_AGENT_ESCALATION_NO_FIELDS', `Inline agent step "${step}"'s quick-form escalation declares no \`fields\` — the reviewer gets an `
|
|
3606
3609
|
+ `empty form.`);
|
|
3607
3610
|
}
|
|
3611
|
+
for (const f of Array.isArray(e.fields) ? e.fields : []) {
|
|
3612
|
+
if (!FORM_FIELD_TYPES.includes(String(f?.type))) {
|
|
3613
|
+
at('INLINE_AGENT_ESCALATION_FIELD_TYPE_UNKNOWN', `Inline agent step "${step}"'s quick-form escalation gives the field "${String(f?.id ?? '?')}" the type `
|
|
3614
|
+
+ `${JSON.stringify(f?.type)}, which the form does not recognize — it would be published as a plain `
|
|
3615
|
+
+ `string. Valid: ${FORM_FIELD_TYPES.join(', ')}.`, formFieldTypeHint(f?.type));
|
|
3616
|
+
}
|
|
3617
|
+
}
|
|
3608
3618
|
continue;
|
|
3609
3619
|
}
|
|
3610
3620
|
if (e?.fields !== undefined) {
|
|
@@ -4440,8 +4450,15 @@ function checkHttp(step, inputs, diags) {
|
|
|
4440
4450
|
}
|
|
4441
4451
|
}
|
|
4442
4452
|
}
|
|
4453
|
+
/** Every FormFieldType, once; `Record<FormFieldType, …>` makes tsc refuse a missing or extra one. */
|
|
4454
|
+
const FORM_FIELD_TYPE_SET = { text: true, number: true, boolean: true, 'date-time': true };
|
|
4443
4455
|
/** Form-field types the platform recognizes; anything else normalizes to text. */
|
|
4444
|
-
const FORM_FIELD_TYPES =
|
|
4456
|
+
const FORM_FIELD_TYPES = Object.keys(FORM_FIELD_TYPE_SET);
|
|
4457
|
+
/** The `suggestion` for an unknown form-field type: the nearest valid one, else `type: 'text'`. */
|
|
4458
|
+
function formFieldTypeHint(type) {
|
|
4459
|
+
const nearest = nearestName(String(type), FORM_FIELD_TYPES);
|
|
4460
|
+
return nearest !== undefined ? `type: '${nearest}'` : `type: 'text'`;
|
|
4461
|
+
}
|
|
4445
4462
|
/** Names the human task's own result already uses — an answer cannot claim one. */
|
|
4446
4463
|
const RESERVED_ANSWER_IDS = new Set(['output', 'status', 'Action']);
|
|
4447
4464
|
/**
|
|
@@ -4717,11 +4734,10 @@ function checkHitl(step, inputs, diags) {
|
|
|
4717
4734
|
return;
|
|
4718
4735
|
}
|
|
4719
4736
|
if (!FORM_FIELD_TYPES.includes(String(f?.type))) {
|
|
4720
|
-
const nearest = nearestName(String(f?.type), FORM_FIELD_TYPES);
|
|
4721
4737
|
at('HITL_FIELD_TYPE_UNKNOWN', `Human task "${step}" gives the form field "${id}" the type ${JSON.stringify(f?.type)}, which `
|
|
4722
4738
|
+ `the platform does not recognize — it normalizes an unknown type to text, so the reviewer `
|
|
4723
4739
|
+ `gets a text box and the value comes back as a string. Valid: `
|
|
4724
|
-
+ `${FORM_FIELD_TYPES.join(', ')}.`,
|
|
4740
|
+
+ `${FORM_FIELD_TYPES.join(', ')}.`, formFieldTypeHint(f?.type));
|
|
4725
4741
|
}
|
|
4726
4742
|
if (isAnswerField(f))
|
|
4727
4743
|
answers++; // an `output`, or an `inOut` whose reviewed value comes back
|
|
@@ -5715,7 +5731,7 @@ function checkStepRefs(built, diags) {
|
|
|
5715
5731
|
}
|
|
5716
5732
|
};
|
|
5717
5733
|
collect(built.steps, undefined, '', undefined);
|
|
5718
|
-
for (const { target,
|
|
5734
|
+
for (const { target, from, after, scope, arm } of found) {
|
|
5719
5735
|
const where = from ? `after "${from}"` : 'at the start of the flow';
|
|
5720
5736
|
const say = (level, code, message, suggestion) => {
|
|
5721
5737
|
diags.push({ level, code, message, step: from ?? 'stepToRef', ...(suggestion ? { suggestion } : {}) });
|
|
@@ -5781,7 +5797,7 @@ function checkStepRefs(built, diags) {
|
|
|
5781
5797
|
* checks and what it does not. It checks the FIELD NAME against the envelope's
|
|
5782
5798
|
* own fields, which are the same on every family. It does NOT police the prefix:
|
|
5783
5799
|
* `.error` vs `.output` is a per-family runtime boundary, measured per family and
|
|
5784
|
-
* rewritten by `serialize` (`
|
|
5800
|
+
* rewritten by `serialize` (`ERROR_ENVELOPE_VAR`), so an author writing `.error`
|
|
5785
5801
|
* is right by construction and an author hand-writing `.output` is caught by
|
|
5786
5802
|
* ERROR_ENVELOPE_VIA_OUTPUT instead.
|
|
5787
5803
|
*
|
package/dist/core/ceql.js
CHANGED
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
* rather than a wrong one.
|
|
34
34
|
*/
|
|
35
35
|
import { stableId } from './stable-id.js';
|
|
36
|
+
import { ownEntry } from './own-entry.js';
|
|
36
37
|
/** Raised when an expression is not CEQL this parser can represent. */
|
|
37
38
|
export class CeqlParseError extends Error {
|
|
38
39
|
expression;
|
|
@@ -128,9 +129,11 @@ function readOperator(s) {
|
|
|
128
129
|
}
|
|
129
130
|
}
|
|
130
131
|
const alias = /^([A-Za-z]+)\b/.exec(s.rest);
|
|
131
|
-
|
|
132
|
+
const word = alias?.[1].toLowerCase();
|
|
133
|
+
const odata = word !== undefined ? ownEntry(ODATA_ALIASES, word) : undefined;
|
|
134
|
+
if (alias && odata) {
|
|
132
135
|
const wrong = alias[1];
|
|
133
|
-
throw new CeqlParseError(`\`${wrong}\` is an OData operator; CEQL uses \`${
|
|
136
|
+
throw new CeqlParseError(`\`${wrong}\` is an OData operator; CEQL uses \`${odata}\`.`, s.src);
|
|
134
137
|
}
|
|
135
138
|
for (const [text, op] of SYMBOL_OPERATORS) {
|
|
136
139
|
if (s.src.startsWith(text, s.pos)) {
|
|
@@ -28,6 +28,8 @@ import { editDistance } from './edit-distance.js';
|
|
|
28
28
|
/** Flow's dialect, re-exported so `serialize.ts` need not reach past this module. */
|
|
29
29
|
export { FLOW_EXPR_DIALECT } from './connector-checks.js';
|
|
30
30
|
import { FLOW_EXPR_DIALECT as FLOW_DIALECT } from './connector-checks.js';
|
|
31
|
+
import { ownEntry } from './own-entry.js';
|
|
32
|
+
import { isRecord } from './node-envelope.js';
|
|
31
33
|
/**
|
|
32
34
|
* Validate a connector's activity inputs against its declared field list and
|
|
33
35
|
* return them ROUTED to the wire slots the platform reads. Catches the three
|
|
@@ -155,7 +157,8 @@ export function buildConnectorInputs(rc, inputs, opts) {
|
|
|
155
157
|
partValues.set(f.name, render(nested.value));
|
|
156
158
|
continue;
|
|
157
159
|
}
|
|
158
|
-
const
|
|
160
|
+
const location = f.location ?? 'body';
|
|
161
|
+
const slot = ownEntry(SLOT_FOR_LOCATION, location) ?? 'bodyParameters';
|
|
159
162
|
routed[slot][f.name] = render(nested.value);
|
|
160
163
|
}
|
|
161
164
|
if (errs.length) {
|
|
@@ -318,9 +321,6 @@ function place(target, parts, index, value) {
|
|
|
318
321
|
target[part.key] = next;
|
|
319
322
|
place(next, parts, index + 1, value);
|
|
320
323
|
}
|
|
321
|
-
function isRecord(value) {
|
|
322
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
323
|
-
}
|
|
324
324
|
function connectorPath(name) {
|
|
325
325
|
return name.split('.').map((raw) => ({
|
|
326
326
|
key: raw.endsWith('[*]') ? raw.slice(0, -3) : raw,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { isLookupToken, resolvedValue, unresolvedLookupMessage, } from './lookups.js';
|
|
22
22
|
import { prepareCommand } from './cli-spelling.js';
|
|
23
|
-
import { EVENT_FILTER_OPERATORS, readEventFilter, eventFilterProblem } from './event-filters.js';
|
|
23
|
+
import { EVENT_FILTER_OPERATORS, readEventFilter, eventFilterProblem, jmesStringProblem } from './event-filters.js';
|
|
24
24
|
import { EVENT_BYOA_UNVERIFIED, byoaUnverified } from './byoa.js';
|
|
25
25
|
/**
|
|
26
26
|
* Ask the library what event parameters a subscription's operation declares.
|
|
@@ -228,6 +228,18 @@ export function checkEventSubscription(subscription, where, at, warn, eventParam
|
|
|
228
228
|
const scopeObject = scopeEntries.find(([k]) => /^(objectName|entityName|object)$/i.test(k))?.[1];
|
|
229
229
|
const object = typeof sub.object === 'string' && sub.object !== '' ? sub.object : undefined;
|
|
230
230
|
const say = warn ?? at;
|
|
231
|
+
// A scope value is folded into the match expression as `k == '<value>'`, so it
|
|
232
|
+
// meets the same JMESPath backslash ambiguity a filter value does. A nested
|
|
233
|
+
// `where` (a dotted parameter written as an object) is checked leaf by leaf.
|
|
234
|
+
const scopeStrings = (value, path) => typeof value === 'string' ? [[path, value]]
|
|
235
|
+
: value && typeof value === 'object' && !Array.isArray(value)
|
|
236
|
+
? Object.entries(value).flatMap(([k, v]) => scopeStrings(v, `${path}.${k}`))
|
|
237
|
+
: [];
|
|
238
|
+
for (const [path, value] of scopeEntries.flatMap(([k, v]) => scopeStrings(v, k))) {
|
|
239
|
+
const ambiguous = jmesStringProblem(value);
|
|
240
|
+
if (ambiguous)
|
|
241
|
+
at('EVENT_FILTER_BACKSLASH', `${where}'s \`where.${path}\`: ${ambiguous}`);
|
|
242
|
+
}
|
|
231
243
|
// The OBJECT half of the contract. A GENERIC event (`record-created` on Data
|
|
232
244
|
// Fabric, Salesforce, ServiceNow, Jira, …) fires for ONE object of the connection
|
|
233
245
|
// and its library entry names none — so `object` is REQUIRED, and its absence is
|
|
@@ -313,8 +325,11 @@ export function checkEventSubscription(subscription, where, at, warn, eventParam
|
|
|
313
325
|
at('EVENT_FILTER_NO_VALUE', `${where}'s filters[${i}] gives \`${keys[0]}\` a value that is not a string, number or boolean.`);
|
|
314
326
|
}
|
|
315
327
|
else {
|
|
328
|
+
const ambiguous = typeof read.value === 'string' ? jmesStringProblem(read.value) : undefined;
|
|
316
329
|
const problem = eventFilterProblem(read);
|
|
317
|
-
if (
|
|
330
|
+
if (ambiguous)
|
|
331
|
+
at('EVENT_FILTER_BACKSLASH', `${where}'s filters[${i}] on \`${read.field}\`: ${ambiguous}`);
|
|
332
|
+
else if (problem)
|
|
318
333
|
at('EVENT_FILTER_BAD_VALUE', `${where}'s filters[${i}] on \`${read.field}\`: ${problem}`);
|
|
319
334
|
}
|
|
320
335
|
});
|
|
@@ -22,7 +22,10 @@
|
|
|
22
22
|
* | … and `lessThanOrEqual` / `greaterThan` / `greaterThanOrEqual` likewise. |
|
|
23
23
|
*
|
|
24
24
|
* Literals follow the designer's `_formatLiteral`: a string is single-quoted, a
|
|
25
|
-
* number or boolean is a JMESPath backtick literal. A
|
|
25
|
+
* number or boolean is a JMESPath backtick literal. A plain string keeps the
|
|
26
|
+
* designer's bytes; a `'` inside it is escaped (`jmesString`), where the designer
|
|
27
|
+
* would emit broken — or injectable — JMESPath, and a backslash no two engines read
|
|
28
|
+
* alike is refused. A DATE is the one case the
|
|
26
29
|
* designer decides from the field's type (`DateTimeOffset` → `to_number(...)` on
|
|
27
30
|
* both sides, because JMESPath compares only numbers). Offline the SDK has no
|
|
28
31
|
* field types for a connection-scoped object, so the VALUE decides: an ISO-8601
|
|
@@ -97,11 +100,42 @@ export declare function readEventFilter(leaf: unknown): {
|
|
|
97
100
|
};
|
|
98
101
|
export declare function isIsoDateString(value: unknown): value is string;
|
|
99
102
|
/**
|
|
100
|
-
* Why a filter cannot be lowered, or `undefined` when it can.
|
|
101
|
-
*
|
|
102
|
-
* so the emitted expression would match nothing and nobody would be told.
|
|
103
|
+
* Why a filter cannot be lowered, or `undefined` when it can. Two shapes are
|
|
104
|
+
* refused. A comparison on a plain string: JMESPath `<`/`>` compare numbers only,
|
|
105
|
+
* so the emitted expression would match nothing and nobody would be told. A string
|
|
106
|
+
* value with a backslash the engines read differently (`jmesStringProblem`).
|
|
103
107
|
*/
|
|
104
108
|
export declare function eventFilterProblem(read: ReadEventFilter): string | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* A JMESPath raw-string literal: `'…'` with each `'` written `\'`. A backslash is
|
|
111
|
+
* kept as it is, so a value without `'` keeps the designer's bytes.
|
|
112
|
+
*
|
|
113
|
+
* The designer's `_formatLiteral` (@uipath/maestro-sdk JmesHelper) splices the value
|
|
114
|
+
* unescaped, so `O'Brien` ends the literal early and the rest of the value is parsed
|
|
115
|
+
* as expression. Escaping `'` closes that.
|
|
116
|
+
*
|
|
117
|
+
* A backslash is the one character the readers disagree on. The specification's
|
|
118
|
+
* raw-string grammar reads `\\` as one backslash and keeps any other escaped
|
|
119
|
+
* character with its backslash (`preserved-escape`). The reference jmespath.js/py
|
|
120
|
+
* lexers keep `\\` as two characters. So `Finance\Q3` and `C:\tmp` read the same
|
|
121
|
+
* everywhere when emitted unchanged, while doubling them would make them miss on a
|
|
122
|
+
* reference engine. Which reader Integration Service runs is unconfirmed, so a value
|
|
123
|
+
* whose backslash HAS no common spelling is refused (`jmesStringProblem`): one before
|
|
124
|
+
* another `\`, before a `'`, or at the end. With those refused, an emitted `\'` is
|
|
125
|
+
* always an escaped quote under every reader, which is what keeps the literal from
|
|
126
|
+
* closing early (`x\' || `true` || '` is refused, not emitted). jmespath.js still
|
|
127
|
+
* unescapes only the first `\'`, so a value with two quotes reads differently there.
|
|
128
|
+
*
|
|
129
|
+
* This is the one spelling for Flow filters, Flow scope clauses and BPMN; FB011 holds
|
|
130
|
+
* every JMESPath string splice to it. It throws on a refused value: `check` reports
|
|
131
|
+
* one first (`EVENT_FILTER_BACKSLASH`), and serialize refuses it with the node's name.
|
|
132
|
+
*/
|
|
133
|
+
export declare function jmesString(value: string): string;
|
|
134
|
+
/**
|
|
135
|
+
* Why `value` has no JMESPath raw-string spelling every reader agrees on, or
|
|
136
|
+
* `undefined` when it has one. See `jmesString`.
|
|
137
|
+
*/
|
|
138
|
+
export declare function jmesStringProblem(value: string): string | undefined;
|
|
105
139
|
/**
|
|
106
140
|
* The JMESPath condition for one filter — the grammar the designer emits,
|
|
107
141
|
* without the outer parentheses (the caller groups conditions).
|
|
@@ -22,7 +22,10 @@
|
|
|
22
22
|
* | … and `lessThanOrEqual` / `greaterThan` / `greaterThanOrEqual` likewise. |
|
|
23
23
|
*
|
|
24
24
|
* Literals follow the designer's `_formatLiteral`: a string is single-quoted, a
|
|
25
|
-
* number or boolean is a JMESPath backtick literal. A
|
|
25
|
+
* number or boolean is a JMESPath backtick literal. A plain string keeps the
|
|
26
|
+
* designer's bytes; a `'` inside it is escaped (`jmesString`), where the designer
|
|
27
|
+
* would emit broken — or injectable — JMESPath, and a backslash no two engines read
|
|
28
|
+
* alike is refused. A DATE is the one case the
|
|
26
29
|
* designer decides from the field's type (`DateTimeOffset` → `to_number(...)` on
|
|
27
30
|
* both sides, because JMESPath compares only numbers). Offline the SDK has no
|
|
28
31
|
* field types for a connection-scoped object, so the VALUE decides: an ISO-8601
|
|
@@ -31,6 +34,7 @@
|
|
|
31
34
|
* strings is null), so `check` refuses it rather than emit a filter that never
|
|
32
35
|
* matches.
|
|
33
36
|
*/
|
|
37
|
+
import { ownEntry } from './own-entry.js';
|
|
34
38
|
/** The designer's operator vocabulary this SDK emits, keyed by the authored key. */
|
|
35
39
|
export const EVENT_FILTER_OPERATORS = {
|
|
36
40
|
contains: { designer: 'Contains', kind: 'function', jmes: 'contains' },
|
|
@@ -82,12 +86,18 @@ export function isIsoDateString(value) {
|
|
|
82
86
|
return typeof value === 'string' && ISO_DATE.test(value);
|
|
83
87
|
}
|
|
84
88
|
/**
|
|
85
|
-
* Why a filter cannot be lowered, or `undefined` when it can.
|
|
86
|
-
*
|
|
87
|
-
* so the emitted expression would match nothing and nobody would be told.
|
|
89
|
+
* Why a filter cannot be lowered, or `undefined` when it can. Two shapes are
|
|
90
|
+
* refused. A comparison on a plain string: JMESPath `<`/`>` compare numbers only,
|
|
91
|
+
* so the emitted expression would match nothing and nobody would be told. A string
|
|
92
|
+
* value with a backslash the engines read differently (`jmesStringProblem`).
|
|
88
93
|
*/
|
|
89
94
|
export function eventFilterProblem(read) {
|
|
90
95
|
const op = EVENT_FILTER_OPERATORS[read.operator];
|
|
96
|
+
if (typeof read.value === 'string') {
|
|
97
|
+
const ambiguous = jmesStringProblem(read.value);
|
|
98
|
+
if (ambiguous)
|
|
99
|
+
return ambiguous;
|
|
100
|
+
}
|
|
91
101
|
if (op.kind === 'function' && typeof read.value !== 'string') {
|
|
92
102
|
return `\`${read.operator}\` is a text test, so its value must be a string — got ${JSON.stringify(read.value)}.`;
|
|
93
103
|
}
|
|
@@ -99,9 +109,54 @@ export function eventFilterProblem(read) {
|
|
|
99
109
|
}
|
|
100
110
|
return undefined;
|
|
101
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* A JMESPath raw-string literal: `'…'` with each `'` written `\'`. A backslash is
|
|
114
|
+
* kept as it is, so a value without `'` keeps the designer's bytes.
|
|
115
|
+
*
|
|
116
|
+
* The designer's `_formatLiteral` (@uipath/maestro-sdk JmesHelper) splices the value
|
|
117
|
+
* unescaped, so `O'Brien` ends the literal early and the rest of the value is parsed
|
|
118
|
+
* as expression. Escaping `'` closes that.
|
|
119
|
+
*
|
|
120
|
+
* A backslash is the one character the readers disagree on. The specification's
|
|
121
|
+
* raw-string grammar reads `\\` as one backslash and keeps any other escaped
|
|
122
|
+
* character with its backslash (`preserved-escape`). The reference jmespath.js/py
|
|
123
|
+
* lexers keep `\\` as two characters. So `Finance\Q3` and `C:\tmp` read the same
|
|
124
|
+
* everywhere when emitted unchanged, while doubling them would make them miss on a
|
|
125
|
+
* reference engine. Which reader Integration Service runs is unconfirmed, so a value
|
|
126
|
+
* whose backslash HAS no common spelling is refused (`jmesStringProblem`): one before
|
|
127
|
+
* another `\`, before a `'`, or at the end. With those refused, an emitted `\'` is
|
|
128
|
+
* always an escaped quote under every reader, which is what keeps the literal from
|
|
129
|
+
* closing early (`x\' || `true` || '` is refused, not emitted). jmespath.js still
|
|
130
|
+
* unescapes only the first `\'`, so a value with two quotes reads differently there.
|
|
131
|
+
*
|
|
132
|
+
* This is the one spelling for Flow filters, Flow scope clauses and BPMN; FB011 holds
|
|
133
|
+
* every JMESPath string splice to it. It throws on a refused value: `check` reports
|
|
134
|
+
* one first (`EVENT_FILTER_BACKSLASH`), and serialize refuses it with the node's name.
|
|
135
|
+
*/
|
|
136
|
+
export function jmesString(value) {
|
|
137
|
+
const problem = jmesStringProblem(value);
|
|
138
|
+
if (problem)
|
|
139
|
+
throw new Error(`jmesString: ${problem}`);
|
|
140
|
+
return `'${value.replace(/'/g, "\\'")}'`;
|
|
141
|
+
}
|
|
142
|
+
/** A backslash whose raw-string reading depends on the engine: before `\` or `'`, or last. */
|
|
143
|
+
const AMBIGUOUS_BACKSLASH = /\\(?=[\\']|$)/;
|
|
144
|
+
/**
|
|
145
|
+
* Why `value` has no JMESPath raw-string spelling every reader agrees on, or
|
|
146
|
+
* `undefined` when it has one. See `jmesString`.
|
|
147
|
+
*/
|
|
148
|
+
export function jmesStringProblem(value) {
|
|
149
|
+
if (!AMBIGUOUS_BACKSLASH.test(value))
|
|
150
|
+
return undefined;
|
|
151
|
+
return `${JSON.stringify(value)} has a backslash at its end or before another \`\\\` or a \`'\`. JMESPath engines `
|
|
152
|
+
+ `disagree on how to read that: the specification reads \`\\\\\` as one backslash, while the reference `
|
|
153
|
+
+ `jmespath.js/py lexers keep two. Which one Integration Service runs is unconfirmed, so the subscription could `
|
|
154
|
+
+ `silently never match. Remove that backslash, or narrow on a substring without it (\`contains\`). A backslash `
|
|
155
|
+
+ `before any other character (\`C:\\tmp\`, \`Finance\\Q3\`) reads the same everywhere and is fine.`;
|
|
156
|
+
}
|
|
102
157
|
/** The JMESPath literal for one filter value, per the designer's `_formatLiteral`. */
|
|
103
158
|
function jmesLiteral(value) {
|
|
104
|
-
return typeof value === 'string' ?
|
|
159
|
+
return typeof value === 'string' ? jmesString(value) : `\`${JSON.stringify(value)}\``;
|
|
105
160
|
}
|
|
106
161
|
/**
|
|
107
162
|
* The JMESPath condition for one filter — the grammar the designer emits,
|
|
@@ -112,7 +167,7 @@ export function eventFilterJmes(read) {
|
|
|
112
167
|
if (op.kind === 'function')
|
|
113
168
|
return `${op.jmes}(${read.field},${jmesLiteral(read.value)})`;
|
|
114
169
|
if (isIsoDateString(read.value))
|
|
115
|
-
return `to_number(${read.field})${op.jmes}to_number(
|
|
170
|
+
return `to_number(${read.field})${op.jmes}to_number(${jmesString(read.value)})`;
|
|
116
171
|
return `${read.field}${op.jmes}${jmesLiteral(read.value)}`;
|
|
117
172
|
}
|
|
118
173
|
/** The designer's tree leaf for one filter — `uiId` is the caller's (it is what keeps a rebuild byte-identical). */
|
|
@@ -128,7 +183,8 @@ export function eventFilterTreeLeaf(read) {
|
|
|
128
183
|
* Returns `undefined` for an operator this SDK does not author (`In`, `IsEmpty`, …).
|
|
129
184
|
*/
|
|
130
185
|
export function eventFilterFromTreeLeaf(leaf) {
|
|
131
|
-
const
|
|
186
|
+
const op = String(leaf?.operator ?? '');
|
|
187
|
+
const key = ownEntry(DESIGNER_TO_KEY, op);
|
|
132
188
|
if (!key || typeof leaf?.id !== 'string')
|
|
133
189
|
return undefined;
|
|
134
190
|
const raw = leaf.value?.value;
|
package/dist/core/expr.d.ts
CHANGED
|
@@ -196,7 +196,7 @@ export type ErrorEnvelopeField = 'code' | 'message' | 'detail' | 'category' | 's
|
|
|
196
196
|
*
|
|
197
197
|
* So the author writes one shape, `.error.<field>`, and `serialize` rewrites it
|
|
198
198
|
* to `.output.<field>` for the one family that publishes it there
|
|
199
|
-
* (`
|
|
199
|
+
* (`ERROR_ENVELOPE_VAR` in `serialize.ts`). Do not hand-write either prefix: which
|
|
200
200
|
* one is right is not a property of the expression, it is a property of the node
|
|
201
201
|
* the step happens to be, and only the builder knows that.
|
|
202
202
|
*
|
package/dist/core/expr.js
CHANGED
|
@@ -209,7 +209,7 @@ export function ran(step) {
|
|
|
209
209
|
*
|
|
210
210
|
* So the author writes one shape, `.error.<field>`, and `serialize` rewrites it
|
|
211
211
|
* to `.output.<field>` for the one family that publishes it there
|
|
212
|
-
* (`
|
|
212
|
+
* (`ERROR_ENVELOPE_VAR` in `serialize.ts`). Do not hand-write either prefix: which
|
|
213
213
|
* one is right is not a property of the expression, it is a property of the node
|
|
214
214
|
* the step happens to be, and only the builder knows that.
|
|
215
215
|
*
|
|
@@ -258,7 +258,7 @@ export function ran(step) {
|
|
|
258
258
|
*/
|
|
259
259
|
export function err(step, field) {
|
|
260
260
|
// ONE shape for every family. `serialize` rewrites the prefix for the families
|
|
261
|
-
// that publish the envelope elsewhere — see `
|
|
261
|
+
// that publish the envelope elsewhere — see `ERROR_ENVELOPE_VAR`.
|
|
262
262
|
return new Expr(`$vars.${step}.error${field ? '.' + field : ''}`);
|
|
263
263
|
}
|
|
264
264
|
/**
|
|
@@ -414,7 +414,7 @@ function segmentEscapes(raw, cooked) {
|
|
|
414
414
|
let value;
|
|
415
415
|
if (next === '\n' || next === '\u2028' || next === '\u2029')
|
|
416
416
|
value = ''; // line continuation
|
|
417
|
-
else if (next
|
|
417
|
+
else if (Object.hasOwn(SINGLE_ESCAPES, next))
|
|
418
418
|
value = SINGLE_ESCAPES[next];
|
|
419
419
|
else if (next === '0' && !/[0-9]/.test(raw[i + 2] ?? ''))
|
|
420
420
|
value = '\0';
|
package/dist/core/json-file.d.ts
CHANGED
package/dist/core/json-file.js
CHANGED
|
@@ -10,3 +10,7 @@ import { writeFileSync } from 'node:fs';
|
|
|
10
10
|
export function writeJsonFile(path, value) {
|
|
11
11
|
writeFileSync(path, JSON.stringify(value, null, 2) + '\n');
|
|
12
12
|
}
|
|
13
|
+
/** `JSON.parse(JSON.stringify(value))`: a deep copy of a JSON value that drops `undefined` and functions, the semantics every copy relied on. */
|
|
14
|
+
export function jsonClone(value) {
|
|
15
|
+
return JSON.parse(JSON.stringify(value));
|
|
16
|
+
}
|
package/dist/core/library.js
CHANGED
|
@@ -14,6 +14,7 @@ import { editDistance } from './edit-distance.js';
|
|
|
14
14
|
import { loadListEnvelopes, lookupListEnvelope } from './list-envelope.js';
|
|
15
15
|
import { lookupSpecOf } from './lookups.js';
|
|
16
16
|
import { loadByoaLedger, loadInvariantCollections, loadLookupResolutions } from './lookup-store.js';
|
|
17
|
+
import { ownEntry } from './own-entry.js';
|
|
17
18
|
/**
|
|
18
19
|
* The refusal {@link Library.resolve} throws, with a `code` for each reason.
|
|
19
20
|
*
|
|
@@ -1265,7 +1266,7 @@ function readFields(v1def, entry) {
|
|
|
1265
1266
|
const out = (v1def?.inputDefinition?.fields ?? []).map((f) => ({ ...f, location: 'body' }));
|
|
1266
1267
|
for (const p of params) {
|
|
1267
1268
|
const name = typeof p?.name === 'string' ? p.name : undefined;
|
|
1268
|
-
const location =
|
|
1269
|
+
const location = typeof p?.type === 'string' ? ownEntry(PARAM_LOCATIONS, p.type) : undefined;
|
|
1269
1270
|
if (!name || !location)
|
|
1270
1271
|
continue;
|
|
1271
1272
|
const field = {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
* so a missing field is an SDK emit bug caught before a file is written — on
|
|
25
25
|
* every path, `compile --no-check` and direct `serialize()` included.
|
|
26
26
|
*/
|
|
27
|
+
export declare const isRecord: (v: unknown) => v is Record<string, unknown>;
|
|
27
28
|
/** Every way `node` breaks the envelope, as `<field>: <problem>` strings. Empty when it conforms. */
|
|
28
29
|
export declare function nodeEnvelopeProblems(node: unknown): string[];
|
|
29
30
|
/**
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* every path, `compile --no-check` and direct `serialize()` included.
|
|
26
26
|
*/
|
|
27
27
|
const TYPE_VERSION_RE = /^\d+\.\d+(\.\d+)?$/;
|
|
28
|
-
const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
28
|
+
export const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
29
29
|
const isNonEmptyString = (v) => typeof v === 'string' && v.length > 0;
|
|
30
30
|
/** Every way `node` breaks the envelope, as `<field>: <problem>` strings. Empty when it conforms. */
|
|
31
31
|
export function nodeEnvelopeProblems(node) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A lookup table's OWN entry for `key`, or `undefined` — never an Object.prototype
|
|
3
|
+
* member. `TABLE[key]` on a plain object answers `toString`, `constructor` and
|
|
4
|
+
* `__proto__` with inherited functions, and `key in TABLE` says they are present;
|
|
5
|
+
* an untrusted key (a node type from a file, a field type from a registry) then
|
|
6
|
+
* reads a function where the caller expects data. FB012 refuses the unguarded
|
|
7
|
+
* forms; this is the guarded read every table shares. FB005 holds the name here.
|
|
8
|
+
*/
|
|
9
|
+
export declare function ownEntry<V>(table: Readonly<Record<string, V>>, key: string): V | undefined;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A lookup table's OWN entry for `key`, or `undefined` — never an Object.prototype
|
|
3
|
+
* member. `TABLE[key]` on a plain object answers `toString`, `constructor` and
|
|
4
|
+
* `__proto__` with inherited functions, and `key in TABLE` says they are present;
|
|
5
|
+
* an untrusted key (a node type from a file, a field type from a registry) then
|
|
6
|
+
* reads a function where the caller expects data. FB012 refuses the unguarded
|
|
7
|
+
* forms; this is the guarded read every table shares. FB005 holds the name here.
|
|
8
|
+
*/
|
|
9
|
+
export function ownEntry(table, key) {
|
|
10
|
+
return Object.hasOwn(table, key) ? table[key] : undefined;
|
|
11
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A value as an inert TypeScript literal in decompiled source.
|
|
3
|
+
*
|
|
4
|
+
* `JSON.stringify` escapes quotes, backslashes and control characters, so an
|
|
5
|
+
* untrusted `.flow`/`.bpmn`/caseplan value — a label, an expression, a URL — can
|
|
6
|
+
* never break out of the literal and become code in a file `compile` later
|
|
7
|
+
* executes. U+2028/U+2029 are escaped too: legal in JSON, illegal in pre-ES2019
|
|
8
|
+
* string literals. The three decompilers each carried a `str()`/`literal()` copy
|
|
9
|
+
* and two had drifted (only some escaped U+2028 in `literal`; one coerced null to
|
|
10
|
+
* `''`). FB005 holds `str`/`literal` to this file, and FB011 holds a decompiler's
|
|
11
|
+
* quoted call argument to these functions. `tsNumber` is the unquoted sibling for
|
|
12
|
+
* numbers: an untrusted `count` spliced with `String()` became code.
|
|
13
|
+
*
|
|
14
|
+
* A missing value is refused, as the decompilers' old `str()` did; the one place
|
|
15
|
+
* that writes the expression `undefined` (Flow's `emitVal`) says so itself.
|
|
16
|
+
*/
|
|
17
|
+
/** A TS expression for `value`: its JSON with U+2028/U+2029 escaped. Throws for `undefined`, and for a value JSON cannot carry (a function or symbol). */
|
|
18
|
+
export declare function tsLiteral(value: unknown): string;
|
|
19
|
+
/** `value` as a TS string literal, null and undefined as `""` (the BPMN decompiler's text fields). */
|
|
20
|
+
export declare function tsText(value: unknown): string;
|
|
21
|
+
/** `value` as a TS number literal: `Number(value)`, refused unless finite — a caseplan or `.flow` number is untrusted text until checked. */
|
|
22
|
+
export declare function tsNumber(value: unknown): string;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A value as an inert TypeScript literal in decompiled source.
|
|
3
|
+
*
|
|
4
|
+
* `JSON.stringify` escapes quotes, backslashes and control characters, so an
|
|
5
|
+
* untrusted `.flow`/`.bpmn`/caseplan value — a label, an expression, a URL — can
|
|
6
|
+
* never break out of the literal and become code in a file `compile` later
|
|
7
|
+
* executes. U+2028/U+2029 are escaped too: legal in JSON, illegal in pre-ES2019
|
|
8
|
+
* string literals. The three decompilers each carried a `str()`/`literal()` copy
|
|
9
|
+
* and two had drifted (only some escaped U+2028 in `literal`; one coerced null to
|
|
10
|
+
* `''`). FB005 holds `str`/`literal` to this file, and FB011 holds a decompiler's
|
|
11
|
+
* quoted call argument to these functions. `tsNumber` is the unquoted sibling for
|
|
12
|
+
* numbers: an untrusted `count` spliced with `String()` became code.
|
|
13
|
+
*
|
|
14
|
+
* A missing value is refused, as the decompilers' old `str()` did; the one place
|
|
15
|
+
* that writes the expression `undefined` (Flow's `emitVal`) says so itself.
|
|
16
|
+
*/
|
|
17
|
+
const LINE_SEPARATORS = /[\u2028\u2029]/g;
|
|
18
|
+
/** A TS expression for `value`: its JSON with U+2028/U+2029 escaped. Throws for `undefined`, and for a value JSON cannot carry (a function or symbol). */
|
|
19
|
+
export function tsLiteral(value) {
|
|
20
|
+
if (value === undefined)
|
|
21
|
+
throw new Error('cannot write undefined as a TypeScript literal.');
|
|
22
|
+
const json = JSON.stringify(value);
|
|
23
|
+
if (json === undefined)
|
|
24
|
+
throw new Error(`cannot write a ${typeof value} as a TypeScript literal.`);
|
|
25
|
+
return json.replace(LINE_SEPARATORS, (c) => `\\u${c.charCodeAt(0).toString(16)}`);
|
|
26
|
+
}
|
|
27
|
+
/** `value` as a TS string literal, null and undefined as `""` (the BPMN decompiler's text fields). */
|
|
28
|
+
export function tsText(value) {
|
|
29
|
+
return tsLiteral(String(value ?? ''));
|
|
30
|
+
}
|
|
31
|
+
/** `value` as a TS number literal: `Number(value)`, refused unless finite — a caseplan or `.flow` number is untrusted text until checked. */
|
|
32
|
+
export function tsNumber(value) {
|
|
33
|
+
const n = Number(value);
|
|
34
|
+
if (!Number.isFinite(n))
|
|
35
|
+
throw new Error(`decompile: expected a number, got ${JSON.stringify(value)}.`);
|
|
36
|
+
return String(n);
|
|
37
|
+
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* the SDK has a typed factory for, and the Data Fabric input keys it may carry.
|
|
4
4
|
* Not re-exported from the package entry point.
|
|
5
5
|
*/
|
|
6
|
+
import { ownEntry } from './own-entry.js';
|
|
6
7
|
/**
|
|
7
8
|
* Every node type the SDK authors as a STEP through a typed factory, with the
|
|
8
9
|
* factory to use. `raw-node-typed-family.test.ts` pins the key set to the
|
|
@@ -135,7 +136,7 @@ const DATAFABRIC_HINT = ' The factory writes the query and write keys: `filters`
|
|
|
135
136
|
export function typedFamilyRawNodeWarning(nodeType) {
|
|
136
137
|
if (typeof nodeType !== 'string')
|
|
137
138
|
return undefined;
|
|
138
|
-
const entry = TYPED_FACTORIES
|
|
139
|
+
const entry = ownEntry(TYPED_FACTORIES, nodeType);
|
|
139
140
|
if (entry === undefined)
|
|
140
141
|
return undefined;
|
|
141
142
|
const hint = nodeType.startsWith('core.datafabric.') ? DATAFABRIC_HINT : '';
|
|
@@ -182,9 +183,9 @@ export function dataFabricUnknownInputs(nodeType, version, inputs) {
|
|
|
182
183
|
}
|
|
183
184
|
if (unknown.length === 0)
|
|
184
185
|
return undefined;
|
|
185
|
-
const bundled = TYPED_FACTORIES
|
|
186
|
+
const bundled = ownEntry(TYPED_FACTORIES, nodeType)?.bundled.includes(version) ?? false;
|
|
186
187
|
const named = unknown.map((k) => `\`${k}\``).join(', ');
|
|
187
|
-
const factory = TYPED_FACTORIES
|
|
188
|
+
const factory = ownEntry(TYPED_FACTORIES, nodeType)?.factory;
|
|
188
189
|
const base = `${nodeType}@${version} carries ${named}, which the platform never reads: Data Fabric `
|
|
189
190
|
+ `nodes read only \`inputs.entityConfig\`, with the keys ${[...DATAFABRIC_ENTITY_CONFIG_KEYS].join(', ')} `
|
|
190
191
|
+ `(flow-workbench entity-vdo.ts \`EntityConfig\` and the entity panels). \`validate\` cannot see `
|