@uipath/gov-tool 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.
Files changed (2) hide show
  1. package/dist/tool.js +225 -8
  2. package/package.json +2 -2
package/dist/tool.js CHANGED
@@ -7653,7 +7653,7 @@ var require_commander = __commonJS(function(exports) {
7653
7653
  var package_default = {
7654
7654
  name: "@uipath/gov-tool",
7655
7655
  license: "SEE LICENSE IN LICENSE.txt",
7656
- version: "1.202.1-preview.220",
7656
+ version: "1.202.1-preview.239",
7657
7657
  description: "Manage UiPath governance — AOps policies, Access policies, and compliance packs.",
7658
7658
  private: false,
7659
7659
  repository: {
@@ -12420,7 +12420,165 @@ class FilterImplicitLimitError extends Error {
12420
12420
  this.instructions = "Pass --limit <n> to choose how many records the filter applies to. " + "To filter over all records, pass the command's maximum accepted --limit (see the option's description in --help).";
12421
12421
  }
12422
12422
  }
12423
- function applyFilter(data, filter) {
12423
+ function countRecords(data) {
12424
+ if (Array.isArray(data))
12425
+ return data.length;
12426
+ return data == null ? 0 : 1;
12427
+ }
12428
+ function availableFields(data) {
12429
+ const records = Array.isArray(data) ? data : [data];
12430
+ const keys = new Set;
12431
+ for (const record of records) {
12432
+ if (record && typeof record === "object" && !Array.isArray(record)) {
12433
+ for (const key of Object.keys(record))
12434
+ keys.add(key);
12435
+ }
12436
+ }
12437
+ return [...keys];
12438
+ }
12439
+ function decodeQuotedIdentifier(whole, inner) {
12440
+ const [error, decoded] = catchError2(() => JSON.parse(whole));
12441
+ if (!error && typeof decoded === "string")
12442
+ return decoded;
12443
+ return inner.replace(/\\(.)/g, "$1");
12444
+ }
12445
+ function referencedFields(filter) {
12446
+ const top = new Set;
12447
+ const nested = new Set;
12448
+ const withoutValueLiterals = filter.replace(/'(?:\\.|[^'\\])*'/g, " ").replace(/`(?:\\.|[^`\\])*`/g, " ");
12449
+ const isPathTail = (text, index) => text[index - 1] === "." && /[A-Za-z0-9_"]/.test(text[index - 2] ?? "");
12450
+ const quoted = [];
12451
+ const withoutLiterals = withoutValueLiterals.replace(/"((?:\\.|[^"\\])*)"/g, (whole, name, index) => {
12452
+ const isAlias = /^\s*:/.test(withoutValueLiterals.slice(index + whole.length));
12453
+ if (!isAlias) {
12454
+ quoted.push({
12455
+ name: decodeQuotedIdentifier(whole, name),
12456
+ index,
12457
+ tail: isPathTail(withoutValueLiterals, index)
12458
+ });
12459
+ }
12460
+ return `"${" ".repeat(whole.length - 2)}"`;
12461
+ });
12462
+ const descent = /[A-Za-z0-9_"]\s*[.[]/.exec(withoutLiterals);
12463
+ const rootEnd = descent ? descent.index + 1 : Number.POSITIVE_INFINITY;
12464
+ const place = (name, index, tail) => {
12465
+ if (tail || index >= rootEnd)
12466
+ nested.add(name);
12467
+ else
12468
+ top.add(name);
12469
+ };
12470
+ for (const entry of quoted)
12471
+ place(entry.name, entry.index, entry.tail);
12472
+ const identifiers = withoutLiterals.matchAll(/([A-Za-z_][A-Za-z0-9_]*)(\s*[:(])?/g);
12473
+ const reserved = new Set(["true", "false", "null", "and", "or", "not"]);
12474
+ for (const match of identifiers) {
12475
+ const [, name, trailing] = match;
12476
+ if (trailing || reserved.has(name))
12477
+ continue;
12478
+ place(name, match.index, isPathTail(withoutLiterals, match.index));
12479
+ }
12480
+ return {
12481
+ top: [...top],
12482
+ nested: [...nested].filter((name) => !top.has(name)),
12483
+ hasPredicate: /\[\s*\?/.test(withoutValueLiterals)
12484
+ };
12485
+ }
12486
+ function appearsBelowTopLevel(data, name) {
12487
+ let budget = 2000;
12488
+ const visit = (value, depth) => {
12489
+ if (budget-- <= 0 || depth > 4)
12490
+ return false;
12491
+ if (value === null || typeof value !== "object")
12492
+ return false;
12493
+ if (Array.isArray(value))
12494
+ return value.some((entry) => visit(entry, depth));
12495
+ const record = value;
12496
+ if (depth > 0 && Object.hasOwn(record, name))
12497
+ return true;
12498
+ return Object.values(record).some((entry) => visit(entry, depth + 1));
12499
+ };
12500
+ return visit(data, 0);
12501
+ }
12502
+ function alwaysNullKeys(records) {
12503
+ const objects = records.filter((r) => r != null && typeof r === "object" && !Array.isArray(r));
12504
+ if (objects.length === 0 || objects.length !== records.length)
12505
+ return [];
12506
+ const keys = [...new Set(objects.flatMap((o) => Object.keys(o)))];
12507
+ if (keys.length === 0)
12508
+ return [];
12509
+ const nullKeys = keys.filter((key) => objects.every((record) => record[key] === null));
12510
+ return nullKeys.length === keys.length ? nullKeys : [];
12511
+ }
12512
+ function carriesOnlyNulls(value) {
12513
+ if (value === null)
12514
+ return true;
12515
+ if (Array.isArray(value)) {
12516
+ return value.length > 0 && value.every(carriesOnlyNulls);
12517
+ }
12518
+ if (typeof value === "object" && value !== undefined) {
12519
+ const values = Object.values(value);
12520
+ return values.length > 0 && values.every(carriesOnlyNulls);
12521
+ }
12522
+ return false;
12523
+ }
12524
+ function nameList(names, cap2 = 12) {
12525
+ const shown = names.slice(0, cap2).map((n) => `\`${n}\``);
12526
+ const rest = names.length - shown.length;
12527
+ return shown.join(", ") + (rest > 0 ? `, and ${rest} more` : "");
12528
+ }
12529
+ function buildFilterWarning(filter, data, outcome) {
12530
+ const present = availableFields(data);
12531
+ const refs = referencedFields(filter);
12532
+ const unknown = refs.top.filter((name) => !present.includes(name) && !appearsBelowTopLevel(data, name));
12533
+ const unchecked = refs.nested.filter((name) => !present.includes(name));
12534
+ const count = countRecords(data);
12535
+ const scope = `${count} record(s)`;
12536
+ const isNotAField = (names) => `${nameList(names)} ${names.length === 1 ? "is not a field" : "are not fields"} on the ${scope} it read`;
12537
+ 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" : "";
12538
+ const withSoundness = (base) => soundness ? `${base}, and ${soundness}` : base;
12539
+ let detail;
12540
+ let lede;
12541
+ if (outcome.kind === "null-elements") {
12542
+ lede = "returned only null values";
12543
+ const projected = `all ${outcome.count} of the elements it projected are null`;
12544
+ if (unknown.length > 0) {
12545
+ detail = `${projected}, because ${isNotAField(unknown)}`;
12546
+ } else if (unchecked.length > 0) {
12547
+ detail = withSoundness(projected);
12548
+ } else {
12549
+ 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`;
12550
+ }
12551
+ } else if (outcome.kind === "null-rows") {
12552
+ lede = "returned only null values";
12553
+ const projected = `every value it projected is null on all ${outcome.count} row(s)`;
12554
+ detail = unknown.length > 0 ? `${projected}, because ${isNotAField(unknown)}` : withSoundness(projected);
12555
+ } else if (outcome.kind === "null-values") {
12556
+ lede = "returned only null values";
12557
+ const projected = `every key it projected (${nameList(outcome.keys)}) is null`;
12558
+ const sameSet = unknown.length === outcome.keys.length && outcome.keys.every((k) => unknown.includes(k));
12559
+ if (sameSet) {
12560
+ detail = `${isNotAField(outcome.keys)}, so every key it projected is null`;
12561
+ } else if (unknown.length > 0) {
12562
+ detail = `${projected}, because ${isNotAField(unknown)}`;
12563
+ } else {
12564
+ detail = withSoundness(`${projected} on all ${scope}`);
12565
+ }
12566
+ } else {
12567
+ lede = "returned nothing";
12568
+ if (unknown.length > 0) {
12569
+ detail = isNotAField(unknown);
12570
+ } else {
12571
+ const selection = refs.hasPredicate ? "no record matched" : "the expression resolved to no value";
12572
+ detail = withSoundness(`${selection} — it read ${scope}`);
12573
+ }
12574
+ }
12575
+ const fields = present.length > 0 ? ` Available fields: ${nameList(present)}.` : "";
12576
+ return `--output-filter ${JSON.stringify(filter)} ${lede}: ${detail}.${fields}`;
12577
+ }
12578
+ function appendWarning(existing, note) {
12579
+ return existing ? `${existing} ${note}` : note;
12580
+ }
12581
+ function applyFilter(data, filter, onWarning) {
12424
12582
  const codec = requireJmespath();
12425
12583
  let result;
12426
12584
  try {
@@ -12428,9 +12586,34 @@ function applyFilter(data, filter) {
12428
12586
  } catch (err) {
12429
12587
  throw new FilterEvaluationError(filter, err);
12430
12588
  }
12431
- if (result == null)
12589
+ const inputCount = countRecords(data);
12590
+ const warn = (outcome) => {
12591
+ if (inputCount === 0)
12592
+ return;
12593
+ const note = buildFilterWarning(filter, data, outcome);
12594
+ getOutputSink().writeErr(`[WARN] ${note}
12595
+ `);
12596
+ onWarning?.(note);
12597
+ };
12598
+ const warnIfAllNull = (records) => {
12599
+ const keys = alwaysNullKeys(records);
12600
+ if (keys.length > 0)
12601
+ warn({ kind: "null-values", keys });
12602
+ };
12603
+ if (result == null) {
12604
+ warn({ kind: "empty" });
12432
12605
  return [];
12606
+ }
12433
12607
  if (Array.isArray(result)) {
12608
+ if (result.length === 0) {
12609
+ warn({ kind: "empty" });
12610
+ } else if (result.every((entry) => entry === null)) {
12611
+ warn({ kind: "null-elements", count: result.length });
12612
+ } else if (result.every((entry) => Array.isArray(entry)) && carriesOnlyNulls(result)) {
12613
+ warn({ kind: "null-rows", count: result.length });
12614
+ } else {
12615
+ warnIfAllNull(result);
12616
+ }
12434
12617
  if (result.length > 0 && typeof result[0] !== "object") {
12435
12618
  const fieldMatch = filter.match(/\.(\w+)$/);
12436
12619
  const key = fieldMatch ? fieldMatch[1] : "Value";
@@ -12438,10 +12621,30 @@ function applyFilter(data, filter) {
12438
12621
  }
12439
12622
  return result;
12440
12623
  }
12441
- if (typeof result === "object")
12624
+ if (typeof result === "object") {
12625
+ warnIfAllNull([result]);
12442
12626
  return result;
12627
+ }
12443
12628
  return { Value: result };
12444
12629
  }
12630
+ function filterFailureData(envelope) {
12631
+ const filter = getOutputFilter();
12632
+ const data = envelope.Data;
12633
+ if (!filter || data == null)
12634
+ return;
12635
+ let note;
12636
+ const [filterError, filtered] = catchError2(() => applyFilter(data, filter, (n) => {
12637
+ note = n;
12638
+ }));
12639
+ if (filterError) {
12640
+ envelope.Warning = appendWarning(envelope.Warning, `--output-filter was not applied, so Data is shown in full: ${filterError.message}`);
12641
+ return;
12642
+ }
12643
+ envelope.Data = filtered;
12644
+ if (note) {
12645
+ envelope.Warning = appendWarning(envelope.Warning, note);
12646
+ }
12647
+ }
12445
12648
  function defaultErrorCodeForResult(result) {
12446
12649
  switch (result) {
12447
12650
  case RESULTS.AuthenticationError:
@@ -12524,8 +12727,14 @@ var OutputFormatter;
12524
12727
  }
12525
12728
  const filter = getOutputFilter();
12526
12729
  if (filter) {
12527
- const filtered = applyFilter(data.Data, filter);
12730
+ let note;
12731
+ const filtered = applyFilter(data.Data, filter, (n) => {
12732
+ note = n;
12733
+ });
12528
12734
  data.Data = normalize ? normalizeDataKeys(filtered, verbatim, subtrees && { refs: subtrees.refs, mode: "skip" }) : filtered;
12735
+ if (note) {
12736
+ data.Warning = appendWarning(data.Warning, note);
12737
+ }
12529
12738
  }
12530
12739
  logOutput(normalizeOutputKeys(data), getOutputFormat(), options?.tableRowStyle);
12531
12740
  }
@@ -12553,6 +12762,7 @@ var OutputFormatter;
12553
12762
  delete envelope.TelemetryErrorClass;
12554
12763
  delete envelope.TelemetryTerminalOutcome;
12555
12764
  delete envelope.TelemetryTerminalSignal;
12765
+ filterFailureData(envelope);
12556
12766
  if (!suppressTelemetry) {
12557
12767
  telemetry.trackEvent(CommonTelemetryEvents.Error, {
12558
12768
  result: data.Result,
@@ -12601,13 +12811,20 @@ var OutputFormatter;
12601
12811
  OutputFormatter.log = log;
12602
12812
  function formatToString(data) {
12603
12813
  const filter = getOutputFilter();
12814
+ const envelope = data;
12604
12815
  if ("Data" in data && data.Data != null) {
12605
12816
  data.Data = normalizeDataKeys(data.Data);
12606
12817
  if (filter) {
12607
- data.Data = normalizeDataKeys(applyFilter(data.Data, filter));
12818
+ let note;
12819
+ data.Data = normalizeDataKeys(applyFilter(data.Data, filter, (n) => {
12820
+ note = n;
12821
+ }));
12822
+ if (note) {
12823
+ envelope.Warning = appendWarning(envelope.Warning, note);
12824
+ }
12608
12825
  }
12609
12826
  }
12610
- const output = normalizeOutputKeys(data);
12827
+ const output = normalizeOutputKeys(envelope);
12611
12828
  const lines = [];
12612
12829
  const sink = getOutputSink();
12613
12830
  printOutput(output, getOutputFormat(), (msg) => {
@@ -24512,4 +24729,4 @@ export {
24512
24729
  registerCommands
24513
24730
  };
24514
24731
 
24515
- //# debugId=366C2EBBFE2A46D164756E2164756E21
24732
+ //# debugId=D51DB1185621142B64756E2164756E21
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uipath/gov-tool",
3
3
  "license": "SEE LICENSE IN LICENSE.txt",
4
- "version": "1.202.1-preview.220",
4
+ "version": "1.202.1-preview.239",
5
5
  "description": "Manage UiPath governance — AOps policies, Access policies, and compliance packs.",
6
6
  "private": false,
7
7
  "repository": {
@@ -23,5 +23,5 @@
23
23
  "files": [
24
24
  "dist"
25
25
  ],
26
- "gitHead": "a09041733b628c3f6b658a1f58349ea0f40bb492"
26
+ "gitHead": "97545a7857bdff7e6db62bbe13c6097607cf38f1"
27
27
  }