@uipath/audit-commands 1.203.0-preview.235 → 1.203.0-preview.240
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
|
@@ -6953,7 +6953,165 @@ class FilterImplicitLimitError extends Error {
|
|
|
6953
6953
|
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).";
|
|
6954
6954
|
}
|
|
6955
6955
|
}
|
|
6956
|
-
function
|
|
6956
|
+
function countRecords(data) {
|
|
6957
|
+
if (Array.isArray(data))
|
|
6958
|
+
return data.length;
|
|
6959
|
+
return data == null ? 0 : 1;
|
|
6960
|
+
}
|
|
6961
|
+
function availableFields(data) {
|
|
6962
|
+
const records = Array.isArray(data) ? data : [data];
|
|
6963
|
+
const keys = new Set;
|
|
6964
|
+
for (const record of records) {
|
|
6965
|
+
if (record && typeof record === "object" && !Array.isArray(record)) {
|
|
6966
|
+
for (const key of Object.keys(record))
|
|
6967
|
+
keys.add(key);
|
|
6968
|
+
}
|
|
6969
|
+
}
|
|
6970
|
+
return [...keys];
|
|
6971
|
+
}
|
|
6972
|
+
function decodeQuotedIdentifier(whole, inner) {
|
|
6973
|
+
const [error, decoded] = catchError2(() => JSON.parse(whole));
|
|
6974
|
+
if (!error && typeof decoded === "string")
|
|
6975
|
+
return decoded;
|
|
6976
|
+
return inner.replace(/\\(.)/g, "$1");
|
|
6977
|
+
}
|
|
6978
|
+
function referencedFields(filter) {
|
|
6979
|
+
const top = new Set;
|
|
6980
|
+
const nested = new Set;
|
|
6981
|
+
const withoutValueLiterals = filter.replace(/'(?:\\.|[^'\\])*'/g, " ").replace(/`(?:\\.|[^`\\])*`/g, " ");
|
|
6982
|
+
const isPathTail = (text, index) => text[index - 1] === "." && /[A-Za-z0-9_"]/.test(text[index - 2] ?? "");
|
|
6983
|
+
const quoted = [];
|
|
6984
|
+
const withoutLiterals = withoutValueLiterals.replace(/"((?:\\.|[^"\\])*)"/g, (whole, name, index) => {
|
|
6985
|
+
const isAlias = /^\s*:/.test(withoutValueLiterals.slice(index + whole.length));
|
|
6986
|
+
if (!isAlias) {
|
|
6987
|
+
quoted.push({
|
|
6988
|
+
name: decodeQuotedIdentifier(whole, name),
|
|
6989
|
+
index,
|
|
6990
|
+
tail: isPathTail(withoutValueLiterals, index)
|
|
6991
|
+
});
|
|
6992
|
+
}
|
|
6993
|
+
return `"${" ".repeat(whole.length - 2)}"`;
|
|
6994
|
+
});
|
|
6995
|
+
const descent = /[A-Za-z0-9_"]\s*[.[]/.exec(withoutLiterals);
|
|
6996
|
+
const rootEnd = descent ? descent.index + 1 : Number.POSITIVE_INFINITY;
|
|
6997
|
+
const place = (name, index, tail) => {
|
|
6998
|
+
if (tail || index >= rootEnd)
|
|
6999
|
+
nested.add(name);
|
|
7000
|
+
else
|
|
7001
|
+
top.add(name);
|
|
7002
|
+
};
|
|
7003
|
+
for (const entry of quoted)
|
|
7004
|
+
place(entry.name, entry.index, entry.tail);
|
|
7005
|
+
const identifiers = withoutLiterals.matchAll(/([A-Za-z_][A-Za-z0-9_]*)(\s*[:(])?/g);
|
|
7006
|
+
const reserved = new Set(["true", "false", "null", "and", "or", "not"]);
|
|
7007
|
+
for (const match of identifiers) {
|
|
7008
|
+
const [, name, trailing] = match;
|
|
7009
|
+
if (trailing || reserved.has(name))
|
|
7010
|
+
continue;
|
|
7011
|
+
place(name, match.index, isPathTail(withoutLiterals, match.index));
|
|
7012
|
+
}
|
|
7013
|
+
return {
|
|
7014
|
+
top: [...top],
|
|
7015
|
+
nested: [...nested].filter((name) => !top.has(name)),
|
|
7016
|
+
hasPredicate: /\[\s*\?/.test(withoutValueLiterals)
|
|
7017
|
+
};
|
|
7018
|
+
}
|
|
7019
|
+
function appearsBelowTopLevel(data, name) {
|
|
7020
|
+
let budget = 2000;
|
|
7021
|
+
const visit = (value, depth) => {
|
|
7022
|
+
if (budget-- <= 0 || depth > 4)
|
|
7023
|
+
return false;
|
|
7024
|
+
if (value === null || typeof value !== "object")
|
|
7025
|
+
return false;
|
|
7026
|
+
if (Array.isArray(value))
|
|
7027
|
+
return value.some((entry) => visit(entry, depth));
|
|
7028
|
+
const record = value;
|
|
7029
|
+
if (depth > 0 && Object.hasOwn(record, name))
|
|
7030
|
+
return true;
|
|
7031
|
+
return Object.values(record).some((entry) => visit(entry, depth + 1));
|
|
7032
|
+
};
|
|
7033
|
+
return visit(data, 0);
|
|
7034
|
+
}
|
|
7035
|
+
function alwaysNullKeys(records) {
|
|
7036
|
+
const objects = records.filter((r) => r != null && typeof r === "object" && !Array.isArray(r));
|
|
7037
|
+
if (objects.length === 0 || objects.length !== records.length)
|
|
7038
|
+
return [];
|
|
7039
|
+
const keys = [...new Set(objects.flatMap((o) => Object.keys(o)))];
|
|
7040
|
+
if (keys.length === 0)
|
|
7041
|
+
return [];
|
|
7042
|
+
const nullKeys = keys.filter((key) => objects.every((record) => record[key] === null));
|
|
7043
|
+
return nullKeys.length === keys.length ? nullKeys : [];
|
|
7044
|
+
}
|
|
7045
|
+
function carriesOnlyNulls(value) {
|
|
7046
|
+
if (value === null)
|
|
7047
|
+
return true;
|
|
7048
|
+
if (Array.isArray(value)) {
|
|
7049
|
+
return value.length > 0 && value.every(carriesOnlyNulls);
|
|
7050
|
+
}
|
|
7051
|
+
if (typeof value === "object" && value !== undefined) {
|
|
7052
|
+
const values = Object.values(value);
|
|
7053
|
+
return values.length > 0 && values.every(carriesOnlyNulls);
|
|
7054
|
+
}
|
|
7055
|
+
return false;
|
|
7056
|
+
}
|
|
7057
|
+
function nameList(names, cap2 = 12) {
|
|
7058
|
+
const shown = names.slice(0, cap2).map((n) => `\`${n}\``);
|
|
7059
|
+
const rest = names.length - shown.length;
|
|
7060
|
+
return shown.join(", ") + (rest > 0 ? `, and ${rest} more` : "");
|
|
7061
|
+
}
|
|
7062
|
+
function buildFilterWarning(filter, data, outcome) {
|
|
7063
|
+
const present = availableFields(data);
|
|
7064
|
+
const refs = referencedFields(filter);
|
|
7065
|
+
const unknown = refs.top.filter((name) => !present.includes(name) && !appearsBelowTopLevel(data, name));
|
|
7066
|
+
const unchecked = refs.nested.filter((name) => !present.includes(name));
|
|
7067
|
+
const count = countRecords(data);
|
|
7068
|
+
const scope = `${count} record(s)`;
|
|
7069
|
+
const isNotAField = (names) => `${nameList(names)} ${names.length === 1 ? "is not a field" : "are not fields"} on the ${scope} it read`;
|
|
7070
|
+
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" : "";
|
|
7071
|
+
const withSoundness = (base) => soundness ? `${base}, and ${soundness}` : base;
|
|
7072
|
+
let detail;
|
|
7073
|
+
let lede;
|
|
7074
|
+
if (outcome.kind === "null-elements") {
|
|
7075
|
+
lede = "returned only null values";
|
|
7076
|
+
const projected = `all ${outcome.count} of the elements it projected are null`;
|
|
7077
|
+
if (unknown.length > 0) {
|
|
7078
|
+
detail = `${projected}, because ${isNotAField(unknown)}`;
|
|
7079
|
+
} else if (unchecked.length > 0) {
|
|
7080
|
+
detail = withSoundness(projected);
|
|
7081
|
+
} else {
|
|
7082
|
+
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`;
|
|
7083
|
+
}
|
|
7084
|
+
} else if (outcome.kind === "null-rows") {
|
|
7085
|
+
lede = "returned only null values";
|
|
7086
|
+
const projected = `every value it projected is null on all ${outcome.count} row(s)`;
|
|
7087
|
+
detail = unknown.length > 0 ? `${projected}, because ${isNotAField(unknown)}` : withSoundness(projected);
|
|
7088
|
+
} else if (outcome.kind === "null-values") {
|
|
7089
|
+
lede = "returned only null values";
|
|
7090
|
+
const projected = `every key it projected (${nameList(outcome.keys)}) is null`;
|
|
7091
|
+
const sameSet = unknown.length === outcome.keys.length && outcome.keys.every((k) => unknown.includes(k));
|
|
7092
|
+
if (sameSet) {
|
|
7093
|
+
detail = `${isNotAField(outcome.keys)}, so every key it projected is null`;
|
|
7094
|
+
} else if (unknown.length > 0) {
|
|
7095
|
+
detail = `${projected}, because ${isNotAField(unknown)}`;
|
|
7096
|
+
} else {
|
|
7097
|
+
detail = withSoundness(`${projected} on all ${scope}`);
|
|
7098
|
+
}
|
|
7099
|
+
} else {
|
|
7100
|
+
lede = "returned nothing";
|
|
7101
|
+
if (unknown.length > 0) {
|
|
7102
|
+
detail = isNotAField(unknown);
|
|
7103
|
+
} else {
|
|
7104
|
+
const selection = refs.hasPredicate ? "no record matched" : "the expression resolved to no value";
|
|
7105
|
+
detail = withSoundness(`${selection} — it read ${scope}`);
|
|
7106
|
+
}
|
|
7107
|
+
}
|
|
7108
|
+
const fields = present.length > 0 ? ` Available fields: ${nameList(present)}.` : "";
|
|
7109
|
+
return `--output-filter ${JSON.stringify(filter)} ${lede}: ${detail}.${fields}`;
|
|
7110
|
+
}
|
|
7111
|
+
function appendWarning(existing, note) {
|
|
7112
|
+
return existing ? `${existing} ${note}` : note;
|
|
7113
|
+
}
|
|
7114
|
+
function applyFilter(data, filter, onWarning) {
|
|
6957
7115
|
const codec = requireJmespath();
|
|
6958
7116
|
let result;
|
|
6959
7117
|
try {
|
|
@@ -6961,9 +7119,34 @@ function applyFilter(data, filter) {
|
|
|
6961
7119
|
} catch (err) {
|
|
6962
7120
|
throw new FilterEvaluationError(filter, err);
|
|
6963
7121
|
}
|
|
6964
|
-
|
|
7122
|
+
const inputCount = countRecords(data);
|
|
7123
|
+
const warn = (outcome) => {
|
|
7124
|
+
if (inputCount === 0)
|
|
7125
|
+
return;
|
|
7126
|
+
const note = buildFilterWarning(filter, data, outcome);
|
|
7127
|
+
getOutputSink().writeErr(`[WARN] ${note}
|
|
7128
|
+
`);
|
|
7129
|
+
onWarning?.(note);
|
|
7130
|
+
};
|
|
7131
|
+
const warnIfAllNull = (records) => {
|
|
7132
|
+
const keys = alwaysNullKeys(records);
|
|
7133
|
+
if (keys.length > 0)
|
|
7134
|
+
warn({ kind: "null-values", keys });
|
|
7135
|
+
};
|
|
7136
|
+
if (result == null) {
|
|
7137
|
+
warn({ kind: "empty" });
|
|
6965
7138
|
return [];
|
|
7139
|
+
}
|
|
6966
7140
|
if (Array.isArray(result)) {
|
|
7141
|
+
if (result.length === 0) {
|
|
7142
|
+
warn({ kind: "empty" });
|
|
7143
|
+
} else if (result.every((entry) => entry === null)) {
|
|
7144
|
+
warn({ kind: "null-elements", count: result.length });
|
|
7145
|
+
} else if (result.every((entry) => Array.isArray(entry)) && carriesOnlyNulls(result)) {
|
|
7146
|
+
warn({ kind: "null-rows", count: result.length });
|
|
7147
|
+
} else {
|
|
7148
|
+
warnIfAllNull(result);
|
|
7149
|
+
}
|
|
6967
7150
|
if (result.length > 0 && typeof result[0] !== "object") {
|
|
6968
7151
|
const fieldMatch = filter.match(/\.(\w+)$/);
|
|
6969
7152
|
const key = fieldMatch ? fieldMatch[1] : "Value";
|
|
@@ -6971,10 +7154,30 @@ function applyFilter(data, filter) {
|
|
|
6971
7154
|
}
|
|
6972
7155
|
return result;
|
|
6973
7156
|
}
|
|
6974
|
-
if (typeof result === "object")
|
|
7157
|
+
if (typeof result === "object") {
|
|
7158
|
+
warnIfAllNull([result]);
|
|
6975
7159
|
return result;
|
|
7160
|
+
}
|
|
6976
7161
|
return { Value: result };
|
|
6977
7162
|
}
|
|
7163
|
+
function filterFailureData(envelope) {
|
|
7164
|
+
const filter = getOutputFilter();
|
|
7165
|
+
const data = envelope.Data;
|
|
7166
|
+
if (!filter || data == null)
|
|
7167
|
+
return;
|
|
7168
|
+
let note;
|
|
7169
|
+
const [filterError, filtered] = catchError2(() => applyFilter(data, filter, (n) => {
|
|
7170
|
+
note = n;
|
|
7171
|
+
}));
|
|
7172
|
+
if (filterError) {
|
|
7173
|
+
envelope.Warning = appendWarning(envelope.Warning, `--output-filter was not applied, so Data is shown in full: ${filterError.message}`);
|
|
7174
|
+
return;
|
|
7175
|
+
}
|
|
7176
|
+
envelope.Data = filtered;
|
|
7177
|
+
if (note) {
|
|
7178
|
+
envelope.Warning = appendWarning(envelope.Warning, note);
|
|
7179
|
+
}
|
|
7180
|
+
}
|
|
6978
7181
|
function defaultErrorCodeForResult(result) {
|
|
6979
7182
|
switch (result) {
|
|
6980
7183
|
case RESULTS.AuthenticationError:
|
|
@@ -7057,8 +7260,14 @@ var OutputFormatter;
|
|
|
7057
7260
|
}
|
|
7058
7261
|
const filter = getOutputFilter();
|
|
7059
7262
|
if (filter) {
|
|
7060
|
-
|
|
7263
|
+
let note;
|
|
7264
|
+
const filtered = applyFilter(data.Data, filter, (n) => {
|
|
7265
|
+
note = n;
|
|
7266
|
+
});
|
|
7061
7267
|
data.Data = normalize ? normalizeDataKeys(filtered, verbatim, subtrees && { refs: subtrees.refs, mode: "skip" }) : filtered;
|
|
7268
|
+
if (note) {
|
|
7269
|
+
data.Warning = appendWarning(data.Warning, note);
|
|
7270
|
+
}
|
|
7062
7271
|
}
|
|
7063
7272
|
logOutput(normalizeOutputKeys(data), getOutputFormat(), options?.tableRowStyle);
|
|
7064
7273
|
}
|
|
@@ -7086,6 +7295,7 @@ var OutputFormatter;
|
|
|
7086
7295
|
delete envelope.TelemetryErrorClass;
|
|
7087
7296
|
delete envelope.TelemetryTerminalOutcome;
|
|
7088
7297
|
delete envelope.TelemetryTerminalSignal;
|
|
7298
|
+
filterFailureData(envelope);
|
|
7089
7299
|
if (!suppressTelemetry) {
|
|
7090
7300
|
telemetry.trackEvent(CommonTelemetryEvents.Error, {
|
|
7091
7301
|
result: data.Result,
|
|
@@ -7134,13 +7344,20 @@ var OutputFormatter;
|
|
|
7134
7344
|
OutputFormatter.log = log;
|
|
7135
7345
|
function formatToString(data) {
|
|
7136
7346
|
const filter = getOutputFilter();
|
|
7347
|
+
const envelope = data;
|
|
7137
7348
|
if ("Data" in data && data.Data != null) {
|
|
7138
7349
|
data.Data = normalizeDataKeys(data.Data);
|
|
7139
7350
|
if (filter) {
|
|
7140
|
-
|
|
7351
|
+
let note;
|
|
7352
|
+
data.Data = normalizeDataKeys(applyFilter(data.Data, filter, (n) => {
|
|
7353
|
+
note = n;
|
|
7354
|
+
}));
|
|
7355
|
+
if (note) {
|
|
7356
|
+
envelope.Warning = appendWarning(envelope.Warning, note);
|
|
7357
|
+
}
|
|
7141
7358
|
}
|
|
7142
7359
|
}
|
|
7143
|
-
const output = normalizeOutputKeys(
|
|
7360
|
+
const output = normalizeOutputKeys(envelope);
|
|
7144
7361
|
const lines = [];
|
|
7145
7362
|
const sink = getOutputSink();
|
|
7146
7363
|
printOutput(output, getOutputFormat(), (msg) => {
|
|
@@ -8914,4 +9131,4 @@ export {
|
|
|
8914
9131
|
registerCommands
|
|
8915
9132
|
};
|
|
8916
9133
|
|
|
8917
|
-
//# debugId=
|
|
9134
|
+
//# debugId=C45BBF6F908F140B64756E2164756E21
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@uipath/audit-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.240",
|
|
6
6
|
"description": "Admin CLI commands for the UiPath Audit Service — query event sources, paginate events, and export ZIPs from the long-term store. 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": "95409ea61d359dff5465afaf59cb3a5efae542af"
|
|
30
30
|
}
|