@uipath/identity-commands 1.203.0-preview.233 → 1.203.0-preview.237
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
|
@@ -4991,7 +4991,165 @@ class FilterImplicitLimitError extends Error {
|
|
|
4991
4991
|
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).";
|
|
4992
4992
|
}
|
|
4993
4993
|
}
|
|
4994
|
-
function
|
|
4994
|
+
function countRecords(data) {
|
|
4995
|
+
if (Array.isArray(data))
|
|
4996
|
+
return data.length;
|
|
4997
|
+
return data == null ? 0 : 1;
|
|
4998
|
+
}
|
|
4999
|
+
function availableFields(data) {
|
|
5000
|
+
const records = Array.isArray(data) ? data : [data];
|
|
5001
|
+
const keys = new Set;
|
|
5002
|
+
for (const record of records) {
|
|
5003
|
+
if (record && typeof record === "object" && !Array.isArray(record)) {
|
|
5004
|
+
for (const key of Object.keys(record))
|
|
5005
|
+
keys.add(key);
|
|
5006
|
+
}
|
|
5007
|
+
}
|
|
5008
|
+
return [...keys];
|
|
5009
|
+
}
|
|
5010
|
+
function decodeQuotedIdentifier(whole, inner) {
|
|
5011
|
+
const [error, decoded] = catchError(() => JSON.parse(whole));
|
|
5012
|
+
if (!error && typeof decoded === "string")
|
|
5013
|
+
return decoded;
|
|
5014
|
+
return inner.replace(/\\(.)/g, "$1");
|
|
5015
|
+
}
|
|
5016
|
+
function referencedFields(filter) {
|
|
5017
|
+
const top = new Set;
|
|
5018
|
+
const nested = new Set;
|
|
5019
|
+
const withoutValueLiterals = filter.replace(/'(?:\\.|[^'\\])*'/g, " ").replace(/`(?:\\.|[^`\\])*`/g, " ");
|
|
5020
|
+
const isPathTail = (text, index) => text[index - 1] === "." && /[A-Za-z0-9_"]/.test(text[index - 2] ?? "");
|
|
5021
|
+
const quoted = [];
|
|
5022
|
+
const withoutLiterals = withoutValueLiterals.replace(/"((?:\\.|[^"\\])*)"/g, (whole, name, index) => {
|
|
5023
|
+
const isAlias = /^\s*:/.test(withoutValueLiterals.slice(index + whole.length));
|
|
5024
|
+
if (!isAlias) {
|
|
5025
|
+
quoted.push({
|
|
5026
|
+
name: decodeQuotedIdentifier(whole, name),
|
|
5027
|
+
index,
|
|
5028
|
+
tail: isPathTail(withoutValueLiterals, index)
|
|
5029
|
+
});
|
|
5030
|
+
}
|
|
5031
|
+
return `"${" ".repeat(whole.length - 2)}"`;
|
|
5032
|
+
});
|
|
5033
|
+
const descent = /[A-Za-z0-9_"]\s*[.[]/.exec(withoutLiterals);
|
|
5034
|
+
const rootEnd = descent ? descent.index + 1 : Number.POSITIVE_INFINITY;
|
|
5035
|
+
const place = (name, index, tail) => {
|
|
5036
|
+
if (tail || index >= rootEnd)
|
|
5037
|
+
nested.add(name);
|
|
5038
|
+
else
|
|
5039
|
+
top.add(name);
|
|
5040
|
+
};
|
|
5041
|
+
for (const entry of quoted)
|
|
5042
|
+
place(entry.name, entry.index, entry.tail);
|
|
5043
|
+
const identifiers = withoutLiterals.matchAll(/([A-Za-z_][A-Za-z0-9_]*)(\s*[:(])?/g);
|
|
5044
|
+
const reserved = new Set(["true", "false", "null", "and", "or", "not"]);
|
|
5045
|
+
for (const match of identifiers) {
|
|
5046
|
+
const [, name, trailing] = match;
|
|
5047
|
+
if (trailing || reserved.has(name))
|
|
5048
|
+
continue;
|
|
5049
|
+
place(name, match.index, isPathTail(withoutLiterals, match.index));
|
|
5050
|
+
}
|
|
5051
|
+
return {
|
|
5052
|
+
top: [...top],
|
|
5053
|
+
nested: [...nested].filter((name) => !top.has(name)),
|
|
5054
|
+
hasPredicate: /\[\s*\?/.test(withoutValueLiterals)
|
|
5055
|
+
};
|
|
5056
|
+
}
|
|
5057
|
+
function appearsBelowTopLevel(data, name) {
|
|
5058
|
+
let budget = 2000;
|
|
5059
|
+
const visit = (value, depth) => {
|
|
5060
|
+
if (budget-- <= 0 || depth > 4)
|
|
5061
|
+
return false;
|
|
5062
|
+
if (value === null || typeof value !== "object")
|
|
5063
|
+
return false;
|
|
5064
|
+
if (Array.isArray(value))
|
|
5065
|
+
return value.some((entry) => visit(entry, depth));
|
|
5066
|
+
const record = value;
|
|
5067
|
+
if (depth > 0 && Object.hasOwn(record, name))
|
|
5068
|
+
return true;
|
|
5069
|
+
return Object.values(record).some((entry) => visit(entry, depth + 1));
|
|
5070
|
+
};
|
|
5071
|
+
return visit(data, 0);
|
|
5072
|
+
}
|
|
5073
|
+
function alwaysNullKeys(records) {
|
|
5074
|
+
const objects = records.filter((r) => r != null && typeof r === "object" && !Array.isArray(r));
|
|
5075
|
+
if (objects.length === 0 || objects.length !== records.length)
|
|
5076
|
+
return [];
|
|
5077
|
+
const keys = [...new Set(objects.flatMap((o) => Object.keys(o)))];
|
|
5078
|
+
if (keys.length === 0)
|
|
5079
|
+
return [];
|
|
5080
|
+
const nullKeys = keys.filter((key) => objects.every((record) => record[key] === null));
|
|
5081
|
+
return nullKeys.length === keys.length ? nullKeys : [];
|
|
5082
|
+
}
|
|
5083
|
+
function carriesOnlyNulls(value) {
|
|
5084
|
+
if (value === null)
|
|
5085
|
+
return true;
|
|
5086
|
+
if (Array.isArray(value)) {
|
|
5087
|
+
return value.length > 0 && value.every(carriesOnlyNulls);
|
|
5088
|
+
}
|
|
5089
|
+
if (typeof value === "object" && value !== undefined) {
|
|
5090
|
+
const values = Object.values(value);
|
|
5091
|
+
return values.length > 0 && values.every(carriesOnlyNulls);
|
|
5092
|
+
}
|
|
5093
|
+
return false;
|
|
5094
|
+
}
|
|
5095
|
+
function nameList(names, cap2 = 12) {
|
|
5096
|
+
const shown = names.slice(0, cap2).map((n) => `\`${n}\``);
|
|
5097
|
+
const rest = names.length - shown.length;
|
|
5098
|
+
return shown.join(", ") + (rest > 0 ? `, and ${rest} more` : "");
|
|
5099
|
+
}
|
|
5100
|
+
function buildFilterWarning(filter, data, outcome) {
|
|
5101
|
+
const present = availableFields(data);
|
|
5102
|
+
const refs = referencedFields(filter);
|
|
5103
|
+
const unknown = refs.top.filter((name) => !present.includes(name) && !appearsBelowTopLevel(data, name));
|
|
5104
|
+
const unchecked = refs.nested.filter((name) => !present.includes(name));
|
|
5105
|
+
const count = countRecords(data);
|
|
5106
|
+
const scope = `${count} record(s)`;
|
|
5107
|
+
const isNotAField = (names) => `${nameList(names)} ${names.length === 1 ? "is not a field" : "are not fields"} on the ${scope} it read`;
|
|
5108
|
+
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" : "";
|
|
5109
|
+
const withSoundness = (base) => soundness ? `${base}, and ${soundness}` : base;
|
|
5110
|
+
let detail;
|
|
5111
|
+
let lede;
|
|
5112
|
+
if (outcome.kind === "null-elements") {
|
|
5113
|
+
lede = "returned only null values";
|
|
5114
|
+
const projected = `all ${outcome.count} of the elements it projected are null`;
|
|
5115
|
+
if (unknown.length > 0) {
|
|
5116
|
+
detail = `${projected}, because ${isNotAField(unknown)}`;
|
|
5117
|
+
} else if (unchecked.length > 0) {
|
|
5118
|
+
detail = withSoundness(projected);
|
|
5119
|
+
} else {
|
|
5120
|
+
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`;
|
|
5121
|
+
}
|
|
5122
|
+
} else if (outcome.kind === "null-rows") {
|
|
5123
|
+
lede = "returned only null values";
|
|
5124
|
+
const projected = `every value it projected is null on all ${outcome.count} row(s)`;
|
|
5125
|
+
detail = unknown.length > 0 ? `${projected}, because ${isNotAField(unknown)}` : withSoundness(projected);
|
|
5126
|
+
} else if (outcome.kind === "null-values") {
|
|
5127
|
+
lede = "returned only null values";
|
|
5128
|
+
const projected = `every key it projected (${nameList(outcome.keys)}) is null`;
|
|
5129
|
+
const sameSet = unknown.length === outcome.keys.length && outcome.keys.every((k) => unknown.includes(k));
|
|
5130
|
+
if (sameSet) {
|
|
5131
|
+
detail = `${isNotAField(outcome.keys)}, so every key it projected is null`;
|
|
5132
|
+
} else if (unknown.length > 0) {
|
|
5133
|
+
detail = `${projected}, because ${isNotAField(unknown)}`;
|
|
5134
|
+
} else {
|
|
5135
|
+
detail = withSoundness(`${projected} on all ${scope}`);
|
|
5136
|
+
}
|
|
5137
|
+
} else {
|
|
5138
|
+
lede = "returned nothing";
|
|
5139
|
+
if (unknown.length > 0) {
|
|
5140
|
+
detail = isNotAField(unknown);
|
|
5141
|
+
} else {
|
|
5142
|
+
const selection = refs.hasPredicate ? "no record matched" : "the expression resolved to no value";
|
|
5143
|
+
detail = withSoundness(`${selection} — it read ${scope}`);
|
|
5144
|
+
}
|
|
5145
|
+
}
|
|
5146
|
+
const fields = present.length > 0 ? ` Available fields: ${nameList(present)}.` : "";
|
|
5147
|
+
return `--output-filter ${JSON.stringify(filter)} ${lede}: ${detail}.${fields}`;
|
|
5148
|
+
}
|
|
5149
|
+
function appendWarning(existing, note) {
|
|
5150
|
+
return existing ? `${existing} ${note}` : note;
|
|
5151
|
+
}
|
|
5152
|
+
function applyFilter(data, filter, onWarning) {
|
|
4995
5153
|
const codec = requireJmespath();
|
|
4996
5154
|
let result;
|
|
4997
5155
|
try {
|
|
@@ -4999,9 +5157,34 @@ function applyFilter(data, filter) {
|
|
|
4999
5157
|
} catch (err) {
|
|
5000
5158
|
throw new FilterEvaluationError(filter, err);
|
|
5001
5159
|
}
|
|
5002
|
-
|
|
5160
|
+
const inputCount = countRecords(data);
|
|
5161
|
+
const warn = (outcome) => {
|
|
5162
|
+
if (inputCount === 0)
|
|
5163
|
+
return;
|
|
5164
|
+
const note = buildFilterWarning(filter, data, outcome);
|
|
5165
|
+
getOutputSink().writeErr(`[WARN] ${note}
|
|
5166
|
+
`);
|
|
5167
|
+
onWarning?.(note);
|
|
5168
|
+
};
|
|
5169
|
+
const warnIfAllNull = (records) => {
|
|
5170
|
+
const keys = alwaysNullKeys(records);
|
|
5171
|
+
if (keys.length > 0)
|
|
5172
|
+
warn({ kind: "null-values", keys });
|
|
5173
|
+
};
|
|
5174
|
+
if (result == null) {
|
|
5175
|
+
warn({ kind: "empty" });
|
|
5003
5176
|
return [];
|
|
5177
|
+
}
|
|
5004
5178
|
if (Array.isArray(result)) {
|
|
5179
|
+
if (result.length === 0) {
|
|
5180
|
+
warn({ kind: "empty" });
|
|
5181
|
+
} else if (result.every((entry) => entry === null)) {
|
|
5182
|
+
warn({ kind: "null-elements", count: result.length });
|
|
5183
|
+
} else if (result.every((entry) => Array.isArray(entry)) && carriesOnlyNulls(result)) {
|
|
5184
|
+
warn({ kind: "null-rows", count: result.length });
|
|
5185
|
+
} else {
|
|
5186
|
+
warnIfAllNull(result);
|
|
5187
|
+
}
|
|
5005
5188
|
if (result.length > 0 && typeof result[0] !== "object") {
|
|
5006
5189
|
const fieldMatch = filter.match(/\.(\w+)$/);
|
|
5007
5190
|
const key = fieldMatch ? fieldMatch[1] : "Value";
|
|
@@ -5009,10 +5192,30 @@ function applyFilter(data, filter) {
|
|
|
5009
5192
|
}
|
|
5010
5193
|
return result;
|
|
5011
5194
|
}
|
|
5012
|
-
if (typeof result === "object")
|
|
5195
|
+
if (typeof result === "object") {
|
|
5196
|
+
warnIfAllNull([result]);
|
|
5013
5197
|
return result;
|
|
5198
|
+
}
|
|
5014
5199
|
return { Value: result };
|
|
5015
5200
|
}
|
|
5201
|
+
function filterFailureData(envelope) {
|
|
5202
|
+
const filter = getOutputFilter();
|
|
5203
|
+
const data = envelope.Data;
|
|
5204
|
+
if (!filter || data == null)
|
|
5205
|
+
return;
|
|
5206
|
+
let note;
|
|
5207
|
+
const [filterError, filtered] = catchError(() => applyFilter(data, filter, (n) => {
|
|
5208
|
+
note = n;
|
|
5209
|
+
}));
|
|
5210
|
+
if (filterError) {
|
|
5211
|
+
envelope.Warning = appendWarning(envelope.Warning, `--output-filter was not applied, so Data is shown in full: ${filterError.message}`);
|
|
5212
|
+
return;
|
|
5213
|
+
}
|
|
5214
|
+
envelope.Data = filtered;
|
|
5215
|
+
if (note) {
|
|
5216
|
+
envelope.Warning = appendWarning(envelope.Warning, note);
|
|
5217
|
+
}
|
|
5218
|
+
}
|
|
5016
5219
|
function defaultErrorCodeForResult(result) {
|
|
5017
5220
|
switch (result) {
|
|
5018
5221
|
case RESULTS.AuthenticationError:
|
|
@@ -5095,8 +5298,14 @@ var OutputFormatter;
|
|
|
5095
5298
|
}
|
|
5096
5299
|
const filter = getOutputFilter();
|
|
5097
5300
|
if (filter) {
|
|
5098
|
-
|
|
5301
|
+
let note;
|
|
5302
|
+
const filtered = applyFilter(data.Data, filter, (n) => {
|
|
5303
|
+
note = n;
|
|
5304
|
+
});
|
|
5099
5305
|
data.Data = normalize ? normalizeDataKeys(filtered, verbatim, subtrees && { refs: subtrees.refs, mode: "skip" }) : filtered;
|
|
5306
|
+
if (note) {
|
|
5307
|
+
data.Warning = appendWarning(data.Warning, note);
|
|
5308
|
+
}
|
|
5100
5309
|
}
|
|
5101
5310
|
logOutput(normalizeOutputKeys(data), getOutputFormat(), options?.tableRowStyle);
|
|
5102
5311
|
}
|
|
@@ -5124,6 +5333,7 @@ var OutputFormatter;
|
|
|
5124
5333
|
delete envelope.TelemetryErrorClass;
|
|
5125
5334
|
delete envelope.TelemetryTerminalOutcome;
|
|
5126
5335
|
delete envelope.TelemetryTerminalSignal;
|
|
5336
|
+
filterFailureData(envelope);
|
|
5127
5337
|
if (!suppressTelemetry) {
|
|
5128
5338
|
telemetry.trackEvent(CommonTelemetryEvents.Error, {
|
|
5129
5339
|
result: data.Result,
|
|
@@ -5172,13 +5382,20 @@ var OutputFormatter;
|
|
|
5172
5382
|
OutputFormatter.log = log;
|
|
5173
5383
|
function formatToString(data) {
|
|
5174
5384
|
const filter = getOutputFilter();
|
|
5385
|
+
const envelope = data;
|
|
5175
5386
|
if ("Data" in data && data.Data != null) {
|
|
5176
5387
|
data.Data = normalizeDataKeys(data.Data);
|
|
5177
5388
|
if (filter) {
|
|
5178
|
-
|
|
5389
|
+
let note;
|
|
5390
|
+
data.Data = normalizeDataKeys(applyFilter(data.Data, filter, (n) => {
|
|
5391
|
+
note = n;
|
|
5392
|
+
}));
|
|
5393
|
+
if (note) {
|
|
5394
|
+
envelope.Warning = appendWarning(envelope.Warning, note);
|
|
5395
|
+
}
|
|
5179
5396
|
}
|
|
5180
5397
|
}
|
|
5181
|
-
const output = normalizeOutputKeys(
|
|
5398
|
+
const output = normalizeOutputKeys(envelope);
|
|
5182
5399
|
const lines = [];
|
|
5183
5400
|
const sink = getOutputSink();
|
|
5184
5401
|
printOutput(output, getOutputFormat(), (msg) => {
|
|
@@ -12517,4 +12734,4 @@ export {
|
|
|
12517
12734
|
registerCommands
|
|
12518
12735
|
};
|
|
12519
12736
|
|
|
12520
|
-
//# debugId=
|
|
12737
|
+
//# debugId=4D6E377BDD80CC1064756E2164756E21
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@uipath/identity-commands",
|
|
3
3
|
"author": "UiPath",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
|
-
"version": "1.203.0-preview.
|
|
5
|
+
"version": "1.203.0-preview.237",
|
|
6
6
|
"description": "Admin CLI commands for Identity Server users, groups, robot accounts, and external apps. Library composed by admin-tool, not a standalone CLI tool.",
|
|
7
7
|
"private": false,
|
|
8
8
|
"repository": {
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
"files": [
|
|
27
27
|
"dist"
|
|
28
28
|
],
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "4ad3e17a66f2c7fb7fe1f0e3e04a5b6175a0a9a3"
|
|
30
30
|
}
|