@uipath/case-tool 1.203.0-preview.212 → 1.204.0-preview.211
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 +6 -1
- package/dist/THIRD-PARTY-NOTICES.md +10 -9
- package/dist/authoring-0hr88kff.js +623 -0
- package/dist/{case-api-v6cjyrfw.js → case-api-gdaj9469.js} +5 -5
- package/dist/case-bindings-service-c2mze9vj.js +476 -0
- package/dist/{case-debug-studio-web-service-8th9d8sm.js → case-debug-studio-web-service-6q9ch7cq.js} +11 -10
- package/dist/case-described-io-service-cpe5h2ks.js +132 -0
- package/dist/{case-format-service-q345a2fd.js → case-format-service-qwyjyt0y.js} +2 -2
- package/dist/{case-pack-service-29rza2q2.js → case-pack-service-47yrvmg0.js} +11 -11
- package/dist/case-shape-reader-mw58avr0.js +13 -0
- package/dist/case-splice-service-9zvw19ca.js +312 -0
- package/dist/{case-validate-service-84drzwx3.js → case-validate-service-jcdf4n67.js} +415 -1449
- package/dist/{connector-enrichment-service-2982ykgb.js → connector-enrichment-service-60wwjarq.js} +20 -18
- package/dist/{connector-lookup-service-8ddh4pq2.js → connector-lookup-service-zhf8fz2j.js} +7 -7
- package/dist/{connector-task-spec-qs7q7vnv.js → connector-task-spec-96e3wzx7.js} +86 -26
- package/dist/{debug-service-8x087xxt.js → debug-service-vf5mw0nr.js} +3 -3
- package/dist/{embedded-file-reader-0sjt4nkj.js → embedded-file-reader-v8c2yj2a.js} +2 -2
- package/dist/{enrichment-service-7vbxcwge.js → enrichment-service-78b0gqck.js} +8 -7
- package/dist/index-hhsf00x8.js +15 -0
- package/dist/{index-fz4ttsde.js → index-j2r3jb6c.js} +5 -3
- package/dist/{index-yj8fb3q6.js → index-k7gkw7s9.js} +59 -27
- package/dist/{index-jxj2jz45.js → index-rgw7caht.js} +416 -87
- package/dist/{index-k4xz16db.js → index-wmffgzmr.js} +12522 -7316
- package/dist/index.js +15 -11
- package/dist/{input-reader-pnh948bq.js → input-reader-bb0ptk2v.js} +2 -2
- package/dist/migration-diagnosis-ag2sgd1e.js +71 -0
- package/dist/{node-strategy-gc4sg6a2.js → node-strategy-5pz40tee.js} +1 -1
- package/dist/{node-sync-service-t193ery3.js → node-sync-service-zwjcwgwc.js} +6 -6
- package/dist/out-target-1f4n9vqb.js +70 -0
- package/dist/{packager-tool-wefb1zw3.js → packager-tool-0p3td5zv.js} +8 -7
- package/dist/packager-tool-21qfsbxn.js +17 -0
- package/dist/{strict-sdd-audit-8e2fh9jg.js → packager-tool-4e56rmwe.js} +2771 -1746
- package/dist/{packager-tool-sfkyb4kz.js → packager-tool-4rqd21wc.js} +194 -2
- package/dist/packager-tool-57pzrd0g.js +32 -0
- package/dist/{packager-tool-kpcjnxd1.js → packager-tool-58kx79ta.js} +586 -113
- package/dist/{packager-tool-hrdan5ms.js → packager-tool-5qghkdd0.js} +2 -2
- package/dist/packager-tool-5qp9xza1.js +10 -0
- package/dist/{packager-tool-3qkp2fts.js → packager-tool-76ms0wdw.js} +4 -4
- package/dist/packager-tool-8a9yqfq7.js +76 -0
- package/dist/packager-tool-b250k6w4.js +75 -0
- package/dist/packager-tool-bfgdz1zh.js +73 -0
- package/dist/{packager-tool-p7jgrm5r.js → packager-tool-cmwets3m.js} +1 -1
- package/dist/{packager-tool-d4sjk46c.js → packager-tool-cv05dwac.js} +18 -21
- package/dist/packager-tool-d7jjng8a.js +21 -0
- package/dist/{packager-tool-rh07gzxw.js → packager-tool-dqnc61h1.js} +5 -5
- package/dist/packager-tool-dthjwajc.js +13 -0
- package/dist/packager-tool-f78ntj5g.js +228 -0
- package/dist/{packager-tool-r1g8rqcs.js → packager-tool-gjhg49r1.js} +4 -4
- package/dist/{packager-tool-cg2j4rma.js → packager-tool-kacqd7h7.js} +4 -4
- package/dist/packager-tool-mknccck5.js +24 -0
- package/dist/{packager-tool-sv0d6wb6.js → packager-tool-nj4seavy.js} +7 -3
- package/dist/{packager-tool-adcaxdhs.js → packager-tool-paepfv5d.js} +1 -1
- package/dist/{packager-tool-052kvydg.js → packager-tool-pm646ag4.js} +1 -1
- package/dist/{packager-tool-qht4xd0y.js → packager-tool-q86py4rp.js} +320 -200
- package/dist/{packager-tool-geaetyks.js → packager-tool-qmeaj10z.js} +669 -100
- package/dist/{packager-tool-dd8bq6az.js → packager-tool-rgpdaxbx.js} +548 -108
- package/dist/{packager-tool-8q7vzh65.js → packager-tool-s3e2kepj.js} +455 -13
- package/dist/{packager-tool-r84ng21s.js → packager-tool-sag9gz55.js} +3 -1
- package/dist/{packager-tool-0mj06yen.js → packager-tool-sq931c23.js} +5 -22
- package/dist/{packager-tool-7mggwye6.js → packager-tool-tmfbp50w.js} +6 -6
- package/dist/{packager-tool-yrsrzz1a.js → packager-tool-v99ygh9f.js} +23 -8
- package/dist/packager-tool-wj9d9mqe.js +267 -0
- package/dist/{packager-tool-hz1mz8fs.js → packager-tool-wjaya2k2.js} +2 -2
- package/dist/packager-tool-xcd87qyx.js +44 -0
- package/dist/{packager-tool-0v3s8r01.js → packager-tool-xdxr3ync.js} +4 -2
- package/dist/{packager-tool-61hxhgeg.js → packager-tool-xkgq5fkf.js} +3 -3
- package/dist/packager-tool.js +6 -6
- package/dist/{project-artifacts-8snev67g.js → project-artifacts-wzrhketn.js} +1 -1
- package/dist/resolved-check-p99hysaw.js +50 -0
- package/dist/{resourcesSyncService-01qr5zp7.js → resourcesSyncService-rjt0tht7.js} +25 -18
- package/dist/rule-group-members-zje7n3kf.js +76 -0
- package/dist/sdd-convert-service-gp9733qv.js +1962 -0
- package/dist/{sdd-lookup-x08j9g9m.js → sdd-lookup-vpjej1kt.js} +2 -2
- package/dist/sdd-resolve-service-4hx64x3z.js +288 -0
- package/dist/strict-case-rules-ksy8q7pg.js +731 -0
- package/dist/strict-entry-points-v14d7y50.js +124 -0
- package/dist/strict-sdd-audit-k6hh0mbr.js +23 -0
- package/dist/task-selector-8bjn35dv.js +57 -0
- package/dist/tool.js +15 -11
- package/dist/{trigger-enrichment-service-sddbphf2.js → trigger-enrichment-service-kst89jbe.js} +41 -23
- package/package.json +2 -2
- package/dist/authoring-kngaggwm.js +0 -360
- package/dist/case-bindings-service-1wxfghzd.js +0 -240
- package/dist/packager-tool-83qnybab.js +0 -1564
- package/dist/strict-case-rules-x6t0vb40.js +0 -409
|
@@ -0,0 +1,731 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ACTIVITY_TYPE_ID_PATH,
|
|
3
|
+
activityTypeIdMessage,
|
|
4
|
+
contextEntry,
|
|
5
|
+
missingContextKeys,
|
|
6
|
+
readActivityTypeId
|
|
7
|
+
} from "./packager-tool-cv05dwac.js";
|
|
8
|
+
import {
|
|
9
|
+
BINDING_REFERENCE_PREFIX,
|
|
10
|
+
NAME_BOUND_TASK_TYPES,
|
|
11
|
+
RESOLVED_IDENTITY_KEYS
|
|
12
|
+
} from "./packager-tool-d7jjng8a.js";
|
|
13
|
+
import {
|
|
14
|
+
JINT_GLOBALS
|
|
15
|
+
} from "./packager-tool-bfgdz1zh.js";
|
|
16
|
+
import {
|
|
17
|
+
byCodeUnit
|
|
18
|
+
} from "./packager-tool-5qp9xza1.js";
|
|
19
|
+
import"./packager-tool-1yh8g550.js";
|
|
20
|
+
|
|
21
|
+
// src/services/strict-connection-binding.ts
|
|
22
|
+
var CONNECTION_RESOURCE = "Connection";
|
|
23
|
+
var FOLDER_KEY_ATTRIBUTE = "folderKey";
|
|
24
|
+
var READ_FIELDS = [
|
|
25
|
+
{ field: "id", mustBeNonEmpty: false },
|
|
26
|
+
{ field: "resourceKey", mustBeNonEmpty: true },
|
|
27
|
+
{ field: "propertyAttribute", mustBeNonEmpty: false }
|
|
28
|
+
];
|
|
29
|
+
var EMPTY_FIELD_HARM = {
|
|
30
|
+
id: "A task points at a binding as `=bindings.<id>`, so an entry with an empty `id` is written into the task as `=bindings.` — a reference that resolves to nothing, with every check still passing.",
|
|
31
|
+
propertyAttribute: "The generated entry reads each value by its `propertyAttribute`, so an empty one is never read: whatever this binding carries — a connection id, a folder key — silently contributes nothing to `bindings_v2.json`."
|
|
32
|
+
};
|
|
33
|
+
var nonEmptyString = (value) => typeof value === "string" && value.trim() !== "";
|
|
34
|
+
var checkConnectionBindings = (parsed) => {
|
|
35
|
+
const bindings = Array.isArray(parsed.bindings) ? parsed.bindings : [];
|
|
36
|
+
const issues = [];
|
|
37
|
+
bindings.forEach((entry, index) => {
|
|
38
|
+
if (typeof entry !== "object" || entry === null)
|
|
39
|
+
return;
|
|
40
|
+
const binding = entry;
|
|
41
|
+
if (binding.resource !== CONNECTION_RESOURCE)
|
|
42
|
+
return;
|
|
43
|
+
const path = `bindings[${index}]`;
|
|
44
|
+
const label = nonEmptyString(binding.name) ? ` ("${String(binding.name)}")` : "";
|
|
45
|
+
const missing = READ_FIELDS.filter(({ field, mustBeNonEmpty }) => typeof binding[field] !== "string" || mustBeNonEmpty && !nonEmptyString(binding[field])).map(({ field }) => field);
|
|
46
|
+
const badDefault = binding.default !== undefined && typeof binding.default !== "string";
|
|
47
|
+
if (missing.length > 0 || badDefault) {
|
|
48
|
+
const parts = [
|
|
49
|
+
...missing.map((field) => `\`${field}\``),
|
|
50
|
+
badDefault && "a non-string `default`"
|
|
51
|
+
].filter((part) => part !== false);
|
|
52
|
+
issues.push({
|
|
53
|
+
code: "STRICT_CONNECTION_BINDING_DROPPED",
|
|
54
|
+
path,
|
|
55
|
+
severity: "error",
|
|
56
|
+
message: `This \`Connection\` binding${label} has ` + `${parts.join(", ")}. \`bindings_v2.json\` is generated by ` + "grouping the bindings array, and a binding missing any " + "field the grouping reads is skipped without an error — so " + "the connection never reaches the file, and " + "`uip solution resources refresh` has nothing to resolve."
|
|
57
|
+
});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const empty = READ_FIELDS.map(({ field }) => field).filter((field) => binding[field] === "");
|
|
61
|
+
for (const field of empty) {
|
|
62
|
+
issues.push({
|
|
63
|
+
code: "STRICT_CONNECTION_BINDING_FIELD_EMPTY",
|
|
64
|
+
path: `${path}.${field}`,
|
|
65
|
+
severity: "error",
|
|
66
|
+
message: `This \`Connection\` binding${label} has an empty ` + `\`${field}\`. ${EMPTY_FIELD_HARM[field] ?? ""} The entry ` + "is still grouped into `bindings_v2.json` — only " + "`resourceKey` has to be non-empty for that — so nothing " + "else reports it."
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (empty.length > 0)
|
|
70
|
+
return;
|
|
71
|
+
if (binding.propertyAttribute !== FOLDER_KEY_ATTRIBUTE)
|
|
72
|
+
return;
|
|
73
|
+
if (nonEmptyString(binding.default))
|
|
74
|
+
return;
|
|
75
|
+
issues.push({
|
|
76
|
+
code: "STRICT_CONNECTION_FOLDER_KEY_NO_DEFAULT",
|
|
77
|
+
path: `${path}.default`,
|
|
78
|
+
severity: "error",
|
|
79
|
+
message: `This connection's \`${FOLDER_KEY_ATTRIBUTE}\` binding${label} ` + "carries no `default`. The generated entry takes the folder " + "key from that field and omits the property when it is " + "missing, so the connection ships with its id and no folder — " + "and unlike `ConnectionId`, which falls back to the binding's " + "`resourceKey`, there is nothing to fall back to here."
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
return issues;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// src/services/strict-js-source.ts
|
|
86
|
+
import { Script } from "node:vm";
|
|
87
|
+
var JS_PREFIX = "=js:";
|
|
88
|
+
var asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
89
|
+
var forEachJsExpression = (value, path, visit) => {
|
|
90
|
+
if (typeof value === "string") {
|
|
91
|
+
if (value.startsWith(JS_PREFIX)) {
|
|
92
|
+
visit(value.slice(JS_PREFIX.length), path, value);
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (Array.isArray(value)) {
|
|
97
|
+
value.forEach((entry, index) => {
|
|
98
|
+
forEachJsExpression(entry, `${path}[${index}]`, visit);
|
|
99
|
+
});
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const record = asRecord(value);
|
|
103
|
+
if (!record)
|
|
104
|
+
return;
|
|
105
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
106
|
+
forEachJsExpression(entry, `${path}.${key}`, visit);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var jsSyntaxError = (source) => {
|
|
110
|
+
try {
|
|
111
|
+
new Script(source);
|
|
112
|
+
return null;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
return error instanceof SyntaxError ? error.message : null;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
var interpolationEnd = (source, from) => {
|
|
118
|
+
let index = from;
|
|
119
|
+
let depth = 1;
|
|
120
|
+
while (index < source.length && depth > 0) {
|
|
121
|
+
const char = source[index];
|
|
122
|
+
if (char === "\\") {
|
|
123
|
+
index += 2;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
127
|
+
index += 1;
|
|
128
|
+
while (index < source.length && source[index] !== char) {
|
|
129
|
+
index += source[index] === "\\" ? 2 : 1;
|
|
130
|
+
}
|
|
131
|
+
index += 1;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (char === "/" && source[index + 1] === "/") {
|
|
135
|
+
while (index < source.length && source[index] !== `
|
|
136
|
+
`)
|
|
137
|
+
index += 1;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (char === "/" && source[index + 1] === "*") {
|
|
141
|
+
index += 2;
|
|
142
|
+
while (index + 1 < source.length && !(source[index] === "*" && source[index + 1] === "/")) {
|
|
143
|
+
index += 1;
|
|
144
|
+
}
|
|
145
|
+
index += 2;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (char === "{")
|
|
149
|
+
depth += 1;
|
|
150
|
+
else if (char === "}")
|
|
151
|
+
depth -= 1;
|
|
152
|
+
index += 1;
|
|
153
|
+
}
|
|
154
|
+
return index;
|
|
155
|
+
};
|
|
156
|
+
var stripJsLiterals = (source) => {
|
|
157
|
+
const out = [];
|
|
158
|
+
let index = 0;
|
|
159
|
+
while (index < source.length) {
|
|
160
|
+
const char = source[index];
|
|
161
|
+
if (char === '"' || char === "'") {
|
|
162
|
+
index += 1;
|
|
163
|
+
while (index < source.length && source[index] !== char) {
|
|
164
|
+
index += source[index] === "\\" ? 2 : 1;
|
|
165
|
+
}
|
|
166
|
+
index += 1;
|
|
167
|
+
out.push(" ");
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (char === "`") {
|
|
171
|
+
index += 1;
|
|
172
|
+
while (index < source.length && source[index] !== "`") {
|
|
173
|
+
if (source[index] === "\\") {
|
|
174
|
+
index += 2;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (source[index] === "$" && source[index + 1] === "{") {
|
|
178
|
+
const end = interpolationEnd(source, index + 2);
|
|
179
|
+
out.push(` ${stripJsLiterals(source.slice(index + 2, end - 1))} `);
|
|
180
|
+
index = end;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
index += 1;
|
|
184
|
+
}
|
|
185
|
+
index += 1;
|
|
186
|
+
out.push(" ");
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (char === "/" && source[index + 1] === "/") {
|
|
190
|
+
while (index < source.length && source[index] !== `
|
|
191
|
+
`)
|
|
192
|
+
index += 1;
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (char === "/" && source[index + 1] === "*") {
|
|
196
|
+
index += 2;
|
|
197
|
+
while (index + 1 < source.length && !(source[index] === "*" && source[index + 1] === "/")) {
|
|
198
|
+
index += 1;
|
|
199
|
+
}
|
|
200
|
+
index += 2;
|
|
201
|
+
out.push(" ");
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
out.push(char);
|
|
205
|
+
index += 1;
|
|
206
|
+
}
|
|
207
|
+
return out.join("");
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// src/services/strict-js-scope.ts
|
|
211
|
+
var EXPRESSION_NAMESPACES = new Set([
|
|
212
|
+
"bindings",
|
|
213
|
+
"datafabric",
|
|
214
|
+
"outputs",
|
|
215
|
+
"result",
|
|
216
|
+
"this",
|
|
217
|
+
"vars",
|
|
218
|
+
"iterator",
|
|
219
|
+
"metadata",
|
|
220
|
+
"orchestrator",
|
|
221
|
+
"instanceglobals",
|
|
222
|
+
"runtime",
|
|
223
|
+
"senderinfo"
|
|
224
|
+
]);
|
|
225
|
+
var AMBIENT_NAMES = new Set([
|
|
226
|
+
...JINT_GLOBALS,
|
|
227
|
+
"atob",
|
|
228
|
+
"btoa",
|
|
229
|
+
"async",
|
|
230
|
+
"await",
|
|
231
|
+
"break",
|
|
232
|
+
"case",
|
|
233
|
+
"catch",
|
|
234
|
+
"class",
|
|
235
|
+
"const",
|
|
236
|
+
"continue",
|
|
237
|
+
"default",
|
|
238
|
+
"delete",
|
|
239
|
+
"do",
|
|
240
|
+
"else",
|
|
241
|
+
"extends",
|
|
242
|
+
"false",
|
|
243
|
+
"finally",
|
|
244
|
+
"for",
|
|
245
|
+
"function",
|
|
246
|
+
"if",
|
|
247
|
+
"in",
|
|
248
|
+
"instanceof",
|
|
249
|
+
"let",
|
|
250
|
+
"new",
|
|
251
|
+
"null",
|
|
252
|
+
"of",
|
|
253
|
+
"return",
|
|
254
|
+
"super",
|
|
255
|
+
"switch",
|
|
256
|
+
"throw",
|
|
257
|
+
"true",
|
|
258
|
+
"try",
|
|
259
|
+
"typeof",
|
|
260
|
+
"var",
|
|
261
|
+
"void",
|
|
262
|
+
"while",
|
|
263
|
+
"yield"
|
|
264
|
+
]);
|
|
265
|
+
var ROOT_IDENTIFIER = /(?<![.$\w])([A-Za-z_$][\w$]*)/g;
|
|
266
|
+
var LOCAL_BINDING = /=>|\bfunction\b|\b(?:var|let|const)\s|\bcatch\s*\(/;
|
|
267
|
+
var UNSCANNABLE = /\//;
|
|
268
|
+
var unknownIdentifiers = (source) => {
|
|
269
|
+
if (jsSyntaxError(source) !== null)
|
|
270
|
+
return [];
|
|
271
|
+
const code = stripJsLiterals(source);
|
|
272
|
+
if (LOCAL_BINDING.test(code))
|
|
273
|
+
return [];
|
|
274
|
+
if (UNSCANNABLE.test(code))
|
|
275
|
+
return [];
|
|
276
|
+
const found = [];
|
|
277
|
+
for (const match of code.matchAll(ROOT_IDENTIFIER)) {
|
|
278
|
+
const name = match[1];
|
|
279
|
+
if (EXPRESSION_NAMESPACES.has(name) || AMBIENT_NAMES.has(name))
|
|
280
|
+
continue;
|
|
281
|
+
const after = code.slice(match.index + name.length);
|
|
282
|
+
const before = code.slice(0, match.index).trimEnd();
|
|
283
|
+
const key = before.endsWith("{") || before.endsWith(",") || before === "";
|
|
284
|
+
if (key && /^\s*:/.test(after) && !/^\s*::/.test(after))
|
|
285
|
+
continue;
|
|
286
|
+
if (!found.includes(name))
|
|
287
|
+
found.push(name);
|
|
288
|
+
}
|
|
289
|
+
return found;
|
|
290
|
+
};
|
|
291
|
+
var checkJsExpressionScope = (parsed) => {
|
|
292
|
+
const issues = [];
|
|
293
|
+
forEachJsExpression(parsed, "(root)", (source, path, raw) => {
|
|
294
|
+
const unknown = unknownIdentifiers(source);
|
|
295
|
+
if (unknown.length === 0)
|
|
296
|
+
return;
|
|
297
|
+
const names = unknown.map((name) => `\`${name}\``).join(", ");
|
|
298
|
+
issues.push({
|
|
299
|
+
code: "STRICT_JS_UNKNOWN_IDENTIFIER",
|
|
300
|
+
path,
|
|
301
|
+
severity: "error",
|
|
302
|
+
message: `This \`=js:\` expression reads ${names}, which nothing puts ` + "in scope. The runtime evaluates it as JavaScript against the " + "case data, so an undeclared name is a ReferenceError on the " + "first evaluation and the element it belongs to produces no " + "verdict. A case variable is reached through its namespace " + `(\`vars.${unknown[0]}\`), and a literal string needs its ` + `quotes (\`=js:'${unknown[0]}'\`). Readable namespaces: ` + `${[...EXPRESSION_NAMESPACES].sort(byCodeUnit).join(", ")}. Offending ` + `text: ${JSON.stringify(raw.slice(0, 70))}`
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
return issues;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
// src/services/strict-case-rules.ts
|
|
309
|
+
var FORMAL_ARG_ID = /^v[A-Za-z0-9]{8}$/;
|
|
310
|
+
var asRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
311
|
+
var asArray = (value) => Array.isArray(value) ? value : [];
|
|
312
|
+
var nodeType = (node) => typeof node.type === "string" ? node.type : "";
|
|
313
|
+
var isStage = (node) => nodeType(node).startsWith("case-management:Stage") || nodeType(node) === "case-management:Stage";
|
|
314
|
+
var checkStagesHaveTasks = (nodes) => {
|
|
315
|
+
const issues = [];
|
|
316
|
+
for (const node of nodes) {
|
|
317
|
+
if (!isStage(node))
|
|
318
|
+
continue;
|
|
319
|
+
const data = asRecord2(node.data);
|
|
320
|
+
const lanes = asArray(data?.tasks);
|
|
321
|
+
const taskCount = lanes.reduce((total, lane) => total + asArray(lane).length, 0);
|
|
322
|
+
if (taskCount > 0)
|
|
323
|
+
continue;
|
|
324
|
+
const id = typeof node.id === "string" ? node.id : "?";
|
|
325
|
+
issues.push({
|
|
326
|
+
code: "STRICT_STAGE_NO_TASKS",
|
|
327
|
+
path: `nodes[${id}].data.tasks`,
|
|
328
|
+
severity: "error",
|
|
329
|
+
message: `Stage "${id}" declares no tasks. A stage with empty task ` + "lanes deploys and then has nothing to run, so the case " + "enters it and stops."
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
return issues;
|
|
333
|
+
};
|
|
334
|
+
var checkJsExpressionsParse = (parsed) => {
|
|
335
|
+
const issues = [];
|
|
336
|
+
forEachJsExpression(parsed, "(root)", (source, path, raw) => {
|
|
337
|
+
const failure = jsSyntaxError(source);
|
|
338
|
+
if (failure === null)
|
|
339
|
+
return;
|
|
340
|
+
const escaped = source.replace(/\r\n|\r|\n/g, String.raw`\n`);
|
|
341
|
+
const rawLineBreak = escaped !== source && jsSyntaxError(escaped) === null;
|
|
342
|
+
issues.push({
|
|
343
|
+
code: "STRICT_JS_EXPRESSION_INVALID",
|
|
344
|
+
path,
|
|
345
|
+
severity: "error",
|
|
346
|
+
message: `This \`=js:\` expression does not parse: ${failure}. The ` + "runtime evaluates it as JavaScript, so the element faults on " + "its first evaluation." + (rawLineBreak ? " It carries a raw line break: write `\\\\n` in the JSON " + "so the JavaScript source carries `\\n`." : "") + ` Offending text: ${JSON.stringify(raw.slice(0, 70))}`
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
return issues;
|
|
350
|
+
};
|
|
351
|
+
var argumentCompanionIssues = (variable, name, path, triggerIds) => {
|
|
352
|
+
const at = variable.elementId;
|
|
353
|
+
if (typeof at !== "string" || !triggerIds.has(at))
|
|
354
|
+
return [];
|
|
355
|
+
return ["default", "custom"].filter((key) => variable[key] !== undefined).map((key) => ({
|
|
356
|
+
code: "STRICT_ARGUMENT_COMPANION_FIELD",
|
|
357
|
+
path: `${path}.${key}`,
|
|
358
|
+
severity: "error",
|
|
359
|
+
message: `Argument companion "${name}" carries ` + `"${key}". A companion on a trigger is the ` + "argument half of the pair: the formal slot in " + "`variables.inputs[]` carries the default, and " + "`custom` lists a variable as case data, so neither " + `belongs here. Remove "${key}" from this entry ` + "and keep the rest, including the JobAttachment " + "`body` a file argument carries."
|
|
360
|
+
}));
|
|
361
|
+
};
|
|
362
|
+
var checkVariableContract = (variables, triggerIds) => {
|
|
363
|
+
const issues = [];
|
|
364
|
+
for (const slot of ["inputs", "outputs", "inputOutputs"]) {
|
|
365
|
+
asArray(variables?.[slot]).forEach((entry, index) => {
|
|
366
|
+
const variable = asRecord2(entry);
|
|
367
|
+
if (!variable)
|
|
368
|
+
return;
|
|
369
|
+
const name = typeof variable.name === "string" ? variable.name : `#${index}`;
|
|
370
|
+
const path = `variables.${slot}[${name}]`;
|
|
371
|
+
const id = variable.id;
|
|
372
|
+
if (slot !== "inputOutputs") {
|
|
373
|
+
if (typeof id !== "string" || !FORMAL_ARG_ID.test(id)) {
|
|
374
|
+
issues.push({
|
|
375
|
+
code: "STRICT_FORMAL_ARG_ID",
|
|
376
|
+
path: `${path}.id`,
|
|
377
|
+
severity: "error",
|
|
378
|
+
message: `Formal argument "${name}" has id ` + `"${String(id)}", which is not the generated ` + 'form "v" + 8 characters. An id copied from the ' + "name collides across renames and does not match " + "what the converter emits."
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (slot === "inputOutputs") {
|
|
383
|
+
issues.push(...argumentCompanionIssues(variable, name, path, triggerIds));
|
|
384
|
+
}
|
|
385
|
+
if (variable.default !== undefined && typeof variable.default !== "string") {
|
|
386
|
+
issues.push({
|
|
387
|
+
code: "STRICT_DEFAULT_NOT_STRING",
|
|
388
|
+
path: `${path}.default`,
|
|
389
|
+
severity: "error",
|
|
390
|
+
message: `Default for "${name}" is a ` + `${Array.isArray(variable.default) ? "array" : typeof variable.default} ` + "and must be a JSON string. The converter drops " + "non-string defaults without saying so, so the value " + "silently disappears from entry-points.json."
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
return issues;
|
|
396
|
+
};
|
|
397
|
+
var checkInputOutputCompanions = (variables, nodes) => {
|
|
398
|
+
const issues = [];
|
|
399
|
+
const companions = new Set(asArray(variables?.inputOutputs).map((entry) => asRecord2(entry)?.name).filter((name) => typeof name === "string"));
|
|
400
|
+
const unbound = (name) => !companions.has(name);
|
|
401
|
+
asArray(variables?.inputs).forEach((entry) => {
|
|
402
|
+
const variable = asRecord2(entry);
|
|
403
|
+
const name = variable?.name;
|
|
404
|
+
if (typeof name !== "string" || !unbound(name))
|
|
405
|
+
return;
|
|
406
|
+
issues.push({
|
|
407
|
+
code: "STRICT_INPUTOUTPUTS_COMPANION",
|
|
408
|
+
path: `variables.inputs[${name}]`,
|
|
409
|
+
severity: "error",
|
|
410
|
+
message: `In-argument "${name}" has no entry of the same name in ` + "variables.inputOutputs[]. The companion is what carries the " + "binding, so without it the argument is declared and never " + "bound."
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
for (const node of nodes) {
|
|
414
|
+
const nodeId = typeof node.id === "string" ? node.id : "?";
|
|
415
|
+
const data = asRecord2(node.data);
|
|
416
|
+
for (const lane of asArray(data?.tasks)) {
|
|
417
|
+
for (const task of asArray(lane)) {
|
|
418
|
+
const taskRecord = asRecord2(task);
|
|
419
|
+
if (!taskRecord)
|
|
420
|
+
continue;
|
|
421
|
+
const taskId = typeof taskRecord.id === "string" ? taskRecord.id : "?";
|
|
422
|
+
for (const output of asArray(asRecord2(taskRecord.data)?.outputs)) {
|
|
423
|
+
const record = asRecord2(output);
|
|
424
|
+
if (record?.custom !== true)
|
|
425
|
+
continue;
|
|
426
|
+
const variableName = record.var;
|
|
427
|
+
if (typeof variableName !== "string" || !unbound(variableName)) {
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
const label = typeof record.name === "string" ? record.name : variableName;
|
|
431
|
+
issues.push({
|
|
432
|
+
code: "STRICT_INPUTOUTPUTS_COMPANION",
|
|
433
|
+
path: `nodes[${nodeId}].data.tasks[${taskId}].data.outputs[${label}]`,
|
|
434
|
+
severity: "error",
|
|
435
|
+
message: `Custom output "${label}" writes to ` + `"${variableName}", which has no entry in ` + "variables.inputOutputs[]. Without the companion " + "the value has nowhere to land."
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return issues;
|
|
442
|
+
};
|
|
443
|
+
var checkConnectorRuleContext = (nodes, bindings) => {
|
|
444
|
+
const issues = [];
|
|
445
|
+
const visitRule = (rule, path) => {
|
|
446
|
+
if (rule.rule !== "wait-for-connector")
|
|
447
|
+
return;
|
|
448
|
+
const context = asRecord2(rule.uipath)?.context;
|
|
449
|
+
const missing = missingContextKeys(context, true, bindings);
|
|
450
|
+
if (missing.length > 0) {
|
|
451
|
+
issues.push({
|
|
452
|
+
code: "STRICT_CONNECTOR_CONTEXT_INCOMPLETE",
|
|
453
|
+
path: `${path}.uipath.context`,
|
|
454
|
+
severity: "error",
|
|
455
|
+
message: `Connector rule "${String(rule.id ?? "?")}" is missing ` + `context entries: ${missing.join(", ")}. A rule carrying ` + "the connection but not the activity metadata deploys and " + "then has no event to wait for."
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
if (contextEntry(context, "metadata") === undefined)
|
|
459
|
+
return;
|
|
460
|
+
if (readActivityTypeId(context) === undefined) {
|
|
461
|
+
issues.push({
|
|
462
|
+
code: "STRICT_CONNECTOR_ACTIVITY_TYPE_ID",
|
|
463
|
+
path: `${path}.uipath.context[metadata].${ACTIVITY_TYPE_ID_PATH}`,
|
|
464
|
+
severity: "error",
|
|
465
|
+
message: activityTypeIdMessage(`rule "${typeof rule.id === "string" ? rule.id : "?"}"`, context, "The connection id alone does not identify the event to " + "wait for.")
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
const visitConditions = (conditions, path) => {
|
|
470
|
+
asArray(conditions).forEach((condition, conditionIndex) => {
|
|
471
|
+
const record = asRecord2(condition);
|
|
472
|
+
if (!record)
|
|
473
|
+
return;
|
|
474
|
+
asArray(record.rules).forEach((group, groupIndex) => {
|
|
475
|
+
asArray(group).forEach((rule, ruleIndex) => {
|
|
476
|
+
const ruleRecord = asRecord2(rule);
|
|
477
|
+
if (!ruleRecord)
|
|
478
|
+
return;
|
|
479
|
+
visitRule(ruleRecord, `${path}[${conditionIndex}].rules[${groupIndex}][${ruleIndex}]`);
|
|
480
|
+
});
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
};
|
|
484
|
+
for (const node of nodes) {
|
|
485
|
+
const id = typeof node.id === "string" ? node.id : "?";
|
|
486
|
+
const data = asRecord2(node.data);
|
|
487
|
+
visitConditions(data?.entryConditions, `nodes[${id}].data.entryConditions`);
|
|
488
|
+
visitConditions(data?.exitConditions, `nodes[${id}].data.exitConditions`);
|
|
489
|
+
for (const lane of asArray(data?.tasks)) {
|
|
490
|
+
for (const task of asArray(lane)) {
|
|
491
|
+
const taskRecord = asRecord2(task);
|
|
492
|
+
if (!taskRecord)
|
|
493
|
+
continue;
|
|
494
|
+
const taskId = typeof taskRecord.id === "string" ? taskRecord.id : "?";
|
|
495
|
+
visitConditions(taskRecord.entryConditions, `nodes[${id}].data.tasks[${taskId}].entryConditions`);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return issues;
|
|
500
|
+
};
|
|
501
|
+
var RECIPIENT_PREFIXES = [
|
|
502
|
+
"User:",
|
|
503
|
+
"UserGroup:",
|
|
504
|
+
"Role:",
|
|
505
|
+
"Email:",
|
|
506
|
+
"Expression:"
|
|
507
|
+
];
|
|
508
|
+
var recipientIssues = (recipient, path) => {
|
|
509
|
+
const value = recipient.Value;
|
|
510
|
+
if (typeof value !== "string")
|
|
511
|
+
return [];
|
|
512
|
+
const prefix = RECIPIENT_PREFIXES.find((candidate) => value.startsWith(candidate));
|
|
513
|
+
if (prefix !== undefined) {
|
|
514
|
+
return [
|
|
515
|
+
{
|
|
516
|
+
code: "STRICT_RECIPIENT_PREFIX_LEFT",
|
|
517
|
+
path: `${path}.Value`,
|
|
518
|
+
severity: "error",
|
|
519
|
+
message: `Recipient value "${value}" still carries the ` + `"${prefix}" marker. That marker picks the Type and is ` + "removed on the way in, so the assignment looks up a " + "name nobody has and the task ships assigned to no one."
|
|
520
|
+
}
|
|
521
|
+
];
|
|
522
|
+
}
|
|
523
|
+
if (!value.startsWith("=vars.") || recipient.Type === 3)
|
|
524
|
+
return [];
|
|
525
|
+
return [
|
|
526
|
+
{
|
|
527
|
+
code: "STRICT_RECIPIENT_EXPRESSION_TYPE",
|
|
528
|
+
path: `${path}.Type`,
|
|
529
|
+
severity: "error",
|
|
530
|
+
message: `Recipient value "${value}" is an expression but carries ` + `Type ${String(recipient.Type)}. Type 0 sends it to a user ` + "lookup, Type 1 to a group lookup and Type 2 to an email " + "lookup, all on the literal text. An expression recipient " + "is Type 3."
|
|
531
|
+
}
|
|
532
|
+
];
|
|
533
|
+
};
|
|
534
|
+
var checkActionRecipientShape = (nodes) => nodes.flatMap((node) => {
|
|
535
|
+
const nodeId = typeof node.id === "string" ? node.id : "?";
|
|
536
|
+
const lanes = asArray(asRecord2(node.data)?.tasks);
|
|
537
|
+
return lanes.flatMap((lane) => asArray(lane).flatMap((task) => {
|
|
538
|
+
const taskRecord = asRecord2(task);
|
|
539
|
+
const recipient = asRecord2(asRecord2(taskRecord?.data)?.recipient);
|
|
540
|
+
if (!taskRecord || !recipient)
|
|
541
|
+
return [];
|
|
542
|
+
const taskId = typeof taskRecord.id === "string" ? taskRecord.id : "?";
|
|
543
|
+
return recipientIssues(recipient, `nodes[${nodeId}].data.tasks[${taskId}].data.recipient`);
|
|
544
|
+
}));
|
|
545
|
+
});
|
|
546
|
+
var RESOURCE_TASK_TYPES = new Set([
|
|
547
|
+
"action",
|
|
548
|
+
"agent",
|
|
549
|
+
"api-workflow",
|
|
550
|
+
"case-management",
|
|
551
|
+
"execute-connector-activity",
|
|
552
|
+
"function",
|
|
553
|
+
"process",
|
|
554
|
+
"rpa",
|
|
555
|
+
"wait-for-connector"
|
|
556
|
+
]);
|
|
557
|
+
var collectBindingReferences = (value, path, found) => {
|
|
558
|
+
if (typeof value === "string") {
|
|
559
|
+
if (value.startsWith(BINDING_REFERENCE_PREFIX)) {
|
|
560
|
+
const id = value.slice(BINDING_REFERENCE_PREFIX.length);
|
|
561
|
+
if (id !== "" && !found.has(id))
|
|
562
|
+
found.set(id, path);
|
|
563
|
+
}
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
if (Array.isArray(value)) {
|
|
567
|
+
value.forEach((entry, index) => {
|
|
568
|
+
collectBindingReferences(entry, `${path}[${index}]`, found);
|
|
569
|
+
});
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
const record = asRecord2(value);
|
|
573
|
+
if (record === undefined)
|
|
574
|
+
return;
|
|
575
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
576
|
+
collectBindingReferences(entry, `${path}.${key}`, found);
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
var isBindingReference = (value) => typeof value === "string" && value.startsWith(BINDING_REFERENCE_PREFIX);
|
|
580
|
+
var checkTaskBindings = (nodes) => {
|
|
581
|
+
const issues = [];
|
|
582
|
+
for (const node of nodes) {
|
|
583
|
+
const stage = asRecord2(node.data);
|
|
584
|
+
const stageName = typeof stage?.label === "string" ? stage.label : "";
|
|
585
|
+
for (const lane of asArray(stage?.tasks)) {
|
|
586
|
+
for (const task of asArray(lane)) {
|
|
587
|
+
const taskRecord = asRecord2(task);
|
|
588
|
+
const type = taskRecord?.type;
|
|
589
|
+
const data = asRecord2(taskRecord?.data);
|
|
590
|
+
if (typeof type !== "string" || !NAME_BOUND_TASK_TYPES.has(type) || data === undefined) {
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
const identity = RESOLVED_IDENTITY_KEYS.filter((key) => data[key] !== undefined);
|
|
594
|
+
const unbound = ["name", "folderPath"].filter((field) => !isBindingReference(data[field]));
|
|
595
|
+
const taskName = typeof taskRecord?.displayName === "string" ? taskRecord.displayName : type;
|
|
596
|
+
if (identity.length === 0) {
|
|
597
|
+
const named = ["name", "folderPath"].filter((field) => typeof data[field] === "string" && data[field] !== "");
|
|
598
|
+
if (named.length > 0)
|
|
599
|
+
continue;
|
|
600
|
+
if (Object.keys(data).length === 0)
|
|
601
|
+
continue;
|
|
602
|
+
issues.push({
|
|
603
|
+
code: "STRICT_BINDINGS_TASK_ABSENT",
|
|
604
|
+
path: `nodes[${stageName}].data.tasks[${taskName}].data`,
|
|
605
|
+
severity: "error",
|
|
606
|
+
message: `Task "${taskName}" (${type}) names no resource ` + "at all: no `name`, no `folderPath`, and no " + "resolved id. This plan binds its other " + "resources, so this one was missed rather than " + "left for later — and nothing reports it " + "otherwise, because the plan-wide bindings check " + "only fires on an empty array and the literal " + "check only fires on a literal. The task cannot " + "run: give it a name/folderPath binding pair."
|
|
607
|
+
});
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
if (unbound.length === 0)
|
|
611
|
+
continue;
|
|
612
|
+
issues.push({
|
|
613
|
+
code: "STRICT_BINDINGS_TASK_UNBOUND",
|
|
614
|
+
path: `nodes[${stageName}].data.tasks[${taskName}].data`,
|
|
615
|
+
severity: "error",
|
|
616
|
+
message: `Task "${taskName}" (${type}) pins its resource with ` + `${identity.join(", ")}, but ${unbound.join(" and ")} ` + `${unbound.length === 1 ? `is not a ${BINDING_REFERENCE_PREFIX} reference` : `are not ${BINDING_REFERENCE_PREFIX} references`}. A resolved ` + "resource task binds both: `name` and `folderPath` " + "each point at a root bindings entry, and " + "bindings_v2.json is derived from those. A raw id " + "binds nothing, so the solution ships resolving this " + "task to nothing, and the id itself does not survive " + "a move to another tenant. Bind the pair and drop the " + "raw id."
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
return issues;
|
|
622
|
+
};
|
|
623
|
+
var resourceTaskCount = (nodes) => {
|
|
624
|
+
let count = 0;
|
|
625
|
+
for (const node of nodes) {
|
|
626
|
+
for (const lane of asArray(asRecord2(node.data)?.tasks)) {
|
|
627
|
+
for (const task of asArray(lane)) {
|
|
628
|
+
const taskRecord = asRecord2(task);
|
|
629
|
+
const type = taskRecord?.type;
|
|
630
|
+
if (typeof type === "string" && RESOURCE_TASK_TYPES.has(type) && Object.keys(asRecord2(taskRecord?.data) ?? {}).length > 0) {
|
|
631
|
+
count += 1;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
return count;
|
|
637
|
+
};
|
|
638
|
+
var checkResourceBindings = (parsed, nodes) => {
|
|
639
|
+
const issues = [];
|
|
640
|
+
const bindings = asArray(parsed.bindings).map((entry) => asRecord2(entry)).filter((entry) => entry !== undefined);
|
|
641
|
+
const bindingIds = new Set(bindings.map((entry) => entry.id).filter((id) => typeof id === "string"));
|
|
642
|
+
const seenIds = new Set;
|
|
643
|
+
const reportedIds = new Set;
|
|
644
|
+
for (const entry of bindings) {
|
|
645
|
+
const id = entry.id;
|
|
646
|
+
if (typeof id !== "string" || id === "")
|
|
647
|
+
continue;
|
|
648
|
+
if (!seenIds.has(id)) {
|
|
649
|
+
seenIds.add(id);
|
|
650
|
+
continue;
|
|
651
|
+
}
|
|
652
|
+
if (reportedIds.has(id))
|
|
653
|
+
continue;
|
|
654
|
+
reportedIds.add(id);
|
|
655
|
+
issues.push({
|
|
656
|
+
code: "STRICT_BINDINGS_ID_DUPLICATE",
|
|
657
|
+
path: `bindings[${id}]`,
|
|
658
|
+
severity: "error",
|
|
659
|
+
message: `Two or more bindings share the id "${id}". A ` + `${BINDING_REFERENCE_PREFIX}${id} reference resolves to ` + "whichever entry a consumer scans first, so the one that " + "wins depends on array order — and the losing entry still " + "reads as though it applies. Give each entry its own id."
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
const references = new Map;
|
|
663
|
+
collectBindingReferences(parsed.nodes, "nodes", references);
|
|
664
|
+
collectBindingReferences(parsed.metadata, "metadata", references);
|
|
665
|
+
for (const [id, path] of references) {
|
|
666
|
+
if (bindingIds.has(id))
|
|
667
|
+
continue;
|
|
668
|
+
issues.push({
|
|
669
|
+
code: "STRICT_BINDINGS_REFERENCE_UNRESOLVED",
|
|
670
|
+
path,
|
|
671
|
+
severity: "error",
|
|
672
|
+
message: `"${BINDING_REFERENCE_PREFIX}${id}" points at no entry in the ` + "root bindings array, so nothing resolves it at run time. Add " + `a binding with id "${id}", or correct the reference.`
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
const everywhere = new Map;
|
|
676
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
677
|
+
if (key === "bindings")
|
|
678
|
+
continue;
|
|
679
|
+
collectBindingReferences(value, key, everywhere);
|
|
680
|
+
}
|
|
681
|
+
const referenced = new Set(everywhere.keys());
|
|
682
|
+
const unreferenced = new Set;
|
|
683
|
+
for (const entry of bindings) {
|
|
684
|
+
const id = entry.id;
|
|
685
|
+
if (typeof id !== "string" || id === "")
|
|
686
|
+
continue;
|
|
687
|
+
if (referenced.has(id) || unreferenced.has(id))
|
|
688
|
+
continue;
|
|
689
|
+
unreferenced.add(id);
|
|
690
|
+
const described = [entry.resource, entry.propertyAttribute].filter((part) => typeof part === "string" && part !== "").join(" ");
|
|
691
|
+
issues.push({
|
|
692
|
+
code: "STRICT_BINDINGS_UNREFERENCED",
|
|
693
|
+
path: `bindings[${id}]`,
|
|
694
|
+
severity: "warning",
|
|
695
|
+
message: `No node references the binding "${id}"` + (described === "" ? " (an entry with no `resource` or `propertyAttribute`, so it names no resource at all)" : ` (${described})`) + ", so it binds a resource nothing uses, and bindings_v2.json " + "carries it into the solution. Delete the entry and run " + "`uip maestro case bindings sync <caseplan.json>`, or " + `reference it as ${BINDING_REFERENCE_PREFIX}${id} from the ` + "task that needs it."
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
const resourceTasks = resourceTaskCount(nodes);
|
|
699
|
+
if (bindings.length > 0) {
|
|
700
|
+
issues.push(...checkTaskBindings(nodes));
|
|
701
|
+
} else if (resourceTasks > 0) {
|
|
702
|
+
issues.push({
|
|
703
|
+
code: "STRICT_BINDINGS_ABSENT",
|
|
704
|
+
path: "bindings",
|
|
705
|
+
severity: "warning",
|
|
706
|
+
message: `The root bindings array is empty, but ${resourceTasks} task(s) ` + "name a platform resource (process, agent, rpa, action, " + "api-workflow, function, child case or connector). Every such " + "task needs a name/folderPath binding pair — or, for a " + "connector, a connection and folder key — and bindings_v2.json " + "is derived from that array, so an empty one publishes a " + "solution that resolves none of them."
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
return issues;
|
|
710
|
+
};
|
|
711
|
+
var runStrictCaseRules = (parsed) => {
|
|
712
|
+
const nodes = Array.isArray(parsed.nodes) ? parsed.nodes : [];
|
|
713
|
+
const variables = asRecord2(parsed.variables);
|
|
714
|
+
const triggerIds = new Set(nodes.flatMap((node) => (nodeType(node) === "uipath.case.trigger" || nodeType(node) === "case-management:Trigger") && typeof node.id === "string" ? [node.id] : []));
|
|
715
|
+
return [
|
|
716
|
+
...checkStagesHaveTasks(nodes),
|
|
717
|
+
...checkJsExpressionsParse(parsed),
|
|
718
|
+
...checkJsExpressionScope(parsed),
|
|
719
|
+
...checkVariableContract(variables, triggerIds),
|
|
720
|
+
...checkInputOutputCompanions(variables, nodes),
|
|
721
|
+
...checkConnectorRuleContext(nodes, parsed.bindings),
|
|
722
|
+
...checkActionRecipientShape(nodes),
|
|
723
|
+
...checkResourceBindings(parsed, nodes),
|
|
724
|
+
...checkConnectionBindings(parsed)
|
|
725
|
+
];
|
|
726
|
+
};
|
|
727
|
+
export {
|
|
728
|
+
runStrictCaseRules
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
//# debugId=8B995151F8DE8CA864756E2164756E21
|