@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/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 NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9]{2,99}$/;
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 (!NAME_PATTERN.test(entity.Name)) {
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: `Entity name '${entity.Name}' must start with a letter and contain 3-100 letters or digits.`,
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 (!field.IsSystemField && !NAME_PATTERN.test(field.Name)) {
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: `Field name '${field.Name}' must start with a letter and contain 3-100 letters or digits.`,
1285
+ message: `${fieldNameFormat.message}. ${fieldNameFormat.instructions}`,
641
1286
  severity: "error",
642
1287
  fieldName: field.Name
643
1288
  });
644
1289
  }
645
- if (!field.IsSystemField) {
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 (!field.IsSystemField && !ALLOWED_TYPE_PAIRS.has(`${field.FieldDisplayType}:${field.SqlType.Name}`)) {
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.Name}).`,
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
- diagnostics.push(...validateSystemFields(entity));
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 = entity.Fields.find((field) => field.Name === template.Name);
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
- // src/pack/constants.ts
722
- var ENTITY_EXTENSION_CONST = ".entity";
723
- var ENTITY_VALIDATION_FAILED = "ENTITY_VALIDATION_FAILED";
724
- var PACK_DIAGNOSTIC_CODES = {
725
- misplacedMainFile: "MISPLACED_MAIN_FILE",
726
- noParentSolution: "NO_PARENT_SOLUTION"
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}/entity/native/${entityName}.json`;
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
- let entries = [];
896
- try {
897
- entries = await fs.readdir(dir);
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.some((name) => name.endsWith(".uipx"))) {
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 (solutionDir === undefined) {
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
- function withoutOneOccurrence(names, name) {
999
- const siblings = [...names];
1000
- const self = siblings.indexOf(name);
1001
- if (self >= 0) {
1002
- siblings.splice(self, 1);
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
- async function collectSolutionEntityNames(solutionDir, fs) {
1007
- const names = [];
1008
- let topLevel = [];
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
- topLevel = await fs.readdir(solutionDir);
1749
+ files = await fs.readdir(dir);
1011
1750
  } catch {
1012
- return names;
1751
+ return found;
1013
1752
  }
1014
- for (const entry of topLevel) {
1015
- if (entry === "resources" || entry.startsWith(".")) {
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 stat = await fs.stat(dir);
1021
- if (!stat?.isDirectory()) {
1758
+ const raw = await fs.readFile(fs.path.join(dir, file), "utf-8");
1759
+ if (raw === null) {
1022
1760
  continue;
1023
1761
  }
1024
- for (const file of await fs.readdir(dir)) {
1025
- if (file.endsWith(ENTITY_EXTENSION_CONST)) {
1026
- names.push(fs.path.basename(file, ENTITY_EXTENSION_CONST));
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 names;
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=6EFF0E08D007F24864756E2164756E21
1808
+ //# debugId=B83BCECF16611A3364756E2164756E21