@uipath/packager-tool-datafabric 1.204.0 → 1.205.0-preview.258
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/canonical-path.d.ts +31 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +802 -58
- package/dist/init/entity-init-service.d.ts +7 -0
- package/dist/init.js +1243 -451
- package/dist/inline/inline-entity-service.d.ts +209 -0
- package/dist/inline.d.ts +8 -0
- package/dist/inline.js +3665 -0
- package/dist/missing-path.d.ts +19 -0
- package/dist/pack/constants.d.ts +3 -0
- package/dist/pack/verify-pair.d.ts +14 -1
- package/dist/resource/local-entities.d.ts +14 -0
- package/dist/resource/unified-resource-file.d.ts +21 -0
- package/dist/schema/author-field.d.ts +82 -0
- package/dist/schema/create-entity-skeleton.d.ts +21 -0
- package/dist/schema/solution-entity-names.d.ts +45 -0
- package/dist/schema/validate-entity.d.ts +12 -0
- package/dist/sort-names.d.ts +11 -0
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -1,11 +1,461 @@
|
|
|
1
|
+
// ../../common/src/telemetry/pseudonymize.ts
|
|
2
|
+
var SHA256_K = new Uint32Array([
|
|
3
|
+
1116352408,
|
|
4
|
+
1899447441,
|
|
5
|
+
3049323471,
|
|
6
|
+
3921009573,
|
|
7
|
+
961987163,
|
|
8
|
+
1508970993,
|
|
9
|
+
2453635748,
|
|
10
|
+
2870763221,
|
|
11
|
+
3624381080,
|
|
12
|
+
310598401,
|
|
13
|
+
607225278,
|
|
14
|
+
1426881987,
|
|
15
|
+
1925078388,
|
|
16
|
+
2162078206,
|
|
17
|
+
2614888103,
|
|
18
|
+
3248222580,
|
|
19
|
+
3835390401,
|
|
20
|
+
4022224774,
|
|
21
|
+
264347078,
|
|
22
|
+
604807628,
|
|
23
|
+
770255983,
|
|
24
|
+
1249150122,
|
|
25
|
+
1555081692,
|
|
26
|
+
1996064986,
|
|
27
|
+
2554220882,
|
|
28
|
+
2821834349,
|
|
29
|
+
2952996808,
|
|
30
|
+
3210313671,
|
|
31
|
+
3336571891,
|
|
32
|
+
3584528711,
|
|
33
|
+
113926993,
|
|
34
|
+
338241895,
|
|
35
|
+
666307205,
|
|
36
|
+
773529912,
|
|
37
|
+
1294757372,
|
|
38
|
+
1396182291,
|
|
39
|
+
1695183700,
|
|
40
|
+
1986661051,
|
|
41
|
+
2177026350,
|
|
42
|
+
2456956037,
|
|
43
|
+
2730485921,
|
|
44
|
+
2820302411,
|
|
45
|
+
3259730800,
|
|
46
|
+
3345764771,
|
|
47
|
+
3516065817,
|
|
48
|
+
3600352804,
|
|
49
|
+
4094571909,
|
|
50
|
+
275423344,
|
|
51
|
+
430227734,
|
|
52
|
+
506948616,
|
|
53
|
+
659060556,
|
|
54
|
+
883997877,
|
|
55
|
+
958139571,
|
|
56
|
+
1322822218,
|
|
57
|
+
1537002063,
|
|
58
|
+
1747873779,
|
|
59
|
+
1955562222,
|
|
60
|
+
2024104815,
|
|
61
|
+
2227730452,
|
|
62
|
+
2361852424,
|
|
63
|
+
2428436474,
|
|
64
|
+
2756734187,
|
|
65
|
+
3204031479,
|
|
66
|
+
3329325298
|
|
67
|
+
]);
|
|
68
|
+
var SHA256_INITIAL_STATE = new Uint32Array([
|
|
69
|
+
1779033703,
|
|
70
|
+
3144134277,
|
|
71
|
+
1013904242,
|
|
72
|
+
2773480762,
|
|
73
|
+
1359893119,
|
|
74
|
+
2600822924,
|
|
75
|
+
528734635,
|
|
76
|
+
1541459225
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
// ../../common/src/singleton.ts
|
|
80
|
+
var PREFIX = "@uipath/common/";
|
|
81
|
+
var _g = globalThis;
|
|
82
|
+
function singleton(ctorOrName) {
|
|
83
|
+
const name = typeof ctorOrName === "string" ? ctorOrName : ctorOrName.name;
|
|
84
|
+
const key = Symbol.for(PREFIX + name);
|
|
85
|
+
return {
|
|
86
|
+
get(fallback) {
|
|
87
|
+
return _g[key] ?? fallback;
|
|
88
|
+
},
|
|
89
|
+
set(value) {
|
|
90
|
+
_g[key] = value;
|
|
91
|
+
},
|
|
92
|
+
clear() {
|
|
93
|
+
delete _g[key];
|
|
94
|
+
},
|
|
95
|
+
getOrInit(factory, guard) {
|
|
96
|
+
const existing = _g[key];
|
|
97
|
+
if (existing != null && typeof existing === "object") {
|
|
98
|
+
if (!guard || guard(existing)) {
|
|
99
|
+
return existing;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const instance = factory();
|
|
103
|
+
_g[key] = instance;
|
|
104
|
+
return instance;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ../../common/src/telemetry/supplied-values.ts
|
|
110
|
+
var suppliedValuesSlot = singleton("TelemetrySuppliedArgumentValues");
|
|
111
|
+
|
|
112
|
+
// ../../common/src/telemetry/pii-redactor.ts
|
|
113
|
+
var SENSITIVE_NAME_TOKENS = new Set([
|
|
114
|
+
"token",
|
|
115
|
+
"tokens",
|
|
116
|
+
"secret",
|
|
117
|
+
"secrets",
|
|
118
|
+
"password",
|
|
119
|
+
"passwords",
|
|
120
|
+
"pwd",
|
|
121
|
+
"credential",
|
|
122
|
+
"credentials",
|
|
123
|
+
"auth",
|
|
124
|
+
"authentication",
|
|
125
|
+
"authorization",
|
|
126
|
+
"authority",
|
|
127
|
+
"cert",
|
|
128
|
+
"certificate",
|
|
129
|
+
"certificates"
|
|
130
|
+
]);
|
|
131
|
+
var SENSITIVE_KEY_PREFIXES = new Set([
|
|
132
|
+
"api",
|
|
133
|
+
"access",
|
|
134
|
+
"client",
|
|
135
|
+
"private",
|
|
136
|
+
"public",
|
|
137
|
+
"signing",
|
|
138
|
+
"encryption",
|
|
139
|
+
"session",
|
|
140
|
+
"master",
|
|
141
|
+
"shared",
|
|
142
|
+
"root",
|
|
143
|
+
"ssh",
|
|
144
|
+
"rsa",
|
|
145
|
+
"aes",
|
|
146
|
+
"hmac",
|
|
147
|
+
"oauth"
|
|
148
|
+
]);
|
|
149
|
+
var SOURCE_FILE_EXTENSIONS = new Set([
|
|
150
|
+
"ts",
|
|
151
|
+
"tsx",
|
|
152
|
+
"js",
|
|
153
|
+
"jsx",
|
|
154
|
+
"mjs",
|
|
155
|
+
"cjs",
|
|
156
|
+
"cts",
|
|
157
|
+
"mts",
|
|
158
|
+
"py",
|
|
159
|
+
"cs",
|
|
160
|
+
"java",
|
|
161
|
+
"go",
|
|
162
|
+
"rs",
|
|
163
|
+
"rb",
|
|
164
|
+
"php",
|
|
165
|
+
"sh",
|
|
166
|
+
"ps1",
|
|
167
|
+
"json",
|
|
168
|
+
"jsonc",
|
|
169
|
+
"yaml",
|
|
170
|
+
"yml",
|
|
171
|
+
"xml",
|
|
172
|
+
"xaml",
|
|
173
|
+
"md",
|
|
174
|
+
"txt",
|
|
175
|
+
"log",
|
|
176
|
+
"css",
|
|
177
|
+
"html",
|
|
178
|
+
"htm",
|
|
179
|
+
"csproj",
|
|
180
|
+
"nuspec",
|
|
181
|
+
"sql"
|
|
182
|
+
]);
|
|
183
|
+
var QUOTED_LITERAL_MAX_SPAN = 200;
|
|
184
|
+
var QUOTED_LITERAL_PATTERN = new RegExp([
|
|
185
|
+
`(?<![A-Za-z0-9])'(?:[^\\
|
|
186
|
+
]|\\.){2,${QUOTED_LITERAL_MAX_SPAN}}?'(?![A-Za-z0-9])`,
|
|
187
|
+
`(?<![A-Za-z0-9])"(?:[^\\
|
|
188
|
+
]|\\.){2,${QUOTED_LITERAL_MAX_SPAN}}?"(?![A-Za-z0-9])`
|
|
189
|
+
].join("|"), "g");
|
|
190
|
+
var MESSAGE_NAMES = new Set([
|
|
191
|
+
"message",
|
|
192
|
+
"errormessage",
|
|
193
|
+
"errmessage",
|
|
194
|
+
"error_message",
|
|
195
|
+
"msg",
|
|
196
|
+
"detail",
|
|
197
|
+
"details",
|
|
198
|
+
"reason",
|
|
199
|
+
"instructions",
|
|
200
|
+
"warning"
|
|
201
|
+
]);
|
|
202
|
+
function nameTokens(name) {
|
|
203
|
+
return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[\s._-]+/).map((t) => t.toLowerCase()).filter(Boolean);
|
|
204
|
+
}
|
|
205
|
+
function isSensitiveName(name) {
|
|
206
|
+
const tokens = nameTokens(name);
|
|
207
|
+
for (let i = 0;i < tokens.length; i++) {
|
|
208
|
+
const token = tokens[i];
|
|
209
|
+
if (SENSITIVE_NAME_TOKENS.has(token)) {
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
if (token === "key" || token === "keys") {
|
|
213
|
+
const prev = tokens[i - 1];
|
|
214
|
+
if (prev && SENSITIVE_KEY_PREFIXES.has(prev)) {
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ../../common/src/catch-error.ts
|
|
223
|
+
var MAX_SERIALIZED_LENGTH = 500;
|
|
224
|
+
var TRUNCATION_SUFFIX = "…(truncated)";
|
|
225
|
+
var REDACTED = "[REDACTED]";
|
|
226
|
+
function cap(text) {
|
|
227
|
+
return text.length > MAX_SERIALIZED_LENGTH ? `${text.slice(0, MAX_SERIALIZED_LENGTH)}${TRUNCATION_SUFFIX}` : text;
|
|
228
|
+
}
|
|
229
|
+
function omitSensitive(key, value) {
|
|
230
|
+
return key.length > 0 && isSensitiveName(key) ? REDACTED : value;
|
|
231
|
+
}
|
|
232
|
+
function describeThrownValue(value) {
|
|
233
|
+
if (typeof value !== "object" || value === null) {
|
|
234
|
+
return String(value);
|
|
235
|
+
}
|
|
236
|
+
let message;
|
|
237
|
+
try {
|
|
238
|
+
message = value.message;
|
|
239
|
+
} catch {
|
|
240
|
+
message = undefined;
|
|
241
|
+
}
|
|
242
|
+
if (typeof message === "string" && message.length > 0) {
|
|
243
|
+
return cap(message);
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
const json = JSON.stringify(value, omitSensitive);
|
|
247
|
+
if (json !== undefined) {
|
|
248
|
+
return cap(json);
|
|
249
|
+
}
|
|
250
|
+
} catch {}
|
|
251
|
+
return String(value);
|
|
252
|
+
}
|
|
253
|
+
function toError(error) {
|
|
254
|
+
return error instanceof Error ? error : new Error(describeThrownValue(error), { cause: error });
|
|
255
|
+
}
|
|
256
|
+
function isPromiseLike(value) {
|
|
257
|
+
return value !== null && typeof value === "object" && typeof value.then === "function";
|
|
258
|
+
}
|
|
259
|
+
function catchError(fnOrPromise) {
|
|
260
|
+
if (isPromiseLike(fnOrPromise)) {
|
|
261
|
+
return settlePromiseLike(fnOrPromise);
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
const result = fnOrPromise();
|
|
265
|
+
if (isPromiseLike(result)) {
|
|
266
|
+
return settlePromiseLike(result);
|
|
267
|
+
}
|
|
268
|
+
return [undefined, result];
|
|
269
|
+
} catch (error) {
|
|
270
|
+
return [toError(error), undefined];
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function settlePromiseLike(thenable) {
|
|
274
|
+
return Promise.resolve(thenable).then((data) => [undefined, data]).catch((error) => [toError(error), undefined]);
|
|
275
|
+
}
|
|
276
|
+
|
|
1
277
|
// src/pack/entity-project-tool.ts
|
|
2
278
|
import {
|
|
3
279
|
ProjectTool,
|
|
4
280
|
ToolResult
|
|
5
281
|
} from "@uipath/solutionpackager-tool-core";
|
|
6
282
|
|
|
283
|
+
// src/missing-path.ts
|
|
284
|
+
function isMissingPathError(error) {
|
|
285
|
+
if (!(error instanceof Error) || !("code" in error))
|
|
286
|
+
return false;
|
|
287
|
+
const { code } = error;
|
|
288
|
+
return code === "ENOENT" || code === "ENOTDIR" || code === "PathNotFound";
|
|
289
|
+
}
|
|
290
|
+
function isFilesystemError(error) {
|
|
291
|
+
const code = error?.code;
|
|
292
|
+
return typeof code === "string" && /^E[A-Z]+$/.test(code);
|
|
293
|
+
}
|
|
294
|
+
function isUnreadablePathError(error) {
|
|
295
|
+
return isFilesystemError(error) && !isMissingPathError(error);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// src/pack/constants.ts
|
|
299
|
+
var ENTITY_EXTENSION_CONST = ".entity";
|
|
300
|
+
var ENTITY_VALIDATION_FAILED = "ENTITY_VALIDATION_FAILED";
|
|
301
|
+
var PACK_DIAGNOSTIC_CODES = {
|
|
302
|
+
misplacedMainFile: "MISPLACED_MAIN_FILE",
|
|
303
|
+
noParentSolution: "NO_PARENT_SOLUTION",
|
|
304
|
+
solutionRootUnreadable: "SOLUTION_ROOT_UNREADABLE"
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// src/schema/solution-entity-names.ts
|
|
308
|
+
function withoutOneOccurrence(names, name) {
|
|
309
|
+
const siblings = [...names];
|
|
310
|
+
const self = siblings.indexOf(name);
|
|
311
|
+
if (self >= 0) {
|
|
312
|
+
siblings.splice(self, 1);
|
|
313
|
+
}
|
|
314
|
+
return siblings;
|
|
315
|
+
}
|
|
316
|
+
function isMissingPath(error) {
|
|
317
|
+
return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "PathNotFound");
|
|
318
|
+
}
|
|
319
|
+
async function collectSolutionEntityNames(solutionDir, fs) {
|
|
320
|
+
const names = [];
|
|
321
|
+
let topLevel = [];
|
|
322
|
+
try {
|
|
323
|
+
topLevel = await fs.readdir(solutionDir);
|
|
324
|
+
} catch (error) {
|
|
325
|
+
if (!isMissingPath(error)) {
|
|
326
|
+
throw error;
|
|
327
|
+
}
|
|
328
|
+
return names;
|
|
329
|
+
}
|
|
330
|
+
for (const entry of topLevel) {
|
|
331
|
+
if (entry === "resources" || entry.startsWith(".")) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
const dir = fs.path.join(solutionDir, entry);
|
|
335
|
+
try {
|
|
336
|
+
const stat = await fs.stat(dir);
|
|
337
|
+
if (!stat?.isDirectory()) {
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
for (const file of await fs.readdir(dir)) {
|
|
341
|
+
if (file.endsWith(ENTITY_EXTENSION_CONST)) {
|
|
342
|
+
names.push(fs.path.basename(file, ENTITY_EXTENSION_CONST));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
} catch (error) {
|
|
346
|
+
if (!isMissingPath(error)) {
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return names;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// ../../common/src/entity-field-rules.ts
|
|
355
|
+
var MAX_SAFE_NUMERIC_BOUND = 9007199254740991;
|
|
356
|
+
var LENGTH_LIMIT_RANGES = {
|
|
357
|
+
STRING: [1, 4000],
|
|
358
|
+
MULTILINE_TEXT: [1, 1e4],
|
|
359
|
+
MULTILINE_MAX: [1, 131072]
|
|
360
|
+
};
|
|
361
|
+
var MAX_MULTILINE_MAX_FIELDS = 10;
|
|
362
|
+
function isNumber(v) {
|
|
363
|
+
return typeof v === "number" && Number.isFinite(v);
|
|
364
|
+
}
|
|
365
|
+
function findInvalidFieldConstraints(fields) {
|
|
366
|
+
for (const f of fields) {
|
|
367
|
+
if (typeof f !== "object" || f === null)
|
|
368
|
+
continue;
|
|
369
|
+
const rec = f;
|
|
370
|
+
const type = rec.type;
|
|
371
|
+
if (typeof type !== "string")
|
|
372
|
+
continue;
|
|
373
|
+
const fieldName = typeof rec.name === "string" ? rec.name : "<field>";
|
|
374
|
+
if (rec.lengthLimit !== undefined) {
|
|
375
|
+
if (!isNumber(rec.lengthLimit) || !Number.isInteger(rec.lengthLimit)) {
|
|
376
|
+
return {
|
|
377
|
+
message: `Field '${fieldName}' 'lengthLimit' must be an integer`,
|
|
378
|
+
instructions: "Pass a positive integer within the type's range (STRING 1-4000, MULTILINE_TEXT 1-10000, MULTILINE_MAX 1-131072 UTF-16 bytes)."
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
const range = LENGTH_LIMIT_RANGES[type];
|
|
382
|
+
if (range === undefined) {
|
|
383
|
+
return {
|
|
384
|
+
message: `Field '${fieldName}' of type '${type}' does not accept 'lengthLimit'`,
|
|
385
|
+
instructions: "'lengthLimit' applies only to STRING, MULTILINE_TEXT, and MULTILINE_MAX. Remove it or change the field type."
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
const [min, max] = range;
|
|
389
|
+
if (rec.lengthLimit < min || rec.lengthLimit > max) {
|
|
390
|
+
return {
|
|
391
|
+
message: `Field '${fieldName}' 'lengthLimit' ${rec.lengthLimit} is outside the allowed range for type '${type}'`,
|
|
392
|
+
instructions: `'lengthLimit' on '${type}' must be between ${min} and ${max}. MULTILINE_MAX 'lengthLimit' is a UTF-16 byte budget (≈2 per char).`
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (rec.maxValue !== undefined || rec.minValue !== undefined) {
|
|
397
|
+
if (type !== "DECIMAL" && type !== "AUTO_NUMBER") {
|
|
398
|
+
const which = rec.maxValue !== undefined ? "maxValue" : "minValue";
|
|
399
|
+
return {
|
|
400
|
+
message: `Field '${fieldName}' of type '${type}' does not accept '${which}'`,
|
|
401
|
+
instructions: "'minValue' and 'maxValue' apply only to DECIMAL and AUTO_NUMBER. Remove them or change the field type."
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
if (rec.maxValue !== undefined && !isNumber(rec.maxValue)) {
|
|
405
|
+
return {
|
|
406
|
+
message: `Field '${fieldName}' 'maxValue' must be a number`,
|
|
407
|
+
instructions: "Pass a numeric value."
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
if (rec.minValue !== undefined && !isNumber(rec.minValue)) {
|
|
411
|
+
return {
|
|
412
|
+
message: `Field '${fieldName}' 'minValue' must be a number`,
|
|
413
|
+
instructions: "Pass a numeric value."
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
const maxValue = rec.maxValue;
|
|
417
|
+
if (maxValue !== undefined && (maxValue > MAX_SAFE_NUMERIC_BOUND || maxValue < -MAX_SAFE_NUMERIC_BOUND)) {
|
|
418
|
+
return {
|
|
419
|
+
message: `Field '${fieldName}' 'maxValue' ${rec.maxValue} is outside the supported numeric range`,
|
|
420
|
+
instructions: `Use a value between ${-MAX_SAFE_NUMERIC_BOUND} and ${MAX_SAFE_NUMERIC_BOUND}.`
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
const minValue = rec.minValue;
|
|
424
|
+
if (minValue !== undefined && (minValue > MAX_SAFE_NUMERIC_BOUND || minValue < -MAX_SAFE_NUMERIC_BOUND)) {
|
|
425
|
+
return {
|
|
426
|
+
message: `Field '${fieldName}' 'minValue' ${rec.minValue} is outside the supported numeric range`,
|
|
427
|
+
instructions: `Use a value between ${-MAX_SAFE_NUMERIC_BOUND} and ${MAX_SAFE_NUMERIC_BOUND}.`
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
if (rec.maxValue !== undefined && rec.minValue !== undefined && rec.minValue > rec.maxValue) {
|
|
431
|
+
return {
|
|
432
|
+
message: `Field '${fieldName}' 'minValue' (${rec.minValue}) must not exceed 'maxValue' (${rec.maxValue})`,
|
|
433
|
+
instructions: "Adjust the bounds so 'minValue <= maxValue', or drop one of the two."
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
if (rec.decimalPrecision !== undefined) {
|
|
438
|
+
if (type !== "DECIMAL" && type !== "AUTO_NUMBER") {
|
|
439
|
+
return {
|
|
440
|
+
message: `Field '${fieldName}' of type '${type}' does not accept 'decimalPrecision'`,
|
|
441
|
+
instructions: "'decimalPrecision' applies only to DECIMAL and AUTO_NUMBER. Remove it or change the field type."
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
if (!isNumber(rec.decimalPrecision) || !Number.isInteger(rec.decimalPrecision) || rec.decimalPrecision < 0 || rec.decimalPrecision > 10) {
|
|
445
|
+
return {
|
|
446
|
+
message: `Field '${fieldName}' 'decimalPrecision' ${rec.decimalPrecision} is invalid`,
|
|
447
|
+
instructions: "'decimalPrecision' must be an integer between 0 and 10 (0 for whole numbers, 2 for money)."
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
|
|
7
455
|
// ../../common/src/entity-name-rules.ts
|
|
8
456
|
var RESERVED_SQL_KEYWORDS_LOWER = new Set(["group", "order"]);
|
|
457
|
+
var ENTITY_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_]{2,99}$/;
|
|
458
|
+
var FIELD_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9]{2,99}$/;
|
|
9
459
|
var RESERVED_FIELD_NAMES_LOWER = new Set([
|
|
10
460
|
"id",
|
|
11
461
|
"createdby",
|
|
@@ -223,6 +673,16 @@ function findReservedNameError(name, kind) {
|
|
|
223
673
|
}
|
|
224
674
|
return null;
|
|
225
675
|
}
|
|
676
|
+
function validateNameFormat(name, kind) {
|
|
677
|
+
const pattern = kind === "field" ? FIELD_NAME_PATTERN : ENTITY_NAME_PATTERN;
|
|
678
|
+
if (pattern.test(name)) {
|
|
679
|
+
return null;
|
|
680
|
+
}
|
|
681
|
+
return {
|
|
682
|
+
message: `Invalid ${kind} name '${name}'`,
|
|
683
|
+
instructions: kind === "field" ? "Field names must start with a letter, contain only letters and digits (no underscores), and be 3-100 characters long." : "Names must start with a letter, contain only letters, digits, and underscores, and be 3-100 characters long."
|
|
684
|
+
};
|
|
685
|
+
}
|
|
226
686
|
|
|
227
687
|
// ../../../node_modules/@uipath/entity-modeler/dist/chunk-7VKIHCI7.js
|
|
228
688
|
var SqlTypeName = {
|
|
@@ -250,7 +710,7 @@ var FieldDisplayType = {
|
|
|
250
710
|
AutoNumber: "AutoNumber",
|
|
251
711
|
MultiLineText: "MultiLineText"
|
|
252
712
|
};
|
|
253
|
-
var
|
|
713
|
+
var DEFAULT_REFERENCE_TYPE = "ManyToOne";
|
|
254
714
|
var CSHARP_RESERVED_WORDS = [
|
|
255
715
|
"__arglist",
|
|
256
716
|
"__makeref",
|
|
@@ -514,8 +974,158 @@ var GA_TYPE_PAIRS = [
|
|
|
514
974
|
[FieldDisplayType.File, SqlTypeName.UNIQUEIDENTIFIER]
|
|
515
975
|
];
|
|
516
976
|
var ALLOWED_TYPE_PAIRS = new Set(GA_TYPE_PAIRS.map(([display, sql]) => `${display}:${sql}`));
|
|
977
|
+
// src/sort-names.ts
|
|
978
|
+
function byName(a, b) {
|
|
979
|
+
return a.localeCompare(b, "en");
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// src/schema/author-field.ts
|
|
983
|
+
var TYPE_MAP = {
|
|
984
|
+
STRING: [FieldDisplayType.Basic, SqlTypeName.NVARCHAR],
|
|
985
|
+
DECIMAL: [FieldDisplayType.Basic, SqlTypeName.DECIMAL],
|
|
986
|
+
BOOLEAN: [FieldDisplayType.Basic, SqlTypeName.BIT],
|
|
987
|
+
DATE: [FieldDisplayType.Basic, SqlTypeName.DATE],
|
|
988
|
+
DATETIME_WITH_TZ: [FieldDisplayType.Basic, SqlTypeName.DATETIMEOFFSET],
|
|
989
|
+
MULTILINE_TEXT: [FieldDisplayType.Basic, SqlTypeName.MULTILINE],
|
|
990
|
+
MULTILINE_MAX: [FieldDisplayType.Basic, SqlTypeName.MULTILINE_MAX],
|
|
991
|
+
AUTO_NUMBER: [FieldDisplayType.AutoNumber, SqlTypeName.DECIMAL],
|
|
992
|
+
FILE: [FieldDisplayType.File, SqlTypeName.UNIQUEIDENTIFIER]
|
|
993
|
+
};
|
|
994
|
+
var AUTHORABLE_FIELD_TYPES = Object.freeze(Object.keys(TYPE_MAP).sort(byName));
|
|
995
|
+
var UNAUTHORABLE_TYPES = {
|
|
996
|
+
CHOICE_SET_SINGLE: "choice-set fields are not authorable locally — add the field in Data Fabric",
|
|
997
|
+
CHOICE_SET_MULTIPLE: "choice-set fields are not authorable locally — add the field in Data Fabric",
|
|
998
|
+
RELATIONSHIP: "relationship fields are not authorable locally — add the field in Data Fabric",
|
|
999
|
+
INTEGER: "use DECIMAL with decimalPrecision: 0",
|
|
1000
|
+
BIG_INTEGER: "use DECIMAL with decimalPrecision: 0",
|
|
1001
|
+
FLOAT: "use DECIMAL with a decimalPrecision",
|
|
1002
|
+
DOUBLE: "use DECIMAL with a decimalPrecision",
|
|
1003
|
+
UUID: "use STRING",
|
|
1004
|
+
DATETIME: "use DATETIME_WITH_TZ"
|
|
1005
|
+
};
|
|
1006
|
+
|
|
1007
|
+
class AuthoredFieldError extends Error {
|
|
1008
|
+
instructions;
|
|
1009
|
+
constructor(message, instructions) {
|
|
1010
|
+
super(message);
|
|
1011
|
+
this.instructions = instructions;
|
|
1012
|
+
this.name = "AuthoredFieldError";
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
function buildSqlType(name, spec) {
|
|
1016
|
+
const sqlType = { Name: name };
|
|
1017
|
+
if (spec.lengthLimit != null)
|
|
1018
|
+
sqlType.LengthLimit = spec.lengthLimit;
|
|
1019
|
+
if (spec.decimalPrecision != null)
|
|
1020
|
+
sqlType.DecimalPrecision = spec.decimalPrecision;
|
|
1021
|
+
if (spec.maxValue != null)
|
|
1022
|
+
sqlType.MaxValue = spec.maxValue;
|
|
1023
|
+
if (spec.minValue != null)
|
|
1024
|
+
sqlType.MinValue = spec.minValue;
|
|
1025
|
+
return sqlType;
|
|
1026
|
+
}
|
|
1027
|
+
var DEFAULT_VALUE_SHAPES = {
|
|
1028
|
+
BOOLEAN: '"true" or "false"',
|
|
1029
|
+
DECIMAL: 'a number in quotes, e.g. "0"',
|
|
1030
|
+
AUTO_NUMBER: 'a number in quotes, e.g. "0"'
|
|
1031
|
+
};
|
|
1032
|
+
function assertDefaultValue(spec, checkContent) {
|
|
1033
|
+
const value = spec.defaultValue;
|
|
1034
|
+
if (value === undefined || value === null) {
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
if (!checkContent) {
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
if (typeof value !== "string") {
|
|
1041
|
+
const shape = DEFAULT_VALUE_SHAPES[spec.type] ?? "a string";
|
|
1042
|
+
throw new AuthoredFieldError(`Field '${spec.name}': 'defaultValue' must be a string or null`, `Received ${JSON.stringify(value)}. Entity documents store every default as text, whatever the field type — for ${spec.type} pass ${shape}, or null to clear it.`);
|
|
1043
|
+
}
|
|
1044
|
+
if (spec.type === "BOOLEAN" && value.toLowerCase() !== "true" && value.toLowerCase() !== "false") {
|
|
1045
|
+
throw new AuthoredFieldError(`Field '${spec.name}': 'defaultValue' ${JSON.stringify(value)} is not a boolean`, 'A BOOLEAN default is the text "true" or "false".');
|
|
1046
|
+
}
|
|
1047
|
+
if ((spec.type === "DECIMAL" || spec.type === "AUTO_NUMBER") && (value.trim() === "" || !Number.isFinite(Number(value)))) {
|
|
1048
|
+
throw new AuthoredFieldError(`Field '${spec.name}': 'defaultValue' ${JSON.stringify(value)} is not a number`, `A ${spec.type} default is a number written as text, e.g. "0".`);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
function authorField(spec, options = {}) {
|
|
1052
|
+
const pair = TYPE_MAP[spec.type];
|
|
1053
|
+
if (pair === undefined) {
|
|
1054
|
+
const redirect = UNAUTHORABLE_TYPES[spec.type];
|
|
1055
|
+
throw new AuthoredFieldError(`Field '${spec.name}' has unsupported type '${spec.type}'`, redirect === undefined ? `Supported types: ${AUTHORABLE_FIELD_TYPES.join(", ")}.` : `${redirect}. Supported types: ${AUTHORABLE_FIELD_TYPES.join(", ")}.`);
|
|
1056
|
+
}
|
|
1057
|
+
const [fieldDisplayType, sqlTypeName] = pair;
|
|
1058
|
+
const pairKey = `${fieldDisplayType}:${sqlTypeName}`;
|
|
1059
|
+
if (!ALLOWED_TYPE_PAIRS.has(pairKey)) {
|
|
1060
|
+
throw new AuthoredFieldError(`Internal: type '${spec.type}' maps to ${pairKey}, which is not an allowed pair`, "This is a defect in author-field.ts — the type map has drifted from GA_TYPE_PAIRS.");
|
|
1061
|
+
}
|
|
1062
|
+
for (const [key, value] of [
|
|
1063
|
+
["isRequired", spec.isRequired],
|
|
1064
|
+
["isUnique", spec.isUnique]
|
|
1065
|
+
]) {
|
|
1066
|
+
if (value !== undefined && typeof value !== "boolean") {
|
|
1067
|
+
throw new AuthoredFieldError(`Field '${spec.name}': '${key}' must be true or false`, `Received ${JSON.stringify(value)}. Use a JSON boolean, not a string.`);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
for (const [key, value] of [
|
|
1071
|
+
["displayName", spec.displayName],
|
|
1072
|
+
["description", spec.description]
|
|
1073
|
+
]) {
|
|
1074
|
+
if (value !== undefined && typeof value !== "string") {
|
|
1075
|
+
throw new AuthoredFieldError(`Field '${spec.name}': '${key}' must be a string`, `Received ${JSON.stringify(value)}.`);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
assertDefaultValue(spec, options.defaultValueFromCaller !== false);
|
|
1079
|
+
const constraintError = findInvalidFieldConstraints([
|
|
1080
|
+
{
|
|
1081
|
+
name: spec.name,
|
|
1082
|
+
type: spec.type,
|
|
1083
|
+
...spec.lengthLimit != null && {
|
|
1084
|
+
lengthLimit: spec.lengthLimit
|
|
1085
|
+
},
|
|
1086
|
+
...spec.decimalPrecision != null && {
|
|
1087
|
+
decimalPrecision: spec.decimalPrecision
|
|
1088
|
+
},
|
|
1089
|
+
...spec.maxValue != null && { maxValue: spec.maxValue },
|
|
1090
|
+
...spec.minValue != null && { minValue: spec.minValue }
|
|
1091
|
+
}
|
|
1092
|
+
]);
|
|
1093
|
+
if (constraintError) {
|
|
1094
|
+
throw new AuthoredFieldError(constraintError.message, constraintError.instructions);
|
|
1095
|
+
}
|
|
1096
|
+
return {
|
|
1097
|
+
Name: spec.name,
|
|
1098
|
+
DisplayName: spec.displayName ?? spec.name,
|
|
1099
|
+
SqlType: buildSqlType(sqlTypeName, spec),
|
|
1100
|
+
IsRequired: spec.isRequired ?? false,
|
|
1101
|
+
IsUnique: spec.isUnique ?? false,
|
|
1102
|
+
IsPrimaryKey: false,
|
|
1103
|
+
IsForeignKey: false,
|
|
1104
|
+
IsExternalField: false,
|
|
1105
|
+
IsHiddenField: false,
|
|
1106
|
+
FieldCategoryId: 0,
|
|
1107
|
+
ReferenceType: DEFAULT_REFERENCE_TYPE,
|
|
1108
|
+
Transformation: null,
|
|
1109
|
+
IsEncrypted: false,
|
|
1110
|
+
Description: spec.description ?? "",
|
|
1111
|
+
IsSystemField: false,
|
|
1112
|
+
FieldDisplayType: fieldDisplayType,
|
|
1113
|
+
DefaultValue: spec.defaultValue ?? null,
|
|
1114
|
+
IsAttachment: false,
|
|
1115
|
+
IsRbacEnabled: false,
|
|
1116
|
+
IsModelReserved: false,
|
|
1117
|
+
ReferenceChoiceSet: null,
|
|
1118
|
+
ReferenceEntity: null,
|
|
1119
|
+
ReferenceField: null,
|
|
1120
|
+
ReferenceName: null
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
|
|
517
1124
|
// src/schema/create-entity-skeleton.ts
|
|
518
1125
|
var UNASSIGNED_FOLDER_ID = "99999999-9999-9999-9999-999999999999";
|
|
1126
|
+
function isLocallyAuthored(entity) {
|
|
1127
|
+
return entity.FolderId === UNASSIGNED_FOLDER_ID;
|
|
1128
|
+
}
|
|
519
1129
|
var SYSTEM_FIELD_DEFAULTS = {
|
|
520
1130
|
IsPrimaryKey: false,
|
|
521
1131
|
IsForeignKey: false,
|
|
@@ -605,14 +1215,27 @@ var DIAGNOSTIC_CODES = {
|
|
|
605
1215
|
fieldTypeNotAllowed: "FIELD_TYPE_NOT_ALLOWED",
|
|
606
1216
|
nameReserved: "NAME_RESERVED",
|
|
607
1217
|
systemFieldMissing: "SYSTEM_FIELD_MISSING",
|
|
608
|
-
systemFieldModified: "SYSTEM_FIELD_MODIFIED"
|
|
1218
|
+
systemFieldModified: "SYSTEM_FIELD_MODIFIED",
|
|
1219
|
+
fieldsMalformed: "FIELDS_MALFORMED",
|
|
1220
|
+
tooManyMultilineMax: "TOO_MANY_MULTILINE_MAX",
|
|
1221
|
+
propertyTypeInvalid: "PROPERTY_TYPE_INVALID"
|
|
609
1222
|
};
|
|
610
1223
|
function validateEntity(entity, ctx) {
|
|
611
1224
|
const diagnostics = [];
|
|
612
|
-
if (
|
|
1225
|
+
if (typeof entity?.Name !== "string") {
|
|
1226
|
+
return [
|
|
1227
|
+
{
|
|
1228
|
+
code: DIAGNOSTIC_CODES.entityNameInvalid,
|
|
1229
|
+
message: "The entity document has no 'Name'. The resource is malformed.",
|
|
1230
|
+
severity: "error"
|
|
1231
|
+
}
|
|
1232
|
+
];
|
|
1233
|
+
}
|
|
1234
|
+
const entityNameFormat = validateNameFormat(entity.Name, "entity");
|
|
1235
|
+
if (entityNameFormat) {
|
|
613
1236
|
diagnostics.push({
|
|
614
1237
|
code: DIAGNOSTIC_CODES.entityNameInvalid,
|
|
615
|
-
message:
|
|
1238
|
+
message: `${entityNameFormat.message}. ${entityNameFormat.instructions}`,
|
|
616
1239
|
severity: "error"
|
|
617
1240
|
});
|
|
618
1241
|
}
|
|
@@ -632,17 +1255,39 @@ function validateEntity(entity, ctx) {
|
|
|
632
1255
|
severity: "error"
|
|
633
1256
|
});
|
|
634
1257
|
}
|
|
1258
|
+
diagnostics.push(...typeProblems(entity, ENTITY_SCALARS).map((problem) => propertyTypeDiagnostic(`Entity '${entity.Name}'`, problem)));
|
|
1259
|
+
if (!Array.isArray(entity.Fields)) {
|
|
1260
|
+
diagnostics.push({
|
|
1261
|
+
code: DIAGNOSTIC_CODES.fieldsMalformed,
|
|
1262
|
+
message: "The entity document has no usable 'Fields' array. The resource is malformed.",
|
|
1263
|
+
severity: "error"
|
|
1264
|
+
});
|
|
1265
|
+
return diagnostics;
|
|
1266
|
+
}
|
|
635
1267
|
const seenFieldNames = new Map;
|
|
636
1268
|
for (const field of entity.Fields) {
|
|
637
|
-
if (
|
|
1269
|
+
if (typeof field?.Name !== "string") {
|
|
1270
|
+
diagnostics.push({
|
|
1271
|
+
code: DIAGNOSTIC_CODES.fieldNameInvalid,
|
|
1272
|
+
message: "A field has no 'Name'. Every field needs one, system or custom.",
|
|
1273
|
+
severity: "error"
|
|
1274
|
+
});
|
|
1275
|
+
continue;
|
|
1276
|
+
}
|
|
1277
|
+
const isSystem = isSystemField(field);
|
|
1278
|
+
if (!SYSTEM_FIELD_NAMES.has(field.Name)) {
|
|
1279
|
+
diagnostics.push(...fieldTypeDiagnostics(field));
|
|
1280
|
+
}
|
|
1281
|
+
const fieldNameFormat = isSystem ? null : validateNameFormat(field.Name, "field");
|
|
1282
|
+
if (fieldNameFormat) {
|
|
638
1283
|
diagnostics.push({
|
|
639
1284
|
code: DIAGNOSTIC_CODES.fieldNameInvalid,
|
|
640
|
-
message:
|
|
1285
|
+
message: `${fieldNameFormat.message}. ${fieldNameFormat.instructions}`,
|
|
641
1286
|
severity: "error",
|
|
642
1287
|
fieldName: field.Name
|
|
643
1288
|
});
|
|
644
1289
|
}
|
|
645
|
-
if (!
|
|
1290
|
+
if (!isSystem) {
|
|
646
1291
|
const reservedFieldName = findReservedNameError(field.Name, "field");
|
|
647
1292
|
if (reservedFieldName) {
|
|
648
1293
|
diagnostics.push({
|
|
@@ -654,6 +1299,14 @@ function validateEntity(entity, ctx) {
|
|
|
654
1299
|
}
|
|
655
1300
|
}
|
|
656
1301
|
const fieldNameLower = field.Name.toLowerCase();
|
|
1302
|
+
if (!isSystem && typeof entity.Name === "string" && fieldNameLower === entity.Name.toLowerCase()) {
|
|
1303
|
+
diagnostics.push({
|
|
1304
|
+
code: DIAGNOSTIC_CODES.fieldNameInvalid,
|
|
1305
|
+
message: `Field name '${field.Name}' cannot match entity name '${entity.Name}' (names are compared case-insensitively).`,
|
|
1306
|
+
severity: "error",
|
|
1307
|
+
fieldName: field.Name
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
657
1310
|
const firstWithName = seenFieldNames.get(fieldNameLower);
|
|
658
1311
|
if (firstWithName !== undefined) {
|
|
659
1312
|
diagnostics.push({
|
|
@@ -665,16 +1318,25 @@ function validateEntity(entity, ctx) {
|
|
|
665
1318
|
} else {
|
|
666
1319
|
seenFieldNames.set(fieldNameLower, field.Name);
|
|
667
1320
|
}
|
|
668
|
-
if (!
|
|
1321
|
+
if (!isSystem && !ALLOWED_TYPE_PAIRS.has(`${field.FieldDisplayType}:${field.SqlType?.Name}`)) {
|
|
669
1322
|
diagnostics.push({
|
|
670
1323
|
code: DIAGNOSTIC_CODES.fieldTypeNotAllowed,
|
|
671
|
-
message: `Field '${field.Name}' uses an unsupported type combination ` + `(${field.FieldDisplayType} / ${field.SqlType
|
|
1324
|
+
message: `Field '${field.Name}' uses an unsupported type combination ` + `(${field.FieldDisplayType} / ${field.SqlType?.Name}).`,
|
|
672
1325
|
severity: "error",
|
|
673
1326
|
fieldName: field.Name
|
|
674
1327
|
});
|
|
675
1328
|
}
|
|
676
1329
|
}
|
|
677
|
-
|
|
1330
|
+
const usableFields = entity.Fields.filter((field) => typeof field === "object" && field !== null);
|
|
1331
|
+
const multilineMax = usableFields.filter((field) => field.SqlType?.Name === SqlTypeName.MULTILINE_MAX);
|
|
1332
|
+
if (multilineMax.length > MAX_MULTILINE_MAX_FIELDS) {
|
|
1333
|
+
diagnostics.push({
|
|
1334
|
+
code: DIAGNOSTIC_CODES.tooManyMultilineMax,
|
|
1335
|
+
message: `Entity '${entity.Name}' defines ${multilineMax.length} MULTILINE_MAX fields; ` + `the maximum is ${MAX_MULTILINE_MAX_FIELDS}. Remove some, or use MULTILINE_TEXT where the content fits.`,
|
|
1336
|
+
severity: "error"
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
diagnostics.push(...validateSystemFields(entity, usableFields));
|
|
678
1340
|
return diagnostics;
|
|
679
1341
|
}
|
|
680
1342
|
var SERVER_ASSIGNED_FIELD_PROPS = new Set([
|
|
@@ -693,10 +1355,10 @@ function isUnmodifiedSystemField(template, actual) {
|
|
|
693
1355
|
}
|
|
694
1356
|
return Object.keys(actual).every((key) => (key in template) || SERVER_ASSIGNED_FIELD_PROPS.has(key));
|
|
695
1357
|
}
|
|
696
|
-
function validateSystemFields(entity) {
|
|
1358
|
+
function validateSystemFields(entity, usableFields) {
|
|
697
1359
|
const diagnostics = [];
|
|
698
1360
|
for (const template of SYSTEM_FIELD_TEMPLATES) {
|
|
699
|
-
const actual =
|
|
1361
|
+
const actual = usableFields.find((field) => field.Name === template.Name);
|
|
700
1362
|
if (!actual) {
|
|
701
1363
|
diagnostics.push({
|
|
702
1364
|
code: DIAGNOSTIC_CODES.systemFieldMissing,
|
|
@@ -717,14 +1379,75 @@ function validateSystemFields(entity) {
|
|
|
717
1379
|
}
|
|
718
1380
|
return diagnostics;
|
|
719
1381
|
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
var
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
}
|
|
1382
|
+
function isSystemField(field) {
|
|
1383
|
+
const { IsSystemField: flag, Name: name } = field ?? {};
|
|
1384
|
+
return flag === true || typeof name === "string" && SYSTEM_FIELD_NAMES.has(name);
|
|
1385
|
+
}
|
|
1386
|
+
var SYSTEM_FIELD_NAMES = new Set(SYSTEM_FIELD_TEMPLATES.map((template) => template.Name));
|
|
1387
|
+
var ENTITY_SCALARS = [
|
|
1388
|
+
{ key: "DisplayName", kind: "string" },
|
|
1389
|
+
{ key: "Description", kind: "string" },
|
|
1390
|
+
{ key: "EntityTypeId", kind: "integer" },
|
|
1391
|
+
{ key: "RecordCount", kind: "integer" },
|
|
1392
|
+
{ key: "IsRbacEnabled", kind: "boolean" },
|
|
1393
|
+
{ key: "IsModelReserved", kind: "boolean" }
|
|
1394
|
+
];
|
|
1395
|
+
var FIELD_SCALARS = [
|
|
1396
|
+
{ key: "DisplayName", kind: "string" },
|
|
1397
|
+
{ key: "Description", kind: "string" },
|
|
1398
|
+
{ key: "ReferenceType", kind: "string" },
|
|
1399
|
+
{ key: "FieldCategoryId", kind: "integer" },
|
|
1400
|
+
{ key: "IsRequired", kind: "boolean" },
|
|
1401
|
+
{ key: "IsUnique", kind: "boolean" },
|
|
1402
|
+
{ key: "IsPrimaryKey", kind: "boolean" },
|
|
1403
|
+
{ key: "IsForeignKey", kind: "boolean" },
|
|
1404
|
+
{ key: "IsSystemField", kind: "boolean" },
|
|
1405
|
+
{ key: "IsExternalField", kind: "boolean" },
|
|
1406
|
+
{ key: "IsHiddenField", kind: "boolean" },
|
|
1407
|
+
{ key: "IsEncrypted", kind: "boolean" },
|
|
1408
|
+
{ key: "IsAttachment", kind: "boolean" },
|
|
1409
|
+
{ key: "IsRbacEnabled", kind: "boolean" },
|
|
1410
|
+
{ key: "IsModelReserved", kind: "boolean" }
|
|
1411
|
+
];
|
|
1412
|
+
var SQL_TYPE_SCALARS = [
|
|
1413
|
+
{ key: "LengthLimit", kind: "integer", nullable: true },
|
|
1414
|
+
{ key: "DecimalPrecision", kind: "integer", nullable: true },
|
|
1415
|
+
{ key: "MaxValue", kind: "number", nullable: true },
|
|
1416
|
+
{ key: "MinValue", kind: "number", nullable: true }
|
|
1417
|
+
];
|
|
1418
|
+
function typeProblems(record, rules, prefix = "") {
|
|
1419
|
+
const values = record;
|
|
1420
|
+
return rules.filter(({ key, kind, nullable }) => {
|
|
1421
|
+
const value = values[key];
|
|
1422
|
+
if (value === undefined)
|
|
1423
|
+
return false;
|
|
1424
|
+
if (value === null)
|
|
1425
|
+
return !nullable;
|
|
1426
|
+
if (kind === "integer")
|
|
1427
|
+
return !Number.isInteger(value);
|
|
1428
|
+
return kind === "number" ? !(typeof value === "number" && Number.isFinite(value)) : typeof value !== kind;
|
|
1429
|
+
}).map(({ key, kind, nullable }) => `'${prefix}${key}' must be ${kind === "integer" ? "an" : "a"} ${kind}${nullable ? " or null" : ""}`);
|
|
1430
|
+
}
|
|
1431
|
+
function propertyTypeDiagnostic(subject, problem, fieldName) {
|
|
1432
|
+
return {
|
|
1433
|
+
code: DIAGNOSTIC_CODES.propertyTypeInvalid,
|
|
1434
|
+
message: `${subject}: ${problem}. The resource was edited by hand or is malformed.`,
|
|
1435
|
+
severity: "error",
|
|
1436
|
+
...fieldName !== undefined && { fieldName }
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
function fieldTypeDiagnostics(field) {
|
|
1440
|
+
const problems = typeProblems(field, FIELD_SCALARS);
|
|
1441
|
+
if (typeof field.SqlType === "object" && field.SqlType !== null) {
|
|
1442
|
+
problems.push(...typeProblems(field.SqlType, SQL_TYPE_SCALARS, "SqlType."));
|
|
1443
|
+
}
|
|
1444
|
+
const defaultValue = field.DefaultValue;
|
|
1445
|
+
const isYesNo = field.SqlType?.Name === SqlTypeName.BIT;
|
|
1446
|
+
if (defaultValue != null && typeof defaultValue !== "string" && !(isYesNo && typeof defaultValue === "boolean")) {
|
|
1447
|
+
problems.push(isYesNo ? "'DefaultValue' must be a boolean, a string or null" : "'DefaultValue' must be a string or null");
|
|
1448
|
+
}
|
|
1449
|
+
return problems.map((problem) => propertyTypeDiagnostic(`Field '${field.Name}'`, problem, field.Name));
|
|
1450
|
+
}
|
|
728
1451
|
|
|
729
1452
|
// src/resource/unified-resource-file.ts
|
|
730
1453
|
var ENTITY_RESOURCE_KIND = "entity";
|
|
@@ -732,8 +1455,9 @@ var ENTITY_RESOURCE_TYPE = "native";
|
|
|
732
1455
|
var ENTITY_RESOURCE_API_VERSION = "dataservice.uipath.com/v2";
|
|
733
1456
|
var ENTITY_RESOURCE_DOC_VERSION = "1.0.0";
|
|
734
1457
|
var SOLUTION_FOLDER = "solution_folder";
|
|
1458
|
+
var ENTITY_RESOURCE_DIR = `${ENTITY_RESOURCE_KIND}/${ENTITY_RESOURCE_TYPE}`;
|
|
735
1459
|
function entityResourcePath(entityName) {
|
|
736
|
-
return `resources/${SOLUTION_FOLDER}
|
|
1460
|
+
return `resources/${SOLUTION_FOLDER}/${ENTITY_RESOURCE_DIR}/${entityName}.json`;
|
|
737
1461
|
}
|
|
738
1462
|
|
|
739
1463
|
// src/resource/resource-io.ts
|
|
@@ -891,14 +1615,16 @@ function failure(code, message) {
|
|
|
891
1615
|
}
|
|
892
1616
|
async function findSolutionRoot(startDir, fs) {
|
|
893
1617
|
let dir = fs.path.resolve(startDir);
|
|
1618
|
+
let unreadable;
|
|
894
1619
|
for (;; ) {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
} catch {
|
|
899
|
-
entries = [];
|
|
1620
|
+
const [error, entries] = await catchError(fs.readdir(dir));
|
|
1621
|
+
if (error && isUnreadablePathError(error)) {
|
|
1622
|
+
unreadable ??= error;
|
|
900
1623
|
}
|
|
901
|
-
if (entries
|
|
1624
|
+
if (entries?.some((name) => name.endsWith(".uipx"))) {
|
|
1625
|
+
if (unreadable) {
|
|
1626
|
+
throw Object.assign(new Error(`Could not locate the solution from '${startDir}': ${unreadable.message}. A directory between here and the nearest .uipx cannot be read, and it may be the solution itself — fix read access and retry.`, { cause: unreadable }), { code: unreadable.code });
|
|
1627
|
+
}
|
|
902
1628
|
return dir;
|
|
903
1629
|
}
|
|
904
1630
|
const parent = fs.path.dirname(dir);
|
|
@@ -938,8 +1664,16 @@ class EntityProjectTool extends ProjectTool {
|
|
|
938
1664
|
message: `'${foreign}' is a Flow main file inside an Entity project — move it to a Flow project.`
|
|
939
1665
|
});
|
|
940
1666
|
}
|
|
941
|
-
const solutionDir = await findSolutionRoot(projectPath, fs);
|
|
942
|
-
if (
|
|
1667
|
+
const [rootError, solutionDir] = await catchError(findSolutionRoot(projectPath, fs));
|
|
1668
|
+
if (rootError) {
|
|
1669
|
+
if (stubs.length > 0) {
|
|
1670
|
+
diagnostics.push({
|
|
1671
|
+
file: projectPath,
|
|
1672
|
+
code: PACK_DIAGNOSTIC_CODES.solutionRootUnreadable,
|
|
1673
|
+
message: rootError.message
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
} else if (solutionDir === undefined) {
|
|
943
1677
|
if (stubs.length > 0) {
|
|
944
1678
|
diagnostics.push({
|
|
945
1679
|
file: projectPath,
|
|
@@ -995,51 +1729,57 @@ function compareCodeUnits(left, right) {
|
|
|
995
1729
|
}
|
|
996
1730
|
return left > right ? 1 : 0;
|
|
997
1731
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1732
|
+
// src/pack/entity-tool-factory.ts
|
|
1733
|
+
class EntityToolFactory {
|
|
1734
|
+
supportedTypes = ["Entity"];
|
|
1735
|
+
async createAsync(logger, fileSystem) {
|
|
1736
|
+
return new EntityProjectTool(fileSystem, logger);
|
|
1003
1737
|
}
|
|
1004
|
-
return siblings;
|
|
1005
1738
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1739
|
+
// src/resource/local-entities.ts
|
|
1740
|
+
async function readSolutionInlineEntities(fs, flowFilePath) {
|
|
1741
|
+
const found = new Map;
|
|
1742
|
+
const solutionDir = await findSolutionRoot(fs.path.dirname(fs.path.resolve(flowFilePath)), fs);
|
|
1743
|
+
if (solutionDir === undefined) {
|
|
1744
|
+
return found;
|
|
1745
|
+
}
|
|
1746
|
+
const dir = fs.path.join(solutionDir, "resources", SOLUTION_FOLDER, ...ENTITY_RESOURCE_DIR.split("/"));
|
|
1747
|
+
let files = [];
|
|
1009
1748
|
try {
|
|
1010
|
-
|
|
1749
|
+
files = await fs.readdir(dir);
|
|
1011
1750
|
} catch {
|
|
1012
|
-
return
|
|
1751
|
+
return found;
|
|
1013
1752
|
}
|
|
1014
|
-
for (const
|
|
1015
|
-
if (
|
|
1753
|
+
for (const file of files) {
|
|
1754
|
+
if (!file.endsWith(".json")) {
|
|
1016
1755
|
continue;
|
|
1017
1756
|
}
|
|
1018
|
-
const dir = fs.path.join(solutionDir, entry);
|
|
1019
1757
|
try {
|
|
1020
|
-
const
|
|
1021
|
-
if (
|
|
1758
|
+
const raw = await fs.readFile(fs.path.join(dir, file), "utf-8");
|
|
1759
|
+
if (raw === null) {
|
|
1022
1760
|
continue;
|
|
1023
1761
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1762
|
+
const parsed = JSON.parse(raw);
|
|
1763
|
+
const entity = unwrapResource(parsed);
|
|
1764
|
+
if (!isLocallyAuthored(entity)) {
|
|
1765
|
+
continue;
|
|
1028
1766
|
}
|
|
1767
|
+
const resourceKey = typeof parsed.resource?.key === "string" && parsed.resource.key !== "" ? parsed.resource.key : entity.Id;
|
|
1768
|
+
found.set(entity.Name.toLowerCase(), {
|
|
1769
|
+
name: entity.Name,
|
|
1770
|
+
resourceKey,
|
|
1771
|
+
folderId: entity.FolderId
|
|
1772
|
+
});
|
|
1029
1773
|
} catch {}
|
|
1030
1774
|
}
|
|
1031
|
-
return
|
|
1032
|
-
}
|
|
1033
|
-
// src/pack/entity-tool-factory.ts
|
|
1034
|
-
class EntityToolFactory {
|
|
1035
|
-
supportedTypes = ["Entity"];
|
|
1036
|
-
async createAsync(logger, fileSystem) {
|
|
1037
|
-
return new EntityProjectTool(fileSystem, logger);
|
|
1038
|
-
}
|
|
1775
|
+
return found;
|
|
1039
1776
|
}
|
|
1040
1777
|
export {
|
|
1778
|
+
AUTHORABLE_FIELD_TYPES,
|
|
1779
|
+
AuthoredFieldError,
|
|
1041
1780
|
DIAGNOSTIC_CODES,
|
|
1042
1781
|
ENTITY_RESOURCE_API_VERSION,
|
|
1782
|
+
ENTITY_RESOURCE_DIR,
|
|
1043
1783
|
ENTITY_RESOURCE_DOC_VERSION,
|
|
1044
1784
|
ENTITY_RESOURCE_KIND,
|
|
1045
1785
|
ENTITY_RESOURCE_TYPE,
|
|
@@ -1049,9 +1789,13 @@ export {
|
|
|
1049
1789
|
EntityToolFactory,
|
|
1050
1790
|
SOLUTION_FOLDER,
|
|
1051
1791
|
SYSTEM_FIELD_TEMPLATES,
|
|
1792
|
+
UNASSIGNED_FOLDER_ID,
|
|
1793
|
+
authorField,
|
|
1052
1794
|
createEntitySkeleton,
|
|
1053
1795
|
entityResourcePath,
|
|
1054
1796
|
findSolutionRoot,
|
|
1797
|
+
isLocallyAuthored,
|
|
1798
|
+
readSolutionInlineEntities,
|
|
1055
1799
|
serialize,
|
|
1056
1800
|
serializeEntityJson,
|
|
1057
1801
|
unwrapResource,
|
|
@@ -1061,4 +1805,4 @@ export {
|
|
|
1061
1805
|
wrapEntityJson
|
|
1062
1806
|
};
|
|
1063
1807
|
|
|
1064
|
-
//# debugId=
|
|
1808
|
+
//# debugId=B83BCECF16611A3364756E2164756E21
|