@uipath/uipath-python-bridge 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/index.js +224 -7
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -9728,7 +9728,165 @@ class FilterImplicitLimitError extends Error {
9728
9728
  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).";
9729
9729
  }
9730
9730
  }
9731
- function applyFilter(data, filter) {
9731
+ function countRecords(data) {
9732
+ if (Array.isArray(data))
9733
+ return data.length;
9734
+ return data == null ? 0 : 1;
9735
+ }
9736
+ function availableFields(data) {
9737
+ const records = Array.isArray(data) ? data : [data];
9738
+ const keys = new Set;
9739
+ for (const record of records) {
9740
+ if (record && typeof record === "object" && !Array.isArray(record)) {
9741
+ for (const key of Object.keys(record))
9742
+ keys.add(key);
9743
+ }
9744
+ }
9745
+ return [...keys];
9746
+ }
9747
+ function decodeQuotedIdentifier(whole, inner) {
9748
+ const [error, decoded] = catchError(() => JSON.parse(whole));
9749
+ if (!error && typeof decoded === "string")
9750
+ return decoded;
9751
+ return inner.replace(/\\(.)/g, "$1");
9752
+ }
9753
+ function referencedFields(filter) {
9754
+ const top = new Set;
9755
+ const nested = new Set;
9756
+ const withoutValueLiterals = filter.replace(/'(?:\\.|[^'\\])*'/g, " ").replace(/`(?:\\.|[^`\\])*`/g, " ");
9757
+ const isPathTail = (text, index) => text[index - 1] === "." && /[A-Za-z0-9_"]/.test(text[index - 2] ?? "");
9758
+ const quoted = [];
9759
+ const withoutLiterals = withoutValueLiterals.replace(/"((?:\\.|[^"\\])*)"/g, (whole, name, index) => {
9760
+ const isAlias = /^\s*:/.test(withoutValueLiterals.slice(index + whole.length));
9761
+ if (!isAlias) {
9762
+ quoted.push({
9763
+ name: decodeQuotedIdentifier(whole, name),
9764
+ index,
9765
+ tail: isPathTail(withoutValueLiterals, index)
9766
+ });
9767
+ }
9768
+ return `"${" ".repeat(whole.length - 2)}"`;
9769
+ });
9770
+ const descent = /[A-Za-z0-9_"]\s*[.[]/.exec(withoutLiterals);
9771
+ const rootEnd = descent ? descent.index + 1 : Number.POSITIVE_INFINITY;
9772
+ const place = (name, index, tail) => {
9773
+ if (tail || index >= rootEnd)
9774
+ nested.add(name);
9775
+ else
9776
+ top.add(name);
9777
+ };
9778
+ for (const entry of quoted)
9779
+ place(entry.name, entry.index, entry.tail);
9780
+ const identifiers = withoutLiterals.matchAll(/([A-Za-z_][A-Za-z0-9_]*)(\s*[:(])?/g);
9781
+ const reserved = new Set(["true", "false", "null", "and", "or", "not"]);
9782
+ for (const match of identifiers) {
9783
+ const [, name, trailing] = match;
9784
+ if (trailing || reserved.has(name))
9785
+ continue;
9786
+ place(name, match.index, isPathTail(withoutLiterals, match.index));
9787
+ }
9788
+ return {
9789
+ top: [...top],
9790
+ nested: [...nested].filter((name) => !top.has(name)),
9791
+ hasPredicate: /\[\s*\?/.test(withoutValueLiterals)
9792
+ };
9793
+ }
9794
+ function appearsBelowTopLevel(data, name) {
9795
+ let budget = 2000;
9796
+ const visit = (value, depth) => {
9797
+ if (budget-- <= 0 || depth > 4)
9798
+ return false;
9799
+ if (value === null || typeof value !== "object")
9800
+ return false;
9801
+ if (Array.isArray(value))
9802
+ return value.some((entry) => visit(entry, depth));
9803
+ const record = value;
9804
+ if (depth > 0 && Object.hasOwn(record, name))
9805
+ return true;
9806
+ return Object.values(record).some((entry) => visit(entry, depth + 1));
9807
+ };
9808
+ return visit(data, 0);
9809
+ }
9810
+ function alwaysNullKeys(records) {
9811
+ const objects = records.filter((r) => r != null && typeof r === "object" && !Array.isArray(r));
9812
+ if (objects.length === 0 || objects.length !== records.length)
9813
+ return [];
9814
+ const keys = [...new Set(objects.flatMap((o) => Object.keys(o)))];
9815
+ if (keys.length === 0)
9816
+ return [];
9817
+ const nullKeys = keys.filter((key) => objects.every((record) => record[key] === null));
9818
+ return nullKeys.length === keys.length ? nullKeys : [];
9819
+ }
9820
+ function carriesOnlyNulls(value) {
9821
+ if (value === null)
9822
+ return true;
9823
+ if (Array.isArray(value)) {
9824
+ return value.length > 0 && value.every(carriesOnlyNulls);
9825
+ }
9826
+ if (typeof value === "object" && value !== undefined) {
9827
+ const values = Object.values(value);
9828
+ return values.length > 0 && values.every(carriesOnlyNulls);
9829
+ }
9830
+ return false;
9831
+ }
9832
+ function nameList(names, cap2 = 12) {
9833
+ const shown = names.slice(0, cap2).map((n) => `\`${n}\``);
9834
+ const rest = names.length - shown.length;
9835
+ return shown.join(", ") + (rest > 0 ? `, and ${rest} more` : "");
9836
+ }
9837
+ function buildFilterWarning(filter, data, outcome) {
9838
+ const present = availableFields(data);
9839
+ const refs = referencedFields(filter);
9840
+ const unknown = refs.top.filter((name) => !present.includes(name) && !appearsBelowTopLevel(data, name));
9841
+ const unchecked = refs.nested.filter((name) => !present.includes(name));
9842
+ const count = countRecords(data);
9843
+ const scope = `${count} record(s)`;
9844
+ const isNotAField = (names) => `${nameList(names)} ${names.length === 1 ? "is not a field" : "are not fields"} on the ${scope} it read`;
9845
+ 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" : "";
9846
+ const withSoundness = (base) => soundness ? `${base}, and ${soundness}` : base;
9847
+ let detail;
9848
+ let lede;
9849
+ if (outcome.kind === "null-elements") {
9850
+ lede = "returned only null values";
9851
+ const projected = `all ${outcome.count} of the elements it projected are null`;
9852
+ if (unknown.length > 0) {
9853
+ detail = `${projected}, because ${isNotAField(unknown)}`;
9854
+ } else if (unchecked.length > 0) {
9855
+ detail = withSoundness(projected);
9856
+ } else {
9857
+ 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`;
9858
+ }
9859
+ } else if (outcome.kind === "null-rows") {
9860
+ lede = "returned only null values";
9861
+ const projected = `every value it projected is null on all ${outcome.count} row(s)`;
9862
+ detail = unknown.length > 0 ? `${projected}, because ${isNotAField(unknown)}` : withSoundness(projected);
9863
+ } else if (outcome.kind === "null-values") {
9864
+ lede = "returned only null values";
9865
+ const projected = `every key it projected (${nameList(outcome.keys)}) is null`;
9866
+ const sameSet = unknown.length === outcome.keys.length && outcome.keys.every((k) => unknown.includes(k));
9867
+ if (sameSet) {
9868
+ detail = `${isNotAField(outcome.keys)}, so every key it projected is null`;
9869
+ } else if (unknown.length > 0) {
9870
+ detail = `${projected}, because ${isNotAField(unknown)}`;
9871
+ } else {
9872
+ detail = withSoundness(`${projected} on all ${scope}`);
9873
+ }
9874
+ } else {
9875
+ lede = "returned nothing";
9876
+ if (unknown.length > 0) {
9877
+ detail = isNotAField(unknown);
9878
+ } else {
9879
+ const selection = refs.hasPredicate ? "no record matched" : "the expression resolved to no value";
9880
+ detail = withSoundness(`${selection} — it read ${scope}`);
9881
+ }
9882
+ }
9883
+ const fields = present.length > 0 ? ` Available fields: ${nameList(present)}.` : "";
9884
+ return `--output-filter ${JSON.stringify(filter)} ${lede}: ${detail}.${fields}`;
9885
+ }
9886
+ function appendWarning(existing, note) {
9887
+ return existing ? `${existing} ${note}` : note;
9888
+ }
9889
+ function applyFilter(data, filter, onWarning) {
9732
9890
  const codec = requireJmespath();
9733
9891
  let result;
9734
9892
  try {
@@ -9736,9 +9894,34 @@ function applyFilter(data, filter) {
9736
9894
  } catch (err) {
9737
9895
  throw new FilterEvaluationError(filter, err);
9738
9896
  }
9739
- if (result == null)
9897
+ const inputCount = countRecords(data);
9898
+ const warn = (outcome) => {
9899
+ if (inputCount === 0)
9900
+ return;
9901
+ const note = buildFilterWarning(filter, data, outcome);
9902
+ getOutputSink().writeErr(`[WARN] ${note}
9903
+ `);
9904
+ onWarning?.(note);
9905
+ };
9906
+ const warnIfAllNull = (records) => {
9907
+ const keys = alwaysNullKeys(records);
9908
+ if (keys.length > 0)
9909
+ warn({ kind: "null-values", keys });
9910
+ };
9911
+ if (result == null) {
9912
+ warn({ kind: "empty" });
9740
9913
  return [];
9914
+ }
9741
9915
  if (Array.isArray(result)) {
9916
+ if (result.length === 0) {
9917
+ warn({ kind: "empty" });
9918
+ } else if (result.every((entry) => entry === null)) {
9919
+ warn({ kind: "null-elements", count: result.length });
9920
+ } else if (result.every((entry) => Array.isArray(entry)) && carriesOnlyNulls(result)) {
9921
+ warn({ kind: "null-rows", count: result.length });
9922
+ } else {
9923
+ warnIfAllNull(result);
9924
+ }
9742
9925
  if (result.length > 0 && typeof result[0] !== "object") {
9743
9926
  const fieldMatch = filter.match(/\.(\w+)$/);
9744
9927
  const key = fieldMatch ? fieldMatch[1] : "Value";
@@ -9746,10 +9929,30 @@ function applyFilter(data, filter) {
9746
9929
  }
9747
9930
  return result;
9748
9931
  }
9749
- if (typeof result === "object")
9932
+ if (typeof result === "object") {
9933
+ warnIfAllNull([result]);
9750
9934
  return result;
9935
+ }
9751
9936
  return { Value: result };
9752
9937
  }
9938
+ function filterFailureData(envelope) {
9939
+ const filter = getOutputFilter();
9940
+ const data = envelope.Data;
9941
+ if (!filter || data == null)
9942
+ return;
9943
+ let note;
9944
+ const [filterError, filtered] = catchError(() => applyFilter(data, filter, (n) => {
9945
+ note = n;
9946
+ }));
9947
+ if (filterError) {
9948
+ envelope.Warning = appendWarning(envelope.Warning, `--output-filter was not applied, so Data is shown in full: ${filterError.message}`);
9949
+ return;
9950
+ }
9951
+ envelope.Data = filtered;
9952
+ if (note) {
9953
+ envelope.Warning = appendWarning(envelope.Warning, note);
9954
+ }
9955
+ }
9753
9956
  function defaultErrorCodeForResult(result) {
9754
9957
  switch (result) {
9755
9958
  case RESULTS.AuthenticationError:
@@ -9832,8 +10035,14 @@ var OutputFormatter;
9832
10035
  }
9833
10036
  const filter = getOutputFilter();
9834
10037
  if (filter) {
9835
- const filtered = applyFilter(data.Data, filter);
10038
+ let note;
10039
+ const filtered = applyFilter(data.Data, filter, (n) => {
10040
+ note = n;
10041
+ });
9836
10042
  data.Data = normalize ? normalizeDataKeys(filtered, verbatim, subtrees && { refs: subtrees.refs, mode: "skip" }) : filtered;
10043
+ if (note) {
10044
+ data.Warning = appendWarning(data.Warning, note);
10045
+ }
9837
10046
  }
9838
10047
  logOutput(normalizeOutputKeys(data), getOutputFormat(), options?.tableRowStyle);
9839
10048
  }
@@ -9861,6 +10070,7 @@ var OutputFormatter;
9861
10070
  delete envelope.TelemetryErrorClass;
9862
10071
  delete envelope.TelemetryTerminalOutcome;
9863
10072
  delete envelope.TelemetryTerminalSignal;
10073
+ filterFailureData(envelope);
9864
10074
  if (!suppressTelemetry) {
9865
10075
  telemetry.trackEvent(CommonTelemetryEvents.Error, {
9866
10076
  result: data.Result,
@@ -9909,13 +10119,20 @@ var OutputFormatter;
9909
10119
  OutputFormatter.log = log;
9910
10120
  function formatToString(data) {
9911
10121
  const filter = getOutputFilter();
10122
+ const envelope = data;
9912
10123
  if ("Data" in data && data.Data != null) {
9913
10124
  data.Data = normalizeDataKeys(data.Data);
9914
10125
  if (filter) {
9915
- data.Data = normalizeDataKeys(applyFilter(data.Data, filter));
10126
+ let note;
10127
+ data.Data = normalizeDataKeys(applyFilter(data.Data, filter, (n) => {
10128
+ note = n;
10129
+ }));
10130
+ if (note) {
10131
+ envelope.Warning = appendWarning(envelope.Warning, note);
10132
+ }
9916
10133
  }
9917
10134
  }
9918
- const output = normalizeOutputKeys(data);
10135
+ const output = normalizeOutputKeys(envelope);
9919
10136
  const lines = [];
9920
10137
  const sink = getOutputSink();
9921
10138
  printOutput(output, getOutputFormat(), (msg) => {
@@ -12745,4 +12962,4 @@ export {
12745
12962
  runUipathPythonCommand
12746
12963
  };
12747
12964
 
12748
- //# debugId=B35015771384829464756E2164756E21
12965
+ //# debugId=11AD95BBBAB0DB9F64756E2164756E21
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uipath/uipath-python-bridge",
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": "Shared Python detection, caching, and CLI bridge for UiPath Python SDK tools.",
6
6
  "keywords": [
7
7
  "uip",
@@ -24,5 +24,5 @@
24
24
  "publishConfig": {
25
25
  "registry": "https://registry.npmjs.org/"
26
26
  },
27
- "gitHead": "a09041733b628c3f6b658a1f58349ea0f40bb492"
27
+ "gitHead": "97545a7857bdff7e6db62bbe13c6097607cf38f1"
28
28
  }