@uipath/data-fabric-tool 1.199.0 → 1.201.0-preview.115
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/browser-strategy-yccf8mtd.js +99 -0
- package/dist/getMachineId-bsd-wfkxpxjv.js +38 -0
- package/dist/getMachineId-darwin-9asn4zy6.js +38 -0
- package/dist/getMachineId-linux-62t6m027.js +31 -0
- package/dist/getMachineId-unsupported-dfrzeqc3.js +21 -0
- package/dist/getMachineId-win-zgvrp5q3.js +40 -0
- package/dist/index-2fj08e7n.js +2058 -0
- package/dist/index-w03qc9m8.js +634 -0
- package/dist/index.js +14 -2148
- package/dist/js-yaml-4ypbq2tt.js +3145 -0
- package/dist/node-strategy-12qfy0nv.js +348 -0
- package/dist/tool-0v6na3yp.js +37 -0
- package/dist/tool-5arsyj36.js +11 -0
- package/dist/tool-7eva0peq.js +265 -0
- package/dist/tool-9qecd4wb.js +14 -0
- package/dist/tool-cyfkvxhw.js +23350 -0
- package/dist/tool-h1k9mjs9.js +17 -0
- package/dist/tool-r6rhp5ep.js +1487 -0
- package/dist/tool.js +10 -48431
- package/package.json +2 -2
- package/src/commands/choice-sets.spec.ts +44 -0
- package/src/commands/choice-sets.ts +39 -2
- package/src/commands/entities.spec.ts +70 -8
- package/src/commands/entities.ts +40 -17
- package/src/commands/records.spec.ts +29 -0
- package/src/commands/records.ts +12 -1
- package/src/utils/validate.spec.ts +279 -12
- package/src/utils/validate.ts +694 -40
- package/tests/entities-lifecycle.e2e.test.ts +9 -8
- package/tests/performance.e2e.test.ts +32 -0
|
@@ -2,14 +2,20 @@ import { describe, expect, it } from "vitest";
|
|
|
2
2
|
import {
|
|
3
3
|
findFilePayloadKeys,
|
|
4
4
|
findInvalidFieldConstraints,
|
|
5
|
+
findInvalidFieldMetadata,
|
|
5
6
|
findInvalidFieldName,
|
|
6
7
|
findIsUniqueInUpdateFields,
|
|
7
8
|
findMissingComplexFieldExtras,
|
|
9
|
+
findReferenceFieldsOnFile,
|
|
8
10
|
findReferenceFolderKeyOnChoiceSet,
|
|
11
|
+
findTooManyMultilineMaxFields,
|
|
9
12
|
findUiBrokenFieldType,
|
|
13
|
+
validateChoiceValueDisplayName,
|
|
10
14
|
validateChoiceValueName,
|
|
11
15
|
validateName,
|
|
16
|
+
validateQueryAggregates,
|
|
12
17
|
validateQueryFilter,
|
|
18
|
+
validateSchemaMetadata,
|
|
13
19
|
} from "./validate";
|
|
14
20
|
|
|
15
21
|
describe("validateName", () => {
|
|
@@ -17,10 +23,16 @@ describe("validateName", () => {
|
|
|
17
23
|
expect(validateName("total", "field")).toBeNull();
|
|
18
24
|
});
|
|
19
25
|
|
|
20
|
-
it("accepts
|
|
26
|
+
it("accepts underscores in entity names", () => {
|
|
21
27
|
expect(validateName("Order_2024_v1", "entity")).toBeNull();
|
|
22
28
|
});
|
|
23
29
|
|
|
30
|
+
it("rejects underscores in field names", () => {
|
|
31
|
+
const err = validateName("order_total", "field");
|
|
32
|
+
expect(err?.message).toContain("Invalid field name");
|
|
33
|
+
expect(err?.instructions).toContain("no underscores");
|
|
34
|
+
});
|
|
35
|
+
|
|
24
36
|
it("rejects a name starting with a digit", () => {
|
|
25
37
|
const err = validateName("1Order", "entity");
|
|
26
38
|
expect(err).not.toBeNull();
|
|
@@ -41,6 +53,19 @@ describe("validateName", () => {
|
|
|
41
53
|
expect(err?.message).toContain("reserved");
|
|
42
54
|
});
|
|
43
55
|
|
|
56
|
+
it("rejects every system field name case-insensitively", () => {
|
|
57
|
+
for (const name of [
|
|
58
|
+
"id",
|
|
59
|
+
"CREATEDBY",
|
|
60
|
+
"createTime",
|
|
61
|
+
"UpdatedBy",
|
|
62
|
+
"updatetime",
|
|
63
|
+
"RecordOwner",
|
|
64
|
+
]) {
|
|
65
|
+
expect(validateName(name, "field")?.message).toContain("reserved");
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
44
69
|
it("does not treat 'CreateTime' as reserved for an entity name", () => {
|
|
45
70
|
// The reserved-field-name list is field-specific; entity names go
|
|
46
71
|
// through the keyword check only.
|
|
@@ -55,6 +80,31 @@ describe("validateName", () => {
|
|
|
55
80
|
}
|
|
56
81
|
});
|
|
57
82
|
|
|
83
|
+
it("rejects confirmed SQL keywords for entity names only", () => {
|
|
84
|
+
for (const name of ["Order", "order", "Group", "GROUP"]) {
|
|
85
|
+
expect(validateName(name, "entity")?.message).toContain(
|
|
86
|
+
"reserved SQL keyword",
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("accepts SQL keywords as field names — server only blocks them on entity create", () => {
|
|
92
|
+
for (const name of ["Order", "order", "Group", "GROUP"]) {
|
|
93
|
+
expect(validateName(name, "field")).toBeNull();
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("accepts SQL-like names the platform allows", () => {
|
|
98
|
+
for (const name of ["Status", "Key", "Type", "OrderStatus"]) {
|
|
99
|
+
expect(validateName(name, "field")).toBeNull();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("does not apply entity and field SQL rules to choice-set names", () => {
|
|
104
|
+
expect(validateName("Order", "choice set")).toBeNull();
|
|
105
|
+
expect(validateName("Group", "choice set")).toBeNull();
|
|
106
|
+
});
|
|
107
|
+
|
|
58
108
|
it("labels the message with the kind", () => {
|
|
59
109
|
expect(validateName("Class", "entity")?.message).toContain("Entity");
|
|
60
110
|
expect(validateName("Class", "field")?.message).toContain("Field");
|
|
@@ -92,6 +142,51 @@ describe("findInvalidFieldName", () => {
|
|
|
92
142
|
});
|
|
93
143
|
});
|
|
94
144
|
|
|
145
|
+
describe("schema metadata validation", () => {
|
|
146
|
+
it("enforces fixed entity metadata limits", () => {
|
|
147
|
+
expect(
|
|
148
|
+
validateSchemaMetadata({ displayName: "x".repeat(129) }, "Entity")
|
|
149
|
+
?.message,
|
|
150
|
+
).toContain("128");
|
|
151
|
+
expect(
|
|
152
|
+
validateSchemaMetadata({ description: "x".repeat(513) }, "Entity")
|
|
153
|
+
?.message,
|
|
154
|
+
).toContain("512");
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("rejects case-insensitive field name and display-name collisions", () => {
|
|
158
|
+
expect(
|
|
159
|
+
findInvalidFieldMetadata([
|
|
160
|
+
{ fieldName: "Amount" },
|
|
161
|
+
{ fieldName: "amount" },
|
|
162
|
+
])?.message,
|
|
163
|
+
).toContain("Duplicate field name");
|
|
164
|
+
expect(
|
|
165
|
+
findInvalidFieldMetadata([
|
|
166
|
+
{ fieldName: "Amount", displayName: "Total" },
|
|
167
|
+
{ fieldName: "Price", displayName: "total" },
|
|
168
|
+
])?.message,
|
|
169
|
+
).toContain("Duplicate field display name");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("rejects a field name matching its entity name", () => {
|
|
173
|
+
expect(
|
|
174
|
+
findInvalidFieldMetadata([{ fieldName: "invoice" }], "Invoice")
|
|
175
|
+
?.message,
|
|
176
|
+
).toContain("cannot match entity name");
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("rejects more than ten MULTILINE_MAX fields", () => {
|
|
180
|
+
const fields = Array.from({ length: 11 }, (_, i) => ({
|
|
181
|
+
fieldName: `Body${i}`,
|
|
182
|
+
type: "MULTILINE_MAX",
|
|
183
|
+
}));
|
|
184
|
+
expect(findTooManyMultilineMaxFields(fields)?.message).toContain(
|
|
185
|
+
"maximum is 10",
|
|
186
|
+
);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
95
190
|
describe("findUiBrokenFieldType", () => {
|
|
96
191
|
it("returns null for UI-compatible types", () => {
|
|
97
192
|
expect(
|
|
@@ -136,8 +231,15 @@ describe("findUiBrokenFieldType", () => {
|
|
|
136
231
|
});
|
|
137
232
|
|
|
138
233
|
describe("validateChoiceValueName", () => {
|
|
139
|
-
it("accepts
|
|
140
|
-
expect(validateChoiceValueName("
|
|
234
|
+
it("accepts one-character and alphanumeric names", () => {
|
|
235
|
+
expect(validateChoiceValueName("A")).toBeNull();
|
|
236
|
+
expect(validateChoiceValueName("internalAudit2")).toBeNull();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it("rejects underscores", () => {
|
|
240
|
+
expect(validateChoiceValueName("internal_audit")?.message).toContain(
|
|
241
|
+
"Invalid",
|
|
242
|
+
);
|
|
141
243
|
});
|
|
142
244
|
|
|
143
245
|
it("accepts a capitalized keyword — the validator is case-sensitive", () => {
|
|
@@ -166,6 +268,12 @@ describe("validateChoiceValueName", () => {
|
|
|
166
268
|
const err = validateChoiceValueName("internal");
|
|
167
269
|
expect(err?.instructions).toContain("--display-name");
|
|
168
270
|
});
|
|
271
|
+
|
|
272
|
+
it("enforces the 500-character display-name limit", () => {
|
|
273
|
+
expect(
|
|
274
|
+
validateChoiceValueDisplayName("x".repeat(501))?.message,
|
|
275
|
+
).toContain("500");
|
|
276
|
+
});
|
|
169
277
|
});
|
|
170
278
|
|
|
171
279
|
describe("validateQueryFilter", () => {
|
|
@@ -216,6 +324,15 @@ describe("validateQueryFilter", () => {
|
|
|
216
324
|
expect(err?.message).toContain("requires 'valueList'");
|
|
217
325
|
});
|
|
218
326
|
|
|
327
|
+
it("rejects an empty valueList", () => {
|
|
328
|
+
const err = validateQueryFilter({
|
|
329
|
+
queryFilters: [
|
|
330
|
+
{ fieldName: "Status", operator: "in", valueList: [] },
|
|
331
|
+
],
|
|
332
|
+
});
|
|
333
|
+
expect(err?.message).toContain("non-empty");
|
|
334
|
+
});
|
|
335
|
+
|
|
219
336
|
it("requires value on operators other than in / not in", () => {
|
|
220
337
|
const err = validateQueryFilter({
|
|
221
338
|
queryFilters: [{ fieldName: "Status", operator: "=" }],
|
|
@@ -233,6 +350,22 @@ describe("validateQueryFilter", () => {
|
|
|
233
350
|
).toBeNull();
|
|
234
351
|
});
|
|
235
352
|
|
|
353
|
+
it("rejects null with operators other than = and !=", () => {
|
|
354
|
+
const err = validateQueryFilter({
|
|
355
|
+
queryFilters: [{ fieldName: "Score", operator: ">", value: null }],
|
|
356
|
+
});
|
|
357
|
+
expect(err?.message).toContain("cannot use a null value");
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it("rejects invalid filter field paths", () => {
|
|
361
|
+
const err = validateQueryFilter({
|
|
362
|
+
queryFilters: [
|
|
363
|
+
{ fieldName: "bad-field", operator: "=", value: "x" },
|
|
364
|
+
],
|
|
365
|
+
});
|
|
366
|
+
expect(err?.message).toContain("fieldName");
|
|
367
|
+
});
|
|
368
|
+
|
|
236
369
|
it("recurses into nested filterGroups", () => {
|
|
237
370
|
const err = validateQueryFilter({
|
|
238
371
|
queryFilters: [{ fieldName: "x", operator: "=", value: "y" }],
|
|
@@ -263,6 +396,76 @@ describe("validateQueryFilter", () => {
|
|
|
263
396
|
});
|
|
264
397
|
});
|
|
265
398
|
|
|
399
|
+
describe("validateQueryAggregates", () => {
|
|
400
|
+
it("accepts a valid grouped aggregate", () => {
|
|
401
|
+
expect(
|
|
402
|
+
validateQueryAggregates({
|
|
403
|
+
selectedFields: ["Status"],
|
|
404
|
+
groupBy: ["Status"],
|
|
405
|
+
aggregates: [
|
|
406
|
+
{ function: "COUNT", field: "Id", alias: "total" },
|
|
407
|
+
],
|
|
408
|
+
}),
|
|
409
|
+
).toBeNull();
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it("enforces aggregate and groupBy count limits", () => {
|
|
413
|
+
expect(
|
|
414
|
+
validateQueryAggregates({
|
|
415
|
+
aggregates: Array.from({ length: 6 }, (_, i) => ({
|
|
416
|
+
function: "COUNT",
|
|
417
|
+
field: `Field${i}`,
|
|
418
|
+
})),
|
|
419
|
+
})?.message,
|
|
420
|
+
).toContain("at most 5");
|
|
421
|
+
expect(
|
|
422
|
+
validateQueryAggregates({
|
|
423
|
+
aggregates: [{ function: "COUNT", field: "Id" }],
|
|
424
|
+
groupBy: ["A", "B", "C", "D", "E", "F"],
|
|
425
|
+
})?.message,
|
|
426
|
+
).toContain("groupBy");
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it("rejects invalid functions, aliases, and duplicate aliases", () => {
|
|
430
|
+
expect(
|
|
431
|
+
validateQueryAggregates({
|
|
432
|
+
aggregates: [{ function: "MEDIAN", field: "Score" }],
|
|
433
|
+
})?.message,
|
|
434
|
+
).toContain("invalid function");
|
|
435
|
+
expect(
|
|
436
|
+
validateQueryAggregates({
|
|
437
|
+
aggregates: [
|
|
438
|
+
{ function: "COUNT", field: "Id", alias: "bad]alias" },
|
|
439
|
+
],
|
|
440
|
+
})?.message,
|
|
441
|
+
).toContain("Invalid aggregate alias");
|
|
442
|
+
expect(
|
|
443
|
+
validateQueryAggregates({
|
|
444
|
+
aggregates: [
|
|
445
|
+
{ function: "COUNT", field: "Id", alias: "total" },
|
|
446
|
+
{ function: "SUM", field: "Score", alias: "TOTAL" },
|
|
447
|
+
],
|
|
448
|
+
})?.message,
|
|
449
|
+
).toContain("Duplicate aggregate alias");
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
it("requires selected fields to be grouped", () => {
|
|
453
|
+
expect(
|
|
454
|
+
validateQueryAggregates({
|
|
455
|
+
selectedFields: ["Status"],
|
|
456
|
+
aggregates: [{ function: "COUNT", field: "Id" }],
|
|
457
|
+
})?.message,
|
|
458
|
+
).toContain("'groupBy' is required");
|
|
459
|
+
expect(
|
|
460
|
+
validateQueryAggregates({
|
|
461
|
+
selectedFields: ["Status", "Region"],
|
|
462
|
+
groupBy: ["Status"],
|
|
463
|
+
aggregates: [{ function: "COUNT", field: "Id" }],
|
|
464
|
+
})?.message,
|
|
465
|
+
).toContain("Region");
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
|
|
266
469
|
describe("findReferenceFolderKeyOnChoiceSet", () => {
|
|
267
470
|
it("returns null when CHOICE_SET_* fields omit referenceFolderKey", () => {
|
|
268
471
|
expect(
|
|
@@ -281,7 +484,7 @@ describe("findReferenceFolderKeyOnChoiceSet", () => {
|
|
|
281
484
|
).toBeNull();
|
|
282
485
|
});
|
|
283
486
|
|
|
284
|
-
it("ignores referenceFolderKey on RELATIONSHIP
|
|
487
|
+
it("ignores referenceFolderKey on RELATIONSHIP", () => {
|
|
285
488
|
expect(
|
|
286
489
|
findReferenceFolderKeyOnChoiceSet([
|
|
287
490
|
{
|
|
@@ -291,11 +494,6 @@ describe("findReferenceFolderKeyOnChoiceSet", () => {
|
|
|
291
494
|
referenceFieldId: "f-1",
|
|
292
495
|
referenceFolderKey: "folder-1",
|
|
293
496
|
},
|
|
294
|
-
{
|
|
295
|
-
fieldName: "receipt",
|
|
296
|
-
type: "FILE",
|
|
297
|
-
referenceFolderKey: "folder-1",
|
|
298
|
-
},
|
|
299
497
|
]),
|
|
300
498
|
).toBeNull();
|
|
301
499
|
});
|
|
@@ -326,6 +524,48 @@ describe("findReferenceFolderKeyOnChoiceSet", () => {
|
|
|
326
524
|
});
|
|
327
525
|
});
|
|
328
526
|
|
|
527
|
+
describe("findReferenceFieldsOnFile", () => {
|
|
528
|
+
it("accepts a FILE field without reference metadata", () => {
|
|
529
|
+
expect(
|
|
530
|
+
findReferenceFieldsOnFile([{ fieldName: "receipt", type: "FILE" }]),
|
|
531
|
+
).toBeNull();
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
it("rejects reference metadata on FILE fields", () => {
|
|
535
|
+
for (const key of [
|
|
536
|
+
"referenceFolderKey",
|
|
537
|
+
"referenceEntityId",
|
|
538
|
+
"referenceFieldId",
|
|
539
|
+
"choiceSetId",
|
|
540
|
+
]) {
|
|
541
|
+
const err = findReferenceFieldsOnFile([
|
|
542
|
+
{
|
|
543
|
+
fieldName: "receipt",
|
|
544
|
+
type: "FILE",
|
|
545
|
+
[key]: "value",
|
|
546
|
+
},
|
|
547
|
+
]);
|
|
548
|
+
expect(err, `${key} should be rejected`).not.toBeNull();
|
|
549
|
+
expect(err?.message).toContain("FILE field 'receipt'");
|
|
550
|
+
expect(err?.instructions).toContain(`'${key}'`);
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
it("ignores reference metadata on non-FILE fields", () => {
|
|
555
|
+
expect(
|
|
556
|
+
findReferenceFieldsOnFile([
|
|
557
|
+
{
|
|
558
|
+
fieldName: "customer",
|
|
559
|
+
type: "RELATIONSHIP",
|
|
560
|
+
referenceEntityId: "entity-id",
|
|
561
|
+
referenceFieldId: "field-id",
|
|
562
|
+
referenceFolderKey: "folder-id",
|
|
563
|
+
},
|
|
564
|
+
]),
|
|
565
|
+
).toBeNull();
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
|
|
329
569
|
describe("findMissingComplexFieldExtras", () => {
|
|
330
570
|
it("returns null when complex fields carry their extras", () => {
|
|
331
571
|
expect(
|
|
@@ -456,16 +696,43 @@ describe("findInvalidFieldConstraints", () => {
|
|
|
456
696
|
expect(err?.message).toContain("does not accept 'maxValue'");
|
|
457
697
|
});
|
|
458
698
|
|
|
459
|
-
it("rejects minValue
|
|
699
|
+
it("allows equal numeric bounds and rejects minValue > maxValue", () => {
|
|
700
|
+
expect(
|
|
701
|
+
findInvalidFieldConstraints([
|
|
702
|
+
{
|
|
703
|
+
fieldName: "fixed",
|
|
704
|
+
type: "DECIMAL",
|
|
705
|
+
minValue: 100,
|
|
706
|
+
maxValue: 100,
|
|
707
|
+
},
|
|
708
|
+
]),
|
|
709
|
+
).toBeNull();
|
|
460
710
|
const err = findInvalidFieldConstraints([
|
|
461
711
|
{
|
|
462
712
|
fieldName: "price",
|
|
463
713
|
type: "DECIMAL",
|
|
464
|
-
minValue:
|
|
714
|
+
minValue: 101,
|
|
465
715
|
maxValue: 100,
|
|
466
716
|
},
|
|
467
717
|
]);
|
|
468
|
-
expect(err?.message).toContain("must
|
|
718
|
+
expect(err?.message).toContain("must not exceed");
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
it("rejects fractional length limits and out-of-range numeric bounds", () => {
|
|
722
|
+
expect(
|
|
723
|
+
findInvalidFieldConstraints([
|
|
724
|
+
{ fieldName: "title", type: "STRING", lengthLimit: 1.5 },
|
|
725
|
+
])?.message,
|
|
726
|
+
).toContain("integer");
|
|
727
|
+
expect(
|
|
728
|
+
findInvalidFieldConstraints([
|
|
729
|
+
{
|
|
730
|
+
fieldName: "amount",
|
|
731
|
+
type: "DECIMAL",
|
|
732
|
+
maxValue: 9_007_199_254_740_992,
|
|
733
|
+
},
|
|
734
|
+
])?.message,
|
|
735
|
+
).toContain("supported numeric range");
|
|
469
736
|
});
|
|
470
737
|
|
|
471
738
|
it("rejects decimalPrecision outside 0-10", () => {
|