@uipath/identity-commands 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/index.js +224 -7
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -4745,7 +4745,165 @@ class FilterImplicitLimitError extends Error {
|
|
|
4745
4745
|
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).";
|
|
4746
4746
|
}
|
|
4747
4747
|
}
|
|
4748
|
-
function
|
|
4748
|
+
function countRecords(data) {
|
|
4749
|
+
if (Array.isArray(data))
|
|
4750
|
+
return data.length;
|
|
4751
|
+
return data == null ? 0 : 1;
|
|
4752
|
+
}
|
|
4753
|
+
function availableFields(data) {
|
|
4754
|
+
const records = Array.isArray(data) ? data : [data];
|
|
4755
|
+
const keys = new Set;
|
|
4756
|
+
for (const record of records) {
|
|
4757
|
+
if (record && typeof record === "object" && !Array.isArray(record)) {
|
|
4758
|
+
for (const key of Object.keys(record))
|
|
4759
|
+
keys.add(key);
|
|
4760
|
+
}
|
|
4761
|
+
}
|
|
4762
|
+
return [...keys];
|
|
4763
|
+
}
|
|
4764
|
+
function decodeQuotedIdentifier(whole, inner) {
|
|
4765
|
+
const [error, decoded] = catchError(() => JSON.parse(whole));
|
|
4766
|
+
if (!error && typeof decoded === "string")
|
|
4767
|
+
return decoded;
|
|
4768
|
+
return inner.replace(/\\(.)/g, "$1");
|
|
4769
|
+
}
|
|
4770
|
+
function referencedFields(filter) {
|
|
4771
|
+
const top = new Set;
|
|
4772
|
+
const nested = new Set;
|
|
4773
|
+
const withoutValueLiterals = filter.replace(/'(?:\\.|[^'\\])*'/g, " ").replace(/`(?:\\.|[^`\\])*`/g, " ");
|
|
4774
|
+
const isPathTail = (text, index) => text[index - 1] === "." && /[A-Za-z0-9_"]/.test(text[index - 2] ?? "");
|
|
4775
|
+
const quoted = [];
|
|
4776
|
+
const withoutLiterals = withoutValueLiterals.replace(/"((?:\\.|[^"\\])*)"/g, (whole, name, index) => {
|
|
4777
|
+
const isAlias = /^\s*:/.test(withoutValueLiterals.slice(index + whole.length));
|
|
4778
|
+
if (!isAlias) {
|
|
4779
|
+
quoted.push({
|
|
4780
|
+
name: decodeQuotedIdentifier(whole, name),
|
|
4781
|
+
index,
|
|
4782
|
+
tail: isPathTail(withoutValueLiterals, index)
|
|
4783
|
+
});
|
|
4784
|
+
}
|
|
4785
|
+
return `"${" ".repeat(whole.length - 2)}"`;
|
|
4786
|
+
});
|
|
4787
|
+
const descent = /[A-Za-z0-9_"]\s*[.[]/.exec(withoutLiterals);
|
|
4788
|
+
const rootEnd = descent ? descent.index + 1 : Number.POSITIVE_INFINITY;
|
|
4789
|
+
const place = (name, index, tail) => {
|
|
4790
|
+
if (tail || index >= rootEnd)
|
|
4791
|
+
nested.add(name);
|
|
4792
|
+
else
|
|
4793
|
+
top.add(name);
|
|
4794
|
+
};
|
|
4795
|
+
for (const entry of quoted)
|
|
4796
|
+
place(entry.name, entry.index, entry.tail);
|
|
4797
|
+
const identifiers = withoutLiterals.matchAll(/([A-Za-z_][A-Za-z0-9_]*)(\s*[:(])?/g);
|
|
4798
|
+
const reserved = new Set(["true", "false", "null", "and", "or", "not"]);
|
|
4799
|
+
for (const match of identifiers) {
|
|
4800
|
+
const [, name, trailing] = match;
|
|
4801
|
+
if (trailing || reserved.has(name))
|
|
4802
|
+
continue;
|
|
4803
|
+
place(name, match.index, isPathTail(withoutLiterals, match.index));
|
|
4804
|
+
}
|
|
4805
|
+
return {
|
|
4806
|
+
top: [...top],
|
|
4807
|
+
nested: [...nested].filter((name) => !top.has(name)),
|
|
4808
|
+
hasPredicate: /\[\s*\?/.test(withoutValueLiterals)
|
|
4809
|
+
};
|
|
4810
|
+
}
|
|
4811
|
+
function appearsBelowTopLevel(data, name) {
|
|
4812
|
+
let budget = 2000;
|
|
4813
|
+
const visit = (value, depth) => {
|
|
4814
|
+
if (budget-- <= 0 || depth > 4)
|
|
4815
|
+
return false;
|
|
4816
|
+
if (value === null || typeof value !== "object")
|
|
4817
|
+
return false;
|
|
4818
|
+
if (Array.isArray(value))
|
|
4819
|
+
return value.some((entry) => visit(entry, depth));
|
|
4820
|
+
const record = value;
|
|
4821
|
+
if (depth > 0 && Object.hasOwn(record, name))
|
|
4822
|
+
return true;
|
|
4823
|
+
return Object.values(record).some((entry) => visit(entry, depth + 1));
|
|
4824
|
+
};
|
|
4825
|
+
return visit(data, 0);
|
|
4826
|
+
}
|
|
4827
|
+
function alwaysNullKeys(records) {
|
|
4828
|
+
const objects = records.filter((r) => r != null && typeof r === "object" && !Array.isArray(r));
|
|
4829
|
+
if (objects.length === 0 || objects.length !== records.length)
|
|
4830
|
+
return [];
|
|
4831
|
+
const keys = [...new Set(objects.flatMap((o) => Object.keys(o)))];
|
|
4832
|
+
if (keys.length === 0)
|
|
4833
|
+
return [];
|
|
4834
|
+
const nullKeys = keys.filter((key) => objects.every((record) => record[key] === null));
|
|
4835
|
+
return nullKeys.length === keys.length ? nullKeys : [];
|
|
4836
|
+
}
|
|
4837
|
+
function carriesOnlyNulls(value) {
|
|
4838
|
+
if (value === null)
|
|
4839
|
+
return true;
|
|
4840
|
+
if (Array.isArray(value)) {
|
|
4841
|
+
return value.length > 0 && value.every(carriesOnlyNulls);
|
|
4842
|
+
}
|
|
4843
|
+
if (typeof value === "object" && value !== undefined) {
|
|
4844
|
+
const values = Object.values(value);
|
|
4845
|
+
return values.length > 0 && values.every(carriesOnlyNulls);
|
|
4846
|
+
}
|
|
4847
|
+
return false;
|
|
4848
|
+
}
|
|
4849
|
+
function nameList(names, cap2 = 12) {
|
|
4850
|
+
const shown = names.slice(0, cap2).map((n) => `\`${n}\``);
|
|
4851
|
+
const rest = names.length - shown.length;
|
|
4852
|
+
return shown.join(", ") + (rest > 0 ? `, and ${rest} more` : "");
|
|
4853
|
+
}
|
|
4854
|
+
function buildFilterWarning(filter, data, outcome) {
|
|
4855
|
+
const present = availableFields(data);
|
|
4856
|
+
const refs = referencedFields(filter);
|
|
4857
|
+
const unknown = refs.top.filter((name) => !present.includes(name) && !appearsBelowTopLevel(data, name));
|
|
4858
|
+
const unchecked = refs.nested.filter((name) => !present.includes(name));
|
|
4859
|
+
const count = countRecords(data);
|
|
4860
|
+
const scope = `${count} record(s)`;
|
|
4861
|
+
const isNotAField = (names) => `${nameList(names)} ${names.length === 1 ? "is not a field" : "are not fields"} on the ${scope} it read`;
|
|
4862
|
+
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" : "";
|
|
4863
|
+
const withSoundness = (base) => soundness ? `${base}, and ${soundness}` : base;
|
|
4864
|
+
let detail;
|
|
4865
|
+
let lede;
|
|
4866
|
+
if (outcome.kind === "null-elements") {
|
|
4867
|
+
lede = "returned only null values";
|
|
4868
|
+
const projected = `all ${outcome.count} of the elements it projected are null`;
|
|
4869
|
+
if (unknown.length > 0) {
|
|
4870
|
+
detail = `${projected}, because ${isNotAField(unknown)}`;
|
|
4871
|
+
} else if (unchecked.length > 0) {
|
|
4872
|
+
detail = withSoundness(projected);
|
|
4873
|
+
} else {
|
|
4874
|
+
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`;
|
|
4875
|
+
}
|
|
4876
|
+
} else if (outcome.kind === "null-rows") {
|
|
4877
|
+
lede = "returned only null values";
|
|
4878
|
+
const projected = `every value it projected is null on all ${outcome.count} row(s)`;
|
|
4879
|
+
detail = unknown.length > 0 ? `${projected}, because ${isNotAField(unknown)}` : withSoundness(projected);
|
|
4880
|
+
} else if (outcome.kind === "null-values") {
|
|
4881
|
+
lede = "returned only null values";
|
|
4882
|
+
const projected = `every key it projected (${nameList(outcome.keys)}) is null`;
|
|
4883
|
+
const sameSet = unknown.length === outcome.keys.length && outcome.keys.every((k) => unknown.includes(k));
|
|
4884
|
+
if (sameSet) {
|
|
4885
|
+
detail = `${isNotAField(outcome.keys)}, so every key it projected is null`;
|
|
4886
|
+
} else if (unknown.length > 0) {
|
|
4887
|
+
detail = `${projected}, because ${isNotAField(unknown)}`;
|
|
4888
|
+
} else {
|
|
4889
|
+
detail = withSoundness(`${projected} on all ${scope}`);
|
|
4890
|
+
}
|
|
4891
|
+
} else {
|
|
4892
|
+
lede = "returned nothing";
|
|
4893
|
+
if (unknown.length > 0) {
|
|
4894
|
+
detail = isNotAField(unknown);
|
|
4895
|
+
} else {
|
|
4896
|
+
const selection = refs.hasPredicate ? "no record matched" : "the expression resolved to no value";
|
|
4897
|
+
detail = withSoundness(`${selection} — it read ${scope}`);
|
|
4898
|
+
}
|
|
4899
|
+
}
|
|
4900
|
+
const fields = present.length > 0 ? ` Available fields: ${nameList(present)}.` : "";
|
|
4901
|
+
return `--output-filter ${JSON.stringify(filter)} ${lede}: ${detail}.${fields}`;
|
|
4902
|
+
}
|
|
4903
|
+
function appendWarning(existing, note) {
|
|
4904
|
+
return existing ? `${existing} ${note}` : note;
|
|
4905
|
+
}
|
|
4906
|
+
function applyFilter(data, filter, onWarning) {
|
|
4749
4907
|
const codec = requireJmespath();
|
|
4750
4908
|
let result;
|
|
4751
4909
|
try {
|
|
@@ -4753,9 +4911,34 @@ function applyFilter(data, filter) {
|
|
|
4753
4911
|
} catch (err) {
|
|
4754
4912
|
throw new FilterEvaluationError(filter, err);
|
|
4755
4913
|
}
|
|
4756
|
-
|
|
4914
|
+
const inputCount = countRecords(data);
|
|
4915
|
+
const warn = (outcome) => {
|
|
4916
|
+
if (inputCount === 0)
|
|
4917
|
+
return;
|
|
4918
|
+
const note = buildFilterWarning(filter, data, outcome);
|
|
4919
|
+
getOutputSink().writeErr(`[WARN] ${note}
|
|
4920
|
+
`);
|
|
4921
|
+
onWarning?.(note);
|
|
4922
|
+
};
|
|
4923
|
+
const warnIfAllNull = (records) => {
|
|
4924
|
+
const keys = alwaysNullKeys(records);
|
|
4925
|
+
if (keys.length > 0)
|
|
4926
|
+
warn({ kind: "null-values", keys });
|
|
4927
|
+
};
|
|
4928
|
+
if (result == null) {
|
|
4929
|
+
warn({ kind: "empty" });
|
|
4757
4930
|
return [];
|
|
4931
|
+
}
|
|
4758
4932
|
if (Array.isArray(result)) {
|
|
4933
|
+
if (result.length === 0) {
|
|
4934
|
+
warn({ kind: "empty" });
|
|
4935
|
+
} else if (result.every((entry) => entry === null)) {
|
|
4936
|
+
warn({ kind: "null-elements", count: result.length });
|
|
4937
|
+
} else if (result.every((entry) => Array.isArray(entry)) && carriesOnlyNulls(result)) {
|
|
4938
|
+
warn({ kind: "null-rows", count: result.length });
|
|
4939
|
+
} else {
|
|
4940
|
+
warnIfAllNull(result);
|
|
4941
|
+
}
|
|
4759
4942
|
if (result.length > 0 && typeof result[0] !== "object") {
|
|
4760
4943
|
const fieldMatch = filter.match(/\.(\w+)$/);
|
|
4761
4944
|
const key = fieldMatch ? fieldMatch[1] : "Value";
|
|
@@ -4763,10 +4946,30 @@ function applyFilter(data, filter) {
|
|
|
4763
4946
|
}
|
|
4764
4947
|
return result;
|
|
4765
4948
|
}
|
|
4766
|
-
if (typeof result === "object")
|
|
4949
|
+
if (typeof result === "object") {
|
|
4950
|
+
warnIfAllNull([result]);
|
|
4767
4951
|
return result;
|
|
4952
|
+
}
|
|
4768
4953
|
return { Value: result };
|
|
4769
4954
|
}
|
|
4955
|
+
function filterFailureData(envelope) {
|
|
4956
|
+
const filter = getOutputFilter();
|
|
4957
|
+
const data = envelope.Data;
|
|
4958
|
+
if (!filter || data == null)
|
|
4959
|
+
return;
|
|
4960
|
+
let note;
|
|
4961
|
+
const [filterError, filtered] = catchError(() => applyFilter(data, filter, (n) => {
|
|
4962
|
+
note = n;
|
|
4963
|
+
}));
|
|
4964
|
+
if (filterError) {
|
|
4965
|
+
envelope.Warning = appendWarning(envelope.Warning, `--output-filter was not applied, so Data is shown in full: ${filterError.message}`);
|
|
4966
|
+
return;
|
|
4967
|
+
}
|
|
4968
|
+
envelope.Data = filtered;
|
|
4969
|
+
if (note) {
|
|
4970
|
+
envelope.Warning = appendWarning(envelope.Warning, note);
|
|
4971
|
+
}
|
|
4972
|
+
}
|
|
4770
4973
|
function defaultErrorCodeForResult(result) {
|
|
4771
4974
|
switch (result) {
|
|
4772
4975
|
case RESULTS.AuthenticationError:
|
|
@@ -4849,8 +5052,14 @@ var OutputFormatter;
|
|
|
4849
5052
|
}
|
|
4850
5053
|
const filter = getOutputFilter();
|
|
4851
5054
|
if (filter) {
|
|
4852
|
-
|
|
5055
|
+
let note;
|
|
5056
|
+
const filtered = applyFilter(data.Data, filter, (n) => {
|
|
5057
|
+
note = n;
|
|
5058
|
+
});
|
|
4853
5059
|
data.Data = normalize ? normalizeDataKeys(filtered, verbatim, subtrees && { refs: subtrees.refs, mode: "skip" }) : filtered;
|
|
5060
|
+
if (note) {
|
|
5061
|
+
data.Warning = appendWarning(data.Warning, note);
|
|
5062
|
+
}
|
|
4854
5063
|
}
|
|
4855
5064
|
logOutput(normalizeOutputKeys(data), getOutputFormat(), options?.tableRowStyle);
|
|
4856
5065
|
}
|
|
@@ -4878,6 +5087,7 @@ var OutputFormatter;
|
|
|
4878
5087
|
delete envelope.TelemetryErrorClass;
|
|
4879
5088
|
delete envelope.TelemetryTerminalOutcome;
|
|
4880
5089
|
delete envelope.TelemetryTerminalSignal;
|
|
5090
|
+
filterFailureData(envelope);
|
|
4881
5091
|
if (!suppressTelemetry) {
|
|
4882
5092
|
telemetry.trackEvent(CommonTelemetryEvents.Error, {
|
|
4883
5093
|
result: data.Result,
|
|
@@ -4926,13 +5136,20 @@ var OutputFormatter;
|
|
|
4926
5136
|
OutputFormatter.log = log;
|
|
4927
5137
|
function formatToString(data) {
|
|
4928
5138
|
const filter = getOutputFilter();
|
|
5139
|
+
const envelope = data;
|
|
4929
5140
|
if ("Data" in data && data.Data != null) {
|
|
4930
5141
|
data.Data = normalizeDataKeys(data.Data);
|
|
4931
5142
|
if (filter) {
|
|
4932
|
-
|
|
5143
|
+
let note;
|
|
5144
|
+
data.Data = normalizeDataKeys(applyFilter(data.Data, filter, (n) => {
|
|
5145
|
+
note = n;
|
|
5146
|
+
}));
|
|
5147
|
+
if (note) {
|
|
5148
|
+
envelope.Warning = appendWarning(envelope.Warning, note);
|
|
5149
|
+
}
|
|
4933
5150
|
}
|
|
4934
5151
|
}
|
|
4935
|
-
const output = normalizeOutputKeys(
|
|
5152
|
+
const output = normalizeOutputKeys(envelope);
|
|
4936
5153
|
const lines = [];
|
|
4937
5154
|
const sink = getOutputSink();
|
|
4938
5155
|
printOutput(output, getOutputFormat(), (msg) => {
|
|
@@ -12267,4 +12484,4 @@ export {
|
|
|
12267
12484
|
registerCommands
|
|
12268
12485
|
};
|
|
12269
12486
|
|
|
12270
|
-
//# debugId=
|
|
12487
|
+
//# debugId=50DAB92527A489D464756E2164756E21
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/identity-commands",
|
|
3
3
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
4
|
-
"version": "1.202.1-preview.
|
|
4
|
+
"version": "1.202.1-preview.239",
|
|
5
5
|
"description": "Admin CLI commands for Identity Server users, groups, robot accounts, and external apps. Library composed by admin-tool, not a standalone CLI tool.",
|
|
6
6
|
"private": false,
|
|
7
7
|
"repository": {
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"dist"
|
|
27
27
|
],
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "97545a7857bdff7e6db62bbe13c6097607cf38f1"
|
|
29
29
|
}
|