@uipath/common 1.202.1-preview.220 → 1.202.1-preview.239
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/formatter.d.ts +15 -0
- package/dist/index.js +225 -7
- package/package.json +2 -2
package/dist/formatter.d.ts
CHANGED
|
@@ -102,6 +102,13 @@ export declare class SuccessOutput {
|
|
|
102
102
|
Data: DataRecord | DataRecord[];
|
|
103
103
|
Pagination?: Pagination;
|
|
104
104
|
Instructions?: string;
|
|
105
|
+
/**
|
|
106
|
+
* A note for the caller that does not change the `Data` contract — e.g.
|
|
107
|
+
* why `--output-filter` returned nothing. Declared here because agents
|
|
108
|
+
* read the envelope and nothing else; `emitList` and the filter paths
|
|
109
|
+
* both set it.
|
|
110
|
+
*/
|
|
111
|
+
Warning?: string;
|
|
105
112
|
Log?: string;
|
|
106
113
|
constructor(code: string, data: DataRecord | DataRecord[]);
|
|
107
114
|
}
|
|
@@ -303,6 +310,9 @@ export declare namespace OutputFormatter {
|
|
|
303
310
|
*
|
|
304
311
|
* **Side-effect:** records the exit code through {@link setExitCode}, so a
|
|
305
312
|
* printed failure exits non-zero even when no `context.exit()` follows.
|
|
313
|
+
*
|
|
314
|
+
* `--output-filter` projects `Data` here as it does in {@link success};
|
|
315
|
+
* see {@link filterFailureData}.
|
|
306
316
|
*/
|
|
307
317
|
function error(data: FailureOutput): void;
|
|
308
318
|
/** Emit a list result. Always uses `Result: "Success"` — an empty list is not an error. */
|
|
@@ -319,6 +329,11 @@ export declare namespace OutputFormatter {
|
|
|
319
329
|
/**
|
|
320
330
|
* Format structured output to a string without writing to console.
|
|
321
331
|
* Useful when the caller needs the formatted string (e.g., Commander's formatHelp).
|
|
332
|
+
*
|
|
333
|
+
* This is the structured-help path, so it carries the filter note on the
|
|
334
|
+
* envelope like {@link success} does: a mistyped filter against `--help`
|
|
335
|
+
* is the same ambiguity as one against a list, and stdout is the only
|
|
336
|
+
* channel its reader has.
|
|
322
337
|
*/
|
|
323
338
|
function formatToString(data: StructuredOutput): string;
|
|
324
339
|
}
|
package/dist/index.js
CHANGED
|
@@ -10871,6 +10871,7 @@ class SuccessOutput {
|
|
|
10871
10871
|
Data;
|
|
10872
10872
|
Pagination;
|
|
10873
10873
|
Instructions;
|
|
10874
|
+
Warning;
|
|
10874
10875
|
Log;
|
|
10875
10876
|
constructor(code, data) {
|
|
10876
10877
|
this.Code = code;
|
|
@@ -11287,7 +11288,165 @@ class ConfigurationError extends Error {
|
|
|
11287
11288
|
function isConfigurationError(error) {
|
|
11288
11289
|
return typeof error === "object" && error !== null && "__brand" in error && error.__brand === "ConfigurationError";
|
|
11289
11290
|
}
|
|
11290
|
-
function
|
|
11291
|
+
function countRecords(data) {
|
|
11292
|
+
if (Array.isArray(data))
|
|
11293
|
+
return data.length;
|
|
11294
|
+
return data == null ? 0 : 1;
|
|
11295
|
+
}
|
|
11296
|
+
function availableFields(data) {
|
|
11297
|
+
const records = Array.isArray(data) ? data : [data];
|
|
11298
|
+
const keys = new Set;
|
|
11299
|
+
for (const record of records) {
|
|
11300
|
+
if (record && typeof record === "object" && !Array.isArray(record)) {
|
|
11301
|
+
for (const key of Object.keys(record))
|
|
11302
|
+
keys.add(key);
|
|
11303
|
+
}
|
|
11304
|
+
}
|
|
11305
|
+
return [...keys];
|
|
11306
|
+
}
|
|
11307
|
+
function decodeQuotedIdentifier(whole, inner) {
|
|
11308
|
+
const [error, decoded] = catchError(() => JSON.parse(whole));
|
|
11309
|
+
if (!error && typeof decoded === "string")
|
|
11310
|
+
return decoded;
|
|
11311
|
+
return inner.replace(/\\(.)/g, "$1");
|
|
11312
|
+
}
|
|
11313
|
+
function referencedFields(filter) {
|
|
11314
|
+
const top = new Set;
|
|
11315
|
+
const nested = new Set;
|
|
11316
|
+
const withoutValueLiterals = filter.replace(/'(?:\\.|[^'\\])*'/g, " ").replace(/`(?:\\.|[^`\\])*`/g, " ");
|
|
11317
|
+
const isPathTail = (text, index) => text[index - 1] === "." && /[A-Za-z0-9_"]/.test(text[index - 2] ?? "");
|
|
11318
|
+
const quoted = [];
|
|
11319
|
+
const withoutLiterals = withoutValueLiterals.replace(/"((?:\\.|[^"\\])*)"/g, (whole, name, index) => {
|
|
11320
|
+
const isAlias = /^\s*:/.test(withoutValueLiterals.slice(index + whole.length));
|
|
11321
|
+
if (!isAlias) {
|
|
11322
|
+
quoted.push({
|
|
11323
|
+
name: decodeQuotedIdentifier(whole, name),
|
|
11324
|
+
index,
|
|
11325
|
+
tail: isPathTail(withoutValueLiterals, index)
|
|
11326
|
+
});
|
|
11327
|
+
}
|
|
11328
|
+
return `"${" ".repeat(whole.length - 2)}"`;
|
|
11329
|
+
});
|
|
11330
|
+
const descent = /[A-Za-z0-9_"]\s*[.[]/.exec(withoutLiterals);
|
|
11331
|
+
const rootEnd = descent ? descent.index + 1 : Number.POSITIVE_INFINITY;
|
|
11332
|
+
const place = (name, index, tail) => {
|
|
11333
|
+
if (tail || index >= rootEnd)
|
|
11334
|
+
nested.add(name);
|
|
11335
|
+
else
|
|
11336
|
+
top.add(name);
|
|
11337
|
+
};
|
|
11338
|
+
for (const entry of quoted)
|
|
11339
|
+
place(entry.name, entry.index, entry.tail);
|
|
11340
|
+
const identifiers = withoutLiterals.matchAll(/([A-Za-z_][A-Za-z0-9_]*)(\s*[:(])?/g);
|
|
11341
|
+
const reserved = new Set(["true", "false", "null", "and", "or", "not"]);
|
|
11342
|
+
for (const match of identifiers) {
|
|
11343
|
+
const [, name, trailing] = match;
|
|
11344
|
+
if (trailing || reserved.has(name))
|
|
11345
|
+
continue;
|
|
11346
|
+
place(name, match.index, isPathTail(withoutLiterals, match.index));
|
|
11347
|
+
}
|
|
11348
|
+
return {
|
|
11349
|
+
top: [...top],
|
|
11350
|
+
nested: [...nested].filter((name) => !top.has(name)),
|
|
11351
|
+
hasPredicate: /\[\s*\?/.test(withoutValueLiterals)
|
|
11352
|
+
};
|
|
11353
|
+
}
|
|
11354
|
+
function appearsBelowTopLevel(data, name) {
|
|
11355
|
+
let budget = 2000;
|
|
11356
|
+
const visit = (value, depth) => {
|
|
11357
|
+
if (budget-- <= 0 || depth > 4)
|
|
11358
|
+
return false;
|
|
11359
|
+
if (value === null || typeof value !== "object")
|
|
11360
|
+
return false;
|
|
11361
|
+
if (Array.isArray(value))
|
|
11362
|
+
return value.some((entry) => visit(entry, depth));
|
|
11363
|
+
const record = value;
|
|
11364
|
+
if (depth > 0 && Object.hasOwn(record, name))
|
|
11365
|
+
return true;
|
|
11366
|
+
return Object.values(record).some((entry) => visit(entry, depth + 1));
|
|
11367
|
+
};
|
|
11368
|
+
return visit(data, 0);
|
|
11369
|
+
}
|
|
11370
|
+
function alwaysNullKeys(records) {
|
|
11371
|
+
const objects = records.filter((r) => r != null && typeof r === "object" && !Array.isArray(r));
|
|
11372
|
+
if (objects.length === 0 || objects.length !== records.length)
|
|
11373
|
+
return [];
|
|
11374
|
+
const keys = [...new Set(objects.flatMap((o) => Object.keys(o)))];
|
|
11375
|
+
if (keys.length === 0)
|
|
11376
|
+
return [];
|
|
11377
|
+
const nullKeys = keys.filter((key) => objects.every((record) => record[key] === null));
|
|
11378
|
+
return nullKeys.length === keys.length ? nullKeys : [];
|
|
11379
|
+
}
|
|
11380
|
+
function carriesOnlyNulls(value) {
|
|
11381
|
+
if (value === null)
|
|
11382
|
+
return true;
|
|
11383
|
+
if (Array.isArray(value)) {
|
|
11384
|
+
return value.length > 0 && value.every(carriesOnlyNulls);
|
|
11385
|
+
}
|
|
11386
|
+
if (typeof value === "object" && value !== undefined) {
|
|
11387
|
+
const values = Object.values(value);
|
|
11388
|
+
return values.length > 0 && values.every(carriesOnlyNulls);
|
|
11389
|
+
}
|
|
11390
|
+
return false;
|
|
11391
|
+
}
|
|
11392
|
+
function nameList(names, cap2 = 12) {
|
|
11393
|
+
const shown = names.slice(0, cap2).map((n) => `\`${n}\``);
|
|
11394
|
+
const rest = names.length - shown.length;
|
|
11395
|
+
return shown.join(", ") + (rest > 0 ? `, and ${rest} more` : "");
|
|
11396
|
+
}
|
|
11397
|
+
function buildFilterWarning(filter, data, outcome) {
|
|
11398
|
+
const present = availableFields(data);
|
|
11399
|
+
const refs = referencedFields(filter);
|
|
11400
|
+
const unknown = refs.top.filter((name) => !present.includes(name) && !appearsBelowTopLevel(data, name));
|
|
11401
|
+
const unchecked = refs.nested.filter((name) => !present.includes(name));
|
|
11402
|
+
const count = countRecords(data);
|
|
11403
|
+
const scope = `${count} record(s)`;
|
|
11404
|
+
const isNotAField = (names) => `${nameList(names)} ${names.length === 1 ? "is not a field" : "are not fields"} on the ${scope} it read`;
|
|
11405
|
+
const soundness = unchecked.length > 0 ? `${nameList(unchecked)} ${unchecked.length === 1 ? "reads" : "read"} below the top level, so ${unchecked.length === 1 ? "it was" : "they were"} not checked against the record keys` : refs.top.length > 0 ? "every field it names exists" : "";
|
|
11406
|
+
const withSoundness = (base) => soundness ? `${base}, and ${soundness}` : base;
|
|
11407
|
+
let detail;
|
|
11408
|
+
let lede;
|
|
11409
|
+
if (outcome.kind === "null-elements") {
|
|
11410
|
+
lede = "returned only null values";
|
|
11411
|
+
const projected = `all ${outcome.count} of the elements it projected are null`;
|
|
11412
|
+
if (unknown.length > 0) {
|
|
11413
|
+
detail = `${projected}, because ${isNotAField(unknown)}`;
|
|
11414
|
+
} else if (unchecked.length > 0) {
|
|
11415
|
+
detail = withSoundness(projected);
|
|
11416
|
+
} else {
|
|
11417
|
+
detail = `${projected}, and every field it names exists — a multi-select list ` + `(\`[A, B]\`) reads each entry against \`Data\` itself, so on a list ` + `result use \`[].[A, B]\` or \`[].{a: A, b: B}\` to read the records`;
|
|
11418
|
+
}
|
|
11419
|
+
} else if (outcome.kind === "null-rows") {
|
|
11420
|
+
lede = "returned only null values";
|
|
11421
|
+
const projected = `every value it projected is null on all ${outcome.count} row(s)`;
|
|
11422
|
+
detail = unknown.length > 0 ? `${projected}, because ${isNotAField(unknown)}` : withSoundness(projected);
|
|
11423
|
+
} else if (outcome.kind === "null-values") {
|
|
11424
|
+
lede = "returned only null values";
|
|
11425
|
+
const projected = `every key it projected (${nameList(outcome.keys)}) is null`;
|
|
11426
|
+
const sameSet = unknown.length === outcome.keys.length && outcome.keys.every((k) => unknown.includes(k));
|
|
11427
|
+
if (sameSet) {
|
|
11428
|
+
detail = `${isNotAField(outcome.keys)}, so every key it projected is null`;
|
|
11429
|
+
} else if (unknown.length > 0) {
|
|
11430
|
+
detail = `${projected}, because ${isNotAField(unknown)}`;
|
|
11431
|
+
} else {
|
|
11432
|
+
detail = withSoundness(`${projected} on all ${scope}`);
|
|
11433
|
+
}
|
|
11434
|
+
} else {
|
|
11435
|
+
lede = "returned nothing";
|
|
11436
|
+
if (unknown.length > 0) {
|
|
11437
|
+
detail = isNotAField(unknown);
|
|
11438
|
+
} else {
|
|
11439
|
+
const selection = refs.hasPredicate ? "no record matched" : "the expression resolved to no value";
|
|
11440
|
+
detail = withSoundness(`${selection} — it read ${scope}`);
|
|
11441
|
+
}
|
|
11442
|
+
}
|
|
11443
|
+
const fields = present.length > 0 ? ` Available fields: ${nameList(present)}.` : "";
|
|
11444
|
+
return `--output-filter ${JSON.stringify(filter)} ${lede}: ${detail}.${fields}`;
|
|
11445
|
+
}
|
|
11446
|
+
function appendWarning(existing, note) {
|
|
11447
|
+
return existing ? `${existing} ${note}` : note;
|
|
11448
|
+
}
|
|
11449
|
+
function applyFilter(data, filter, onWarning) {
|
|
11291
11450
|
const codec = requireJmespath();
|
|
11292
11451
|
let result;
|
|
11293
11452
|
try {
|
|
@@ -11295,9 +11454,34 @@ function applyFilter(data, filter) {
|
|
|
11295
11454
|
} catch (err) {
|
|
11296
11455
|
throw new FilterEvaluationError(filter, err);
|
|
11297
11456
|
}
|
|
11298
|
-
|
|
11457
|
+
const inputCount = countRecords(data);
|
|
11458
|
+
const warn = (outcome) => {
|
|
11459
|
+
if (inputCount === 0)
|
|
11460
|
+
return;
|
|
11461
|
+
const note = buildFilterWarning(filter, data, outcome);
|
|
11462
|
+
getOutputSink().writeErr(`[WARN] ${note}
|
|
11463
|
+
`);
|
|
11464
|
+
onWarning?.(note);
|
|
11465
|
+
};
|
|
11466
|
+
const warnIfAllNull = (records) => {
|
|
11467
|
+
const keys = alwaysNullKeys(records);
|
|
11468
|
+
if (keys.length > 0)
|
|
11469
|
+
warn({ kind: "null-values", keys });
|
|
11470
|
+
};
|
|
11471
|
+
if (result == null) {
|
|
11472
|
+
warn({ kind: "empty" });
|
|
11299
11473
|
return [];
|
|
11474
|
+
}
|
|
11300
11475
|
if (Array.isArray(result)) {
|
|
11476
|
+
if (result.length === 0) {
|
|
11477
|
+
warn({ kind: "empty" });
|
|
11478
|
+
} else if (result.every((entry) => entry === null)) {
|
|
11479
|
+
warn({ kind: "null-elements", count: result.length });
|
|
11480
|
+
} else if (result.every((entry) => Array.isArray(entry)) && carriesOnlyNulls(result)) {
|
|
11481
|
+
warn({ kind: "null-rows", count: result.length });
|
|
11482
|
+
} else {
|
|
11483
|
+
warnIfAllNull(result);
|
|
11484
|
+
}
|
|
11301
11485
|
if (result.length > 0 && typeof result[0] !== "object") {
|
|
11302
11486
|
const fieldMatch = filter.match(/\.(\w+)$/);
|
|
11303
11487
|
const key = fieldMatch ? fieldMatch[1] : "Value";
|
|
@@ -11305,10 +11489,30 @@ function applyFilter(data, filter) {
|
|
|
11305
11489
|
}
|
|
11306
11490
|
return result;
|
|
11307
11491
|
}
|
|
11308
|
-
if (typeof result === "object")
|
|
11492
|
+
if (typeof result === "object") {
|
|
11493
|
+
warnIfAllNull([result]);
|
|
11309
11494
|
return result;
|
|
11495
|
+
}
|
|
11310
11496
|
return { Value: result };
|
|
11311
11497
|
}
|
|
11498
|
+
function filterFailureData(envelope) {
|
|
11499
|
+
const filter = getOutputFilter();
|
|
11500
|
+
const data = envelope.Data;
|
|
11501
|
+
if (!filter || data == null)
|
|
11502
|
+
return;
|
|
11503
|
+
let note;
|
|
11504
|
+
const [filterError, filtered] = catchError(() => applyFilter(data, filter, (n) => {
|
|
11505
|
+
note = n;
|
|
11506
|
+
}));
|
|
11507
|
+
if (filterError) {
|
|
11508
|
+
envelope.Warning = appendWarning(envelope.Warning, `--output-filter was not applied, so Data is shown in full: ${filterError.message}`);
|
|
11509
|
+
return;
|
|
11510
|
+
}
|
|
11511
|
+
envelope.Data = filtered;
|
|
11512
|
+
if (note) {
|
|
11513
|
+
envelope.Warning = appendWarning(envelope.Warning, note);
|
|
11514
|
+
}
|
|
11515
|
+
}
|
|
11312
11516
|
function defaultErrorCodeForResult(result) {
|
|
11313
11517
|
switch (result) {
|
|
11314
11518
|
case RESULTS.AuthenticationError:
|
|
@@ -11391,8 +11595,14 @@ var OutputFormatter;
|
|
|
11391
11595
|
}
|
|
11392
11596
|
const filter = getOutputFilter();
|
|
11393
11597
|
if (filter) {
|
|
11394
|
-
|
|
11598
|
+
let note;
|
|
11599
|
+
const filtered = applyFilter(data.Data, filter, (n) => {
|
|
11600
|
+
note = n;
|
|
11601
|
+
});
|
|
11395
11602
|
data.Data = normalize ? normalizeDataKeys(filtered, verbatim, subtrees && { refs: subtrees.refs, mode: "skip" }) : filtered;
|
|
11603
|
+
if (note) {
|
|
11604
|
+
data.Warning = appendWarning(data.Warning, note);
|
|
11605
|
+
}
|
|
11396
11606
|
}
|
|
11397
11607
|
logOutput(normalizeOutputKeys(data), getOutputFormat(), options?.tableRowStyle);
|
|
11398
11608
|
}
|
|
@@ -11420,6 +11630,7 @@ var OutputFormatter;
|
|
|
11420
11630
|
delete envelope.TelemetryErrorClass;
|
|
11421
11631
|
delete envelope.TelemetryTerminalOutcome;
|
|
11422
11632
|
delete envelope.TelemetryTerminalSignal;
|
|
11633
|
+
filterFailureData(envelope);
|
|
11423
11634
|
if (!suppressTelemetry) {
|
|
11424
11635
|
telemetry.trackEvent(CommonTelemetryEvents.Error, {
|
|
11425
11636
|
result: data.Result,
|
|
@@ -11468,13 +11679,20 @@ var OutputFormatter;
|
|
|
11468
11679
|
OutputFormatter.log = log;
|
|
11469
11680
|
function formatToString(data) {
|
|
11470
11681
|
const filter = getOutputFilter();
|
|
11682
|
+
const envelope = data;
|
|
11471
11683
|
if ("Data" in data && data.Data != null) {
|
|
11472
11684
|
data.Data = normalizeDataKeys(data.Data);
|
|
11473
11685
|
if (filter) {
|
|
11474
|
-
|
|
11686
|
+
let note;
|
|
11687
|
+
data.Data = normalizeDataKeys(applyFilter(data.Data, filter, (n) => {
|
|
11688
|
+
note = n;
|
|
11689
|
+
}));
|
|
11690
|
+
if (note) {
|
|
11691
|
+
envelope.Warning = appendWarning(envelope.Warning, note);
|
|
11692
|
+
}
|
|
11475
11693
|
}
|
|
11476
11694
|
}
|
|
11477
|
-
const output = normalizeOutputKeys(
|
|
11695
|
+
const output = normalizeOutputKeys(envelope);
|
|
11478
11696
|
const lines = [];
|
|
11479
11697
|
const sink = getOutputSink();
|
|
11480
11698
|
printOutput(output, getOutputFormat(), (msg) => {
|
|
@@ -13752,4 +13970,4 @@ export {
|
|
|
13752
13970
|
writeTelemetrySpoolFile
|
|
13753
13971
|
};
|
|
13754
13972
|
|
|
13755
|
-
//# debugId=
|
|
13973
|
+
//# debugId=03A35D12FEEB5F8864756E2164756E21
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/common",
|
|
3
3
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
4
|
-
"version": "1.202.1-preview.
|
|
4
|
+
"version": "1.202.1-preview.239",
|
|
5
5
|
"description": "Common infrastructure needed by uip tools.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"mihaigirleanu",
|
|
76
76
|
"vlad-uipath"
|
|
77
77
|
],
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "97545a7857bdff7e6db62bbe13c6097607cf38f1"
|
|
79
79
|
}
|