@uipath/pm-tool 1.201.0 → 1.202.0-preview.136
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-2fj08e7n.js → index-gpd94m28.js} +27 -27
- package/dist/{index-w03qc9m8.js → index-sby22td6.js} +4 -4
- package/dist/index.js +3 -6
- package/dist/{js-yaml-4ypbq2tt.js → js-yaml-88tdqrtd.js} +27 -19
- package/dist/{tool-0v6na3yp.js → tool-1de529jm.js} +9 -7
- package/dist/{tool-hmgg9vyj.js → tool-6cra7bw3.js} +2501 -716
- package/dist/tool.js +5 -8
- package/package.json +2 -2
- package/dist/browser-strategy-yccf8mtd.js +0 -99
- package/dist/node-strategy-12qfy0nv.js +0 -348
- package/dist/tool-5arsyj36.js +0 -11
- package/dist/tool-7eva0peq.js +0 -265
- package/dist/tool-9qecd4wb.js +0 -14
|
@@ -1,23 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isBrowser
|
|
3
|
-
} from "./tool-9qecd4wb.js";
|
|
4
|
-
import {
|
|
5
|
-
catchError,
|
|
6
|
-
getFileSystem
|
|
7
|
-
} from "./tool-7eva0peq.js";
|
|
8
|
-
import {
|
|
9
|
-
AUTH_FILENAME,
|
|
10
|
-
DEFAULT_BASE_URL,
|
|
11
|
-
UIPATH_HOME_DIR
|
|
12
|
-
} from "./tool-5arsyj36.js";
|
|
13
1
|
import {
|
|
14
2
|
__commonJS,
|
|
15
3
|
__require,
|
|
16
4
|
__toESM
|
|
17
|
-
} from "./tool-
|
|
5
|
+
} from "./tool-1de529jm.js";
|
|
18
6
|
|
|
19
7
|
// ../../node_modules/commander/lib/error.js
|
|
20
|
-
var require_error = __commonJS((exports)
|
|
8
|
+
var require_error = __commonJS(function(exports) {
|
|
21
9
|
class CommanderError extends Error {
|
|
22
10
|
constructor(exitCode, code, message) {
|
|
23
11
|
super(message);
|
|
@@ -41,7 +29,7 @@ var require_error = __commonJS((exports) => {
|
|
|
41
29
|
});
|
|
42
30
|
|
|
43
31
|
// ../../node_modules/commander/lib/argument.js
|
|
44
|
-
var require_argument = __commonJS((exports)
|
|
32
|
+
var require_argument = __commonJS(function(exports) {
|
|
45
33
|
var { InvalidArgumentError } = require_error();
|
|
46
34
|
|
|
47
35
|
class Argument {
|
|
@@ -121,7 +109,7 @@ var require_argument = __commonJS((exports) => {
|
|
|
121
109
|
});
|
|
122
110
|
|
|
123
111
|
// ../../node_modules/commander/lib/help.js
|
|
124
|
-
var require_help = __commonJS((exports)
|
|
112
|
+
var require_help = __commonJS(function(exports) {
|
|
125
113
|
var { humanReadableArgName } = require_argument();
|
|
126
114
|
|
|
127
115
|
class Help {
|
|
@@ -478,7 +466,7 @@ ${itemIndentStr}`);
|
|
|
478
466
|
});
|
|
479
467
|
|
|
480
468
|
// ../../node_modules/commander/lib/option.js
|
|
481
|
-
var require_option = __commonJS((exports)
|
|
469
|
+
var require_option = __commonJS(function(exports) {
|
|
482
470
|
var { InvalidArgumentError } = require_error();
|
|
483
471
|
|
|
484
472
|
class Option {
|
|
@@ -662,7 +650,7 @@ var require_option = __commonJS((exports) => {
|
|
|
662
650
|
});
|
|
663
651
|
|
|
664
652
|
// ../../node_modules/commander/lib/suggestSimilar.js
|
|
665
|
-
var require_suggestSimilar = __commonJS((exports)
|
|
653
|
+
var require_suggestSimilar = __commonJS(function(exports) {
|
|
666
654
|
var maxDistance = 3;
|
|
667
655
|
function editDistance(a, b) {
|
|
668
656
|
if (Math.abs(a.length - b.length) > maxDistance)
|
|
@@ -735,11 +723,11 @@ var require_suggestSimilar = __commonJS((exports) => {
|
|
|
735
723
|
});
|
|
736
724
|
|
|
737
725
|
// ../../node_modules/commander/lib/command.js
|
|
738
|
-
var require_command = __commonJS((exports)
|
|
726
|
+
var require_command = __commonJS(function(exports) {
|
|
739
727
|
var EventEmitter = __require("node:events").EventEmitter;
|
|
740
728
|
var childProcess = __require("node:child_process");
|
|
741
|
-
var
|
|
742
|
-
var
|
|
729
|
+
var path2 = __require("node:path");
|
|
730
|
+
var fs2 = __require("node:fs");
|
|
743
731
|
var process2 = __require("node:process");
|
|
744
732
|
var { Argument, humanReadableArgName } = require_argument();
|
|
745
733
|
var { CommanderError } = require_error();
|
|
@@ -1274,7 +1262,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1274
1262
|
this.processedArgs = [];
|
|
1275
1263
|
}
|
|
1276
1264
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
1277
|
-
if (
|
|
1265
|
+
if (fs2.existsSync(executableFile))
|
|
1278
1266
|
return;
|
|
1279
1267
|
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
1280
1268
|
const executableMissing = `'${executableFile}' does not exist
|
|
@@ -1288,12 +1276,12 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1288
1276
|
let launchWithNode = false;
|
|
1289
1277
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1290
1278
|
function findFile(baseDir, baseName) {
|
|
1291
|
-
const localBin =
|
|
1292
|
-
if (
|
|
1279
|
+
const localBin = path2.resolve(baseDir, baseName);
|
|
1280
|
+
if (fs2.existsSync(localBin))
|
|
1293
1281
|
return localBin;
|
|
1294
|
-
if (sourceExt.includes(
|
|
1282
|
+
if (sourceExt.includes(path2.extname(baseName)))
|
|
1295
1283
|
return;
|
|
1296
|
-
const foundExt = sourceExt.find((ext) =>
|
|
1284
|
+
const foundExt = sourceExt.find((ext) => fs2.existsSync(`${localBin}${ext}`));
|
|
1297
1285
|
if (foundExt)
|
|
1298
1286
|
return `${localBin}${foundExt}`;
|
|
1299
1287
|
return;
|
|
@@ -1305,23 +1293,23 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1305
1293
|
if (this._scriptPath) {
|
|
1306
1294
|
let resolvedScriptPath;
|
|
1307
1295
|
try {
|
|
1308
|
-
resolvedScriptPath =
|
|
1296
|
+
resolvedScriptPath = fs2.realpathSync(this._scriptPath);
|
|
1309
1297
|
} catch {
|
|
1310
1298
|
resolvedScriptPath = this._scriptPath;
|
|
1311
1299
|
}
|
|
1312
|
-
executableDir =
|
|
1300
|
+
executableDir = path2.resolve(path2.dirname(resolvedScriptPath), executableDir);
|
|
1313
1301
|
}
|
|
1314
1302
|
if (executableDir) {
|
|
1315
1303
|
let localFile = findFile(executableDir, executableFile);
|
|
1316
1304
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
1317
|
-
const legacyName =
|
|
1305
|
+
const legacyName = path2.basename(this._scriptPath, path2.extname(this._scriptPath));
|
|
1318
1306
|
if (legacyName !== this._name) {
|
|
1319
1307
|
localFile = findFile(executableDir, `${legacyName}-${subcommand._name}`);
|
|
1320
1308
|
}
|
|
1321
1309
|
}
|
|
1322
1310
|
executableFile = localFile || executableFile;
|
|
1323
1311
|
}
|
|
1324
|
-
launchWithNode = sourceExt.includes(
|
|
1312
|
+
launchWithNode = sourceExt.includes(path2.extname(executableFile));
|
|
1325
1313
|
let proc;
|
|
1326
1314
|
if (process2.platform !== "win32") {
|
|
1327
1315
|
if (launchWithNode) {
|
|
@@ -1910,13 +1898,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1910
1898
|
cmd.helpGroup(this._defaultCommandGroup);
|
|
1911
1899
|
}
|
|
1912
1900
|
nameFromFilename(filename) {
|
|
1913
|
-
this._name =
|
|
1901
|
+
this._name = path2.basename(filename, path2.extname(filename));
|
|
1914
1902
|
return this;
|
|
1915
1903
|
}
|
|
1916
|
-
executableDir(
|
|
1917
|
-
if (
|
|
1904
|
+
executableDir(path3) {
|
|
1905
|
+
if (path3 === undefined)
|
|
1918
1906
|
return this._executableDir;
|
|
1919
|
-
this._executableDir =
|
|
1907
|
+
this._executableDir = path3;
|
|
1920
1908
|
return this;
|
|
1921
1909
|
}
|
|
1922
1910
|
helpInformation(contextOptions) {
|
|
@@ -2090,7 +2078,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2090
2078
|
});
|
|
2091
2079
|
|
|
2092
2080
|
// ../../node_modules/commander/index.js
|
|
2093
|
-
var require_commander = __commonJS((exports)
|
|
2081
|
+
var require_commander = __commonJS(function(exports) {
|
|
2094
2082
|
var { Argument } = require_argument();
|
|
2095
2083
|
var { Command } = require_command();
|
|
2096
2084
|
var { CommanderError, InvalidArgumentError } = require_error();
|
|
@@ -2112,7 +2100,7 @@ var require_commander = __commonJS((exports) => {
|
|
|
2112
2100
|
var package_default = {
|
|
2113
2101
|
name: "@uipath/pm-tool",
|
|
2114
2102
|
license: "MIT",
|
|
2115
|
-
version: "1.
|
|
2103
|
+
version: "1.202.0-preview.136",
|
|
2116
2104
|
description: "Process Mining — process apps, transformations, and data ingestion.",
|
|
2117
2105
|
private: false,
|
|
2118
2106
|
repository: {
|
|
@@ -2154,81 +2142,402 @@ var package_default = {
|
|
|
2154
2142
|
}
|
|
2155
2143
|
};
|
|
2156
2144
|
|
|
2157
|
-
// ../
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2145
|
+
// ../filesystem/src/node.ts
|
|
2146
|
+
import { randomUUID } from "node:crypto";
|
|
2147
|
+
import { existsSync } from "node:fs";
|
|
2148
|
+
import * as fs from "node:fs/promises";
|
|
2149
|
+
import * as os from "node:os";
|
|
2150
|
+
import * as path from "node:path";
|
|
2151
|
+
var LOCK_HEARTBEAT_MS = 5000;
|
|
2152
|
+
var LOCK_STALE_MS = 15000;
|
|
2153
|
+
var LOCK_MAX_WAIT_MS = 20000;
|
|
2154
|
+
var LOCK_MAX_HOLD_MS = 60000;
|
|
2155
|
+
var LOCK_RETRY_MIN_MS = 100;
|
|
2156
|
+
var LOCK_RETRY_JITTER_MS = 200;
|
|
2157
|
+
|
|
2158
|
+
class NodeFileSystem {
|
|
2159
|
+
path = {
|
|
2160
|
+
join: path.join,
|
|
2161
|
+
resolve: path.resolve,
|
|
2162
|
+
relative: path.relative,
|
|
2163
|
+
dirname: path.dirname,
|
|
2164
|
+
isAbsolute: path.isAbsolute,
|
|
2165
|
+
basename: path.basename
|
|
2166
|
+
};
|
|
2167
|
+
env = {
|
|
2168
|
+
cwd: process.cwd,
|
|
2169
|
+
homedir: os.homedir,
|
|
2170
|
+
tmpdir: os.tmpdir,
|
|
2171
|
+
getenv: (key) => process.env[key]
|
|
2172
|
+
};
|
|
2173
|
+
utils = {
|
|
2174
|
+
open: async (url) => {
|
|
2175
|
+
const { default: open } = await import("./index-sby22td6.js");
|
|
2176
|
+
await open(url);
|
|
2177
|
+
}
|
|
2178
|
+
};
|
|
2179
|
+
async readFile(path2, options) {
|
|
2180
|
+
try {
|
|
2181
|
+
if (options) {
|
|
2182
|
+
return await fs.readFile(path2, "utf-8");
|
|
2183
|
+
}
|
|
2184
|
+
return await fs.readFile(path2);
|
|
2185
|
+
} catch (error) {
|
|
2186
|
+
if (this.isEnoent(error))
|
|
2187
|
+
return null;
|
|
2188
|
+
throw error;
|
|
2189
|
+
}
|
|
2164
2190
|
}
|
|
2165
|
-
|
|
2166
|
-
const
|
|
2167
|
-
if (
|
|
2168
|
-
|
|
2191
|
+
async writeFile(filePath, data) {
|
|
2192
|
+
const dir = path.dirname(filePath);
|
|
2193
|
+
if (dir) {
|
|
2194
|
+
await fs.mkdir(dir, { recursive: true });
|
|
2169
2195
|
}
|
|
2170
|
-
|
|
2171
|
-
}
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2196
|
+
await fs.writeFile(filePath, data);
|
|
2197
|
+
}
|
|
2198
|
+
async appendFile(filePath, data) {
|
|
2199
|
+
const dir = path.dirname(filePath);
|
|
2200
|
+
if (dir) {
|
|
2201
|
+
await fs.mkdir(dir, { recursive: true });
|
|
2202
|
+
}
|
|
2203
|
+
await fs.appendFile(filePath, data);
|
|
2204
|
+
}
|
|
2205
|
+
async readdir(dirPath) {
|
|
2206
|
+
try {
|
|
2207
|
+
return await fs.readdir(dirPath);
|
|
2208
|
+
} catch (error) {
|
|
2209
|
+
if (this.isEnoent(error))
|
|
2210
|
+
return [];
|
|
2211
|
+
throw error;
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
async stat(filePath) {
|
|
2215
|
+
try {
|
|
2216
|
+
const stats = await fs.stat(filePath);
|
|
2217
|
+
return {
|
|
2218
|
+
isFile: () => stats.isFile(),
|
|
2219
|
+
isDirectory: () => stats.isDirectory(),
|
|
2220
|
+
size: stats.size,
|
|
2221
|
+
mtimeMs: stats.mtimeMs
|
|
2222
|
+
};
|
|
2223
|
+
} catch (error) {
|
|
2224
|
+
if (this.isEnoent(error))
|
|
2225
|
+
return null;
|
|
2226
|
+
throw error;
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
async exists(filePath) {
|
|
2230
|
+
return existsSync(filePath);
|
|
2231
|
+
}
|
|
2232
|
+
async mkdir(dirPath) {
|
|
2233
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
2234
|
+
}
|
|
2235
|
+
async acquireLock(lockPath) {
|
|
2236
|
+
const canonicalPath = await this.canonicalizeLockTarget(lockPath);
|
|
2237
|
+
const lockFile = `${canonicalPath}.lock`;
|
|
2238
|
+
const ownerId = randomUUID();
|
|
2239
|
+
const start = Date.now();
|
|
2240
|
+
while (true) {
|
|
2241
|
+
try {
|
|
2242
|
+
await fs.writeFile(lockFile, ownerId, { flag: "wx" });
|
|
2243
|
+
return this.createLockRelease(lockFile, ownerId);
|
|
2244
|
+
} catch (error) {
|
|
2245
|
+
if (!this.hasErrnoCode(error, "EEXIST")) {
|
|
2246
|
+
throw error;
|
|
2247
|
+
}
|
|
2248
|
+
const stats = await fs.stat(lockFile).catch(() => null);
|
|
2249
|
+
if (stats && Date.now() - stats.mtimeMs > LOCK_STALE_MS) {
|
|
2250
|
+
const reclaimed = await fs.rm(lockFile, { force: true }).then(() => true).catch(() => false);
|
|
2251
|
+
if (reclaimed)
|
|
2252
|
+
continue;
|
|
2253
|
+
}
|
|
2254
|
+
if (Date.now() - start > LOCK_MAX_WAIT_MS) {
|
|
2255
|
+
throw new Error(`ELOCKED: timed out waiting for lock on ${canonicalPath}`);
|
|
2256
|
+
}
|
|
2257
|
+
await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MIN_MS + Math.random() * LOCK_RETRY_JITTER_MS));
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
async canonicalizeLockTarget(lockPath) {
|
|
2262
|
+
const absolute = path.resolve(lockPath);
|
|
2263
|
+
const fullReal = await fs.realpath(absolute).catch(() => null);
|
|
2264
|
+
if (fullReal)
|
|
2265
|
+
return fullReal;
|
|
2266
|
+
const parent = path.dirname(absolute);
|
|
2267
|
+
const base = path.basename(absolute);
|
|
2268
|
+
const canonicalParent = await fs.realpath(parent).catch(() => parent);
|
|
2269
|
+
return path.join(canonicalParent, base);
|
|
2270
|
+
}
|
|
2271
|
+
createLockRelease(lockFile, ownerId) {
|
|
2272
|
+
const heartbeatStart = Date.now();
|
|
2273
|
+
let heartbeatTimer;
|
|
2274
|
+
let stopped = false;
|
|
2275
|
+
const stopHeartbeat = () => {
|
|
2276
|
+
stopped = true;
|
|
2277
|
+
if (heartbeatTimer)
|
|
2278
|
+
clearTimeout(heartbeatTimer);
|
|
2279
|
+
};
|
|
2280
|
+
const scheduleNextHeartbeat = () => {
|
|
2281
|
+
if (stopped)
|
|
2282
|
+
return;
|
|
2283
|
+
if (Date.now() - heartbeatStart >= LOCK_MAX_HOLD_MS) {
|
|
2284
|
+
stopped = true;
|
|
2285
|
+
return;
|
|
2286
|
+
}
|
|
2287
|
+
heartbeatTimer = setTimeout(() => {
|
|
2288
|
+
runHeartbeat();
|
|
2289
|
+
}, LOCK_HEARTBEAT_MS);
|
|
2290
|
+
heartbeatTimer.unref?.();
|
|
2291
|
+
};
|
|
2292
|
+
const runHeartbeat = async () => {
|
|
2293
|
+
if (stopped)
|
|
2294
|
+
return;
|
|
2295
|
+
const current = await fs.readFile(lockFile, "utf-8").catch(() => null);
|
|
2296
|
+
if (stopped)
|
|
2297
|
+
return;
|
|
2298
|
+
if (current !== ownerId) {
|
|
2299
|
+
stopped = true;
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2302
|
+
const now = Date.now() / 1000;
|
|
2303
|
+
await fs.utimes(lockFile, now, now).catch(() => {});
|
|
2304
|
+
scheduleNextHeartbeat();
|
|
2305
|
+
};
|
|
2306
|
+
scheduleNextHeartbeat();
|
|
2307
|
+
let released = false;
|
|
2308
|
+
return async () => {
|
|
2309
|
+
if (released)
|
|
2310
|
+
return;
|
|
2311
|
+
released = true;
|
|
2312
|
+
stopHeartbeat();
|
|
2313
|
+
const current = await fs.readFile(lockFile, "utf-8").catch(() => null);
|
|
2314
|
+
if (current === ownerId) {
|
|
2315
|
+
await fs.rm(lockFile, { force: true });
|
|
2316
|
+
}
|
|
2317
|
+
};
|
|
2318
|
+
}
|
|
2319
|
+
async rm(filePath) {
|
|
2320
|
+
await fs.rm(filePath, { recursive: true, force: true });
|
|
2321
|
+
}
|
|
2322
|
+
async rename(oldPath, newPath) {
|
|
2323
|
+
await fs.rename(oldPath, newPath);
|
|
2324
|
+
}
|
|
2325
|
+
async realpath(filePath) {
|
|
2326
|
+
try {
|
|
2327
|
+
return await fs.realpath(filePath);
|
|
2328
|
+
} catch (error) {
|
|
2329
|
+
if (this.isEnoent(error))
|
|
2330
|
+
return filePath;
|
|
2331
|
+
throw error;
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
async getTempDir() {
|
|
2335
|
+
return await fs.mkdtemp(path.join(os.tmpdir(), "uipath-fs-"));
|
|
2336
|
+
}
|
|
2337
|
+
async copyDirectory(sourcePath, destPath) {
|
|
2338
|
+
const sourceStats = await this.stat(sourcePath);
|
|
2339
|
+
if (!sourceStats) {
|
|
2340
|
+
throw new Error(`Source directory does not exist: ${sourcePath}`);
|
|
2341
|
+
}
|
|
2342
|
+
if (!sourceStats.isDirectory()) {
|
|
2343
|
+
throw new Error(`Source path is not a directory: ${sourcePath}`);
|
|
2344
|
+
}
|
|
2345
|
+
await this.mkdir(destPath);
|
|
2346
|
+
const entries = await this.readdir(sourcePath);
|
|
2347
|
+
for (const entry of entries) {
|
|
2348
|
+
const srcEntry = path.join(sourcePath, entry);
|
|
2349
|
+
const destEntry = path.join(destPath, entry);
|
|
2350
|
+
const entryStats = await this.stat(srcEntry);
|
|
2351
|
+
if (!entryStats)
|
|
2352
|
+
continue;
|
|
2353
|
+
if (entryStats.isDirectory()) {
|
|
2354
|
+
await this.copyDirectory(srcEntry, destEntry);
|
|
2355
|
+
} else if (entryStats.isFile()) {
|
|
2356
|
+
const content = await this.readFile(srcEntry);
|
|
2357
|
+
if (content !== null) {
|
|
2358
|
+
await this.writeFile(destEntry, content);
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
isEnoent(error) {
|
|
2364
|
+
return this.hasErrnoCode(error, "ENOENT");
|
|
2365
|
+
}
|
|
2366
|
+
hasErrnoCode(error, code) {
|
|
2367
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
2176
2368
|
}
|
|
2177
|
-
}
|
|
2178
|
-
function settlePromiseLike(thenable) {
|
|
2179
|
-
return Promise.resolve(thenable).then((data) => [undefined, data]).catch((error) => [
|
|
2180
|
-
error instanceof Error ? error : new Error(String(error)),
|
|
2181
|
-
undefined
|
|
2182
|
-
]);
|
|
2183
2369
|
}
|
|
2184
2370
|
|
|
2185
|
-
// ../
|
|
2186
|
-
var
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2371
|
+
// ../filesystem/src/index.ts
|
|
2372
|
+
var fsInstance = new NodeFileSystem;
|
|
2373
|
+
var getFileSystem = () => fsInstance;
|
|
2374
|
+
|
|
2375
|
+
// ../common/src/telemetry/pseudonymize.ts
|
|
2376
|
+
var PSEUDONYM_DOMAIN = "uipath-cli/telemetry/pseudonym/v1:";
|
|
2377
|
+
var PSEUDONYM_HEX_LENGTH = 32;
|
|
2378
|
+
var SHA256_K = new Uint32Array([
|
|
2379
|
+
1116352408,
|
|
2380
|
+
1899447441,
|
|
2381
|
+
3049323471,
|
|
2382
|
+
3921009573,
|
|
2383
|
+
961987163,
|
|
2384
|
+
1508970993,
|
|
2385
|
+
2453635748,
|
|
2386
|
+
2870763221,
|
|
2387
|
+
3624381080,
|
|
2388
|
+
310598401,
|
|
2389
|
+
607225278,
|
|
2390
|
+
1426881987,
|
|
2391
|
+
1925078388,
|
|
2392
|
+
2162078206,
|
|
2393
|
+
2614888103,
|
|
2394
|
+
3248222580,
|
|
2395
|
+
3835390401,
|
|
2396
|
+
4022224774,
|
|
2397
|
+
264347078,
|
|
2398
|
+
604807628,
|
|
2399
|
+
770255983,
|
|
2400
|
+
1249150122,
|
|
2401
|
+
1555081692,
|
|
2402
|
+
1996064986,
|
|
2403
|
+
2554220882,
|
|
2404
|
+
2821834349,
|
|
2405
|
+
2952996808,
|
|
2406
|
+
3210313671,
|
|
2407
|
+
3336571891,
|
|
2408
|
+
3584528711,
|
|
2409
|
+
113926993,
|
|
2410
|
+
338241895,
|
|
2411
|
+
666307205,
|
|
2412
|
+
773529912,
|
|
2413
|
+
1294757372,
|
|
2414
|
+
1396182291,
|
|
2415
|
+
1695183700,
|
|
2416
|
+
1986661051,
|
|
2417
|
+
2177026350,
|
|
2418
|
+
2456956037,
|
|
2419
|
+
2730485921,
|
|
2420
|
+
2820302411,
|
|
2421
|
+
3259730800,
|
|
2422
|
+
3345764771,
|
|
2423
|
+
3516065817,
|
|
2424
|
+
3600352804,
|
|
2425
|
+
4094571909,
|
|
2426
|
+
275423344,
|
|
2427
|
+
430227734,
|
|
2428
|
+
506948616,
|
|
2429
|
+
659060556,
|
|
2430
|
+
883997877,
|
|
2431
|
+
958139571,
|
|
2432
|
+
1322822218,
|
|
2433
|
+
1537002063,
|
|
2434
|
+
1747873779,
|
|
2435
|
+
1955562222,
|
|
2436
|
+
2024104815,
|
|
2437
|
+
2227730452,
|
|
2438
|
+
2361852424,
|
|
2439
|
+
2428436474,
|
|
2440
|
+
2756734187,
|
|
2441
|
+
3204031479,
|
|
2442
|
+
3329325298
|
|
2196
2443
|
]);
|
|
2197
|
-
var
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2444
|
+
var SHA256_INITIAL_STATE = new Uint32Array([
|
|
2445
|
+
1779033703,
|
|
2446
|
+
3144134277,
|
|
2447
|
+
1013904242,
|
|
2448
|
+
2773480762,
|
|
2449
|
+
1359893119,
|
|
2450
|
+
2600822924,
|
|
2451
|
+
528734635,
|
|
2452
|
+
1541459225
|
|
2206
2453
|
]);
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2454
|
+
function rotr(value, bits) {
|
|
2455
|
+
return (value >>> bits | value << 32 - bits) >>> 0;
|
|
2456
|
+
}
|
|
2457
|
+
function sha256Hex(input) {
|
|
2458
|
+
const bytes = new TextEncoder().encode(input);
|
|
2459
|
+
const paddedLength = bytes.length + 9 + 63 >> 6 << 6;
|
|
2460
|
+
const buffer = new Uint8Array(paddedLength);
|
|
2461
|
+
buffer.set(bytes);
|
|
2462
|
+
buffer[bytes.length] = 128;
|
|
2463
|
+
const view = new DataView(buffer.buffer);
|
|
2464
|
+
const bitLength = bytes.length * 8;
|
|
2465
|
+
view.setUint32(paddedLength - 8, Math.floor(bitLength / 4294967296));
|
|
2466
|
+
view.setUint32(paddedLength - 4, bitLength >>> 0);
|
|
2467
|
+
const state = SHA256_INITIAL_STATE.slice();
|
|
2468
|
+
const schedule = new Uint32Array(64);
|
|
2469
|
+
for (let offset = 0;offset < paddedLength; offset += 64) {
|
|
2470
|
+
for (let i = 0;i < 16; i++) {
|
|
2471
|
+
schedule[i] = view.getUint32(offset + i * 4);
|
|
2472
|
+
}
|
|
2473
|
+
for (let i = 16;i < 64; i++) {
|
|
2474
|
+
const x = schedule[i - 15];
|
|
2475
|
+
const y = schedule[i - 2];
|
|
2476
|
+
const s0 = (rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3) >>> 0;
|
|
2477
|
+
const s1 = (rotr(y, 17) ^ rotr(y, 19) ^ y >>> 10) >>> 0;
|
|
2478
|
+
schedule[i] = schedule[i - 16] + s0 + schedule[i - 7] + s1 >>> 0;
|
|
2479
|
+
}
|
|
2480
|
+
let a = state[0];
|
|
2481
|
+
let b = state[1];
|
|
2482
|
+
let c = state[2];
|
|
2483
|
+
let d = state[3];
|
|
2484
|
+
let e = state[4];
|
|
2485
|
+
let f = state[5];
|
|
2486
|
+
let g = state[6];
|
|
2487
|
+
let h = state[7];
|
|
2488
|
+
for (let i = 0;i < 64; i++) {
|
|
2489
|
+
const s1 = (rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25)) >>> 0;
|
|
2490
|
+
const ch = (e & f ^ ~e & g) >>> 0;
|
|
2491
|
+
const temp1 = h + s1 + ch + SHA256_K[i] + schedule[i] >>> 0;
|
|
2492
|
+
const s0 = (rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)) >>> 0;
|
|
2493
|
+
const maj = (a & b ^ a & c ^ b & c) >>> 0;
|
|
2494
|
+
const temp2 = s0 + maj >>> 0;
|
|
2495
|
+
h = g;
|
|
2496
|
+
g = f;
|
|
2497
|
+
f = e;
|
|
2498
|
+
e = d + temp1 >>> 0;
|
|
2499
|
+
d = c;
|
|
2500
|
+
c = b;
|
|
2501
|
+
b = a;
|
|
2502
|
+
a = temp1 + temp2 >>> 0;
|
|
2503
|
+
}
|
|
2504
|
+
state[0] = state[0] + a >>> 0;
|
|
2505
|
+
state[1] = state[1] + b >>> 0;
|
|
2506
|
+
state[2] = state[2] + c >>> 0;
|
|
2507
|
+
state[3] = state[3] + d >>> 0;
|
|
2508
|
+
state[4] = state[4] + e >>> 0;
|
|
2509
|
+
state[5] = state[5] + f >>> 0;
|
|
2510
|
+
state[6] = state[6] + g >>> 0;
|
|
2511
|
+
state[7] = state[7] + h >>> 0;
|
|
2512
|
+
}
|
|
2513
|
+
let hex = "";
|
|
2514
|
+
for (const word of state) {
|
|
2515
|
+
hex += word.toString(16).padStart(8, "0");
|
|
2516
|
+
}
|
|
2517
|
+
return hex;
|
|
2518
|
+
}
|
|
2519
|
+
function resolveSha256Hex() {
|
|
2520
|
+
try {
|
|
2521
|
+
const nodeCrypto = __require("node:crypto");
|
|
2522
|
+
const createHash = nodeCrypto?.createHash;
|
|
2523
|
+
if (typeof createHash !== "function") {
|
|
2524
|
+
return sha256Hex;
|
|
2525
|
+
}
|
|
2526
|
+
const native = (input) => createHash("sha256").update(input, "utf8").digest("hex");
|
|
2527
|
+
return native("abc") === sha256Hex("abc") ? native : sha256Hex;
|
|
2528
|
+
} catch {
|
|
2529
|
+
return sha256Hex;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
var cachedSha256Hex;
|
|
2533
|
+
function digest(input) {
|
|
2534
|
+
cachedSha256Hex ??= resolveSha256Hex();
|
|
2535
|
+
return cachedSha256Hex(input);
|
|
2536
|
+
}
|
|
2537
|
+
function pseudonymize(input) {
|
|
2538
|
+
return digest(`${PSEUDONYM_DOMAIN}${input}`).slice(0, PSEUDONYM_HEX_LENGTH);
|
|
2539
|
+
}
|
|
2225
2540
|
|
|
2226
|
-
// ../common/src/command-examples.ts
|
|
2227
|
-
var examplesByCommand = new WeakMap;
|
|
2228
|
-
Command.prototype.examples = function(examples) {
|
|
2229
|
-
examplesByCommand.set(this, examples);
|
|
2230
|
-
return this;
|
|
2231
|
-
};
|
|
2232
2541
|
// ../common/src/singleton.ts
|
|
2233
2542
|
var PREFIX = "@uipath/common/";
|
|
2234
2543
|
var _g = globalThis;
|
|
@@ -2259,66 +2568,422 @@ function singleton(ctorOrName) {
|
|
|
2259
2568
|
};
|
|
2260
2569
|
}
|
|
2261
2570
|
|
|
2262
|
-
// ../common/src/
|
|
2263
|
-
var
|
|
2264
|
-
function
|
|
2265
|
-
|
|
2571
|
+
// ../common/src/telemetry/supplied-values.ts
|
|
2572
|
+
var suppliedValuesSlot = singleton("TelemetrySuppliedArgumentValues");
|
|
2573
|
+
function activeEntries() {
|
|
2574
|
+
const existing = suppliedValuesSlot.get();
|
|
2575
|
+
return Array.isArray(existing) ? existing : [];
|
|
2576
|
+
}
|
|
2577
|
+
var MIN_SCRUBBABLE_LENGTH = 4;
|
|
2578
|
+
function recordSuppliedArgumentValues(values) {
|
|
2579
|
+
const flat = [];
|
|
2580
|
+
const push = (value) => {
|
|
2581
|
+
if (Array.isArray(value)) {
|
|
2582
|
+
for (const item of value) {
|
|
2583
|
+
push(item);
|
|
2584
|
+
}
|
|
2585
|
+
return;
|
|
2586
|
+
}
|
|
2587
|
+
if (typeof value === "string" && value.length >= MIN_SCRUBBABLE_LENGTH) {
|
|
2588
|
+
flat.push(value);
|
|
2589
|
+
}
|
|
2590
|
+
};
|
|
2591
|
+
push(values);
|
|
2592
|
+
const entry = { values: flat };
|
|
2593
|
+
suppliedValuesSlot.set([...activeEntries(), entry]);
|
|
2594
|
+
return entry;
|
|
2266
2595
|
}
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2596
|
+
function releaseSuppliedArgumentValues(entry) {
|
|
2597
|
+
suppliedValuesSlot.set(activeEntries().filter((held) => held !== entry));
|
|
2598
|
+
}
|
|
2599
|
+
function getSuppliedArgumentValues() {
|
|
2600
|
+
const all = new Set;
|
|
2601
|
+
for (const entry of activeEntries()) {
|
|
2602
|
+
for (const value of entry.values) {
|
|
2603
|
+
all.add(value);
|
|
2604
|
+
}
|
|
2270
2605
|
}
|
|
2271
|
-
return
|
|
2272
|
-
}
|
|
2606
|
+
return [...all].sort((a, b) => b.length - a.length);
|
|
2607
|
+
}
|
|
2273
2608
|
|
|
2274
|
-
// ../common/src/
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
},
|
|
2282
|
-
run: (_store, fn) => fn()
|
|
2283
|
-
};
|
|
2284
|
-
}
|
|
2285
|
-
return new mod.AsyncLocalStorage;
|
|
2609
|
+
// ../common/src/telemetry/pii-redactor.ts
|
|
2610
|
+
var REDACTED = "[REDACTED]";
|
|
2611
|
+
var MAX_VALUE_LENGTH = 280;
|
|
2612
|
+
var MAX_STACK_LENGTH = 4096;
|
|
2613
|
+
var MAX_SCAN_LENGTH = MAX_STACK_LENGTH;
|
|
2614
|
+
function truncate(value, maxLength) {
|
|
2615
|
+
return value.length > maxLength ? `${value.slice(0, maxLength)}…` : value;
|
|
2286
2616
|
}
|
|
2287
|
-
var
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2617
|
+
var SENSITIVE_NAME_TOKENS = new Set([
|
|
2618
|
+
"token",
|
|
2619
|
+
"tokens",
|
|
2620
|
+
"secret",
|
|
2621
|
+
"secrets",
|
|
2622
|
+
"password",
|
|
2623
|
+
"passwords",
|
|
2624
|
+
"pwd",
|
|
2625
|
+
"credential",
|
|
2626
|
+
"credentials",
|
|
2627
|
+
"auth",
|
|
2628
|
+
"authentication",
|
|
2629
|
+
"authorization",
|
|
2630
|
+
"authority",
|
|
2631
|
+
"cert",
|
|
2632
|
+
"certificate",
|
|
2633
|
+
"certificates"
|
|
2634
|
+
]);
|
|
2635
|
+
var SENSITIVE_KEY_PREFIXES = new Set([
|
|
2636
|
+
"api",
|
|
2637
|
+
"access",
|
|
2638
|
+
"client",
|
|
2639
|
+
"private",
|
|
2640
|
+
"public",
|
|
2641
|
+
"signing",
|
|
2642
|
+
"encryption",
|
|
2643
|
+
"session",
|
|
2644
|
+
"master",
|
|
2645
|
+
"shared",
|
|
2646
|
+
"root",
|
|
2647
|
+
"ssh",
|
|
2648
|
+
"rsa",
|
|
2649
|
+
"aes",
|
|
2650
|
+
"hmac",
|
|
2651
|
+
"oauth"
|
|
2652
|
+
]);
|
|
2653
|
+
var UUID_PATTERN = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi;
|
|
2654
|
+
var EMAIL_PATTERN = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
|
|
2655
|
+
var JWT_PATTERN = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;
|
|
2656
|
+
var LONG_TOKEN_PATTERN = /\b[A-Za-z0-9_-]{40,}\b/g;
|
|
2657
|
+
var PADDED_BASE64_PATTERN = /[A-Za-z0-9+/]{16,}={1,2}(?![A-Za-z0-9+/=])/g;
|
|
2658
|
+
var BASE64_WITH_PLUS_PATTERN = /[A-Za-z0-9+/]{40,}/g;
|
|
2659
|
+
var USER_HOME_PATTERN = /(?<![A-Za-z0-9._-])([/\\])(Users|home|Profiles)([/\\])([^/\\]+)/gi;
|
|
2660
|
+
var UNC_PATH_PATTERN = /(^|[\s"'<>|=,;([{])(\\\\[^\s"'<>|]+)/g;
|
|
2661
|
+
var HOST_PORT_PATTERN = /(?<![/@.\w-])(?!\d+\.\d+\.\d+\.\d+:)[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?)+:\d{1,5}\b/g;
|
|
2662
|
+
var SOURCE_FILE_EXTENSIONS = new Set([
|
|
2663
|
+
"ts",
|
|
2664
|
+
"tsx",
|
|
2665
|
+
"js",
|
|
2666
|
+
"jsx",
|
|
2667
|
+
"mjs",
|
|
2668
|
+
"cjs",
|
|
2669
|
+
"cts",
|
|
2670
|
+
"mts",
|
|
2671
|
+
"py",
|
|
2672
|
+
"cs",
|
|
2673
|
+
"java",
|
|
2674
|
+
"go",
|
|
2675
|
+
"rs",
|
|
2676
|
+
"rb",
|
|
2677
|
+
"php",
|
|
2678
|
+
"sh",
|
|
2679
|
+
"ps1",
|
|
2680
|
+
"json",
|
|
2681
|
+
"jsonc",
|
|
2682
|
+
"yaml",
|
|
2683
|
+
"yml",
|
|
2684
|
+
"xml",
|
|
2685
|
+
"xaml",
|
|
2686
|
+
"md",
|
|
2687
|
+
"txt",
|
|
2688
|
+
"log",
|
|
2689
|
+
"css",
|
|
2690
|
+
"html",
|
|
2691
|
+
"htm",
|
|
2692
|
+
"csproj",
|
|
2693
|
+
"nuspec",
|
|
2694
|
+
"sql"
|
|
2695
|
+
]);
|
|
2696
|
+
var URL_PATTERN = /\bhttps?:\/\/[^\s,;]+/gi;
|
|
2697
|
+
var QUOTED_LITERAL_MAX_SPAN = 200;
|
|
2698
|
+
var QUOTED_LITERAL_PATTERN = new RegExp([
|
|
2699
|
+
`(?<![A-Za-z0-9])'(?:[^\\
|
|
2700
|
+
]|\\.){2,${QUOTED_LITERAL_MAX_SPAN}}?'(?![A-Za-z0-9])`,
|
|
2701
|
+
`(?<![A-Za-z0-9])"(?:[^\\
|
|
2702
|
+
]|\\.){2,${QUOTED_LITERAL_MAX_SPAN}}?"(?![A-Za-z0-9])`
|
|
2703
|
+
].join("|"), "g");
|
|
2704
|
+
var JSON_BODY_PATTERN = /[{[][^{}[\]]*[:,][^{}[\]]*[\]}]/g;
|
|
2705
|
+
var COLLAPSED_BODY = "{…}";
|
|
2706
|
+
var COLLAPSED_BODY_MARKER = "\x01body\x01";
|
|
2707
|
+
var MAX_BODY_NESTING = 8;
|
|
2708
|
+
function collapseJsonBodies(text) {
|
|
2709
|
+
let out = text;
|
|
2710
|
+
for (let pass = 0;pass < MAX_BODY_NESTING; pass++) {
|
|
2711
|
+
const next = out.replace(JSON_BODY_PATTERN, COLLAPSED_BODY_MARKER);
|
|
2712
|
+
if (next === out) {
|
|
2713
|
+
break;
|
|
2714
|
+
}
|
|
2715
|
+
out = next;
|
|
2299
2716
|
}
|
|
2300
|
-
|
|
2301
|
-
function getOutputSink() {
|
|
2302
|
-
return outputStorage.getStore() ?? sinkSlot.get() ?? CONSOLE_FALLBACK;
|
|
2717
|
+
return out.split(COLLAPSED_BODY_MARKER).join(COLLAPSED_BODY);
|
|
2303
2718
|
}
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
logFilePathSlot.set(path);
|
|
2719
|
+
var TRAILING_PROSE_PUNCT = /[.,;:!?)\]}>'"]+$/;
|
|
2720
|
+
function peelTrailingPunctuation(match) {
|
|
2721
|
+
const trailing = match.match(TRAILING_PROSE_PUNCT)?.[0] ?? "";
|
|
2722
|
+
return trailing ? [match.slice(0, -trailing.length), trailing] : [match, ""];
|
|
2309
2723
|
}
|
|
2310
|
-
function
|
|
2311
|
-
|
|
2724
|
+
function redactUrl(raw) {
|
|
2725
|
+
try {
|
|
2726
|
+
const url = new URL(raw);
|
|
2727
|
+
return `${url.protocol}//${url.host}`;
|
|
2728
|
+
} catch {
|
|
2729
|
+
return `url#${pseudonymize(raw)}`;
|
|
2730
|
+
}
|
|
2312
2731
|
}
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2732
|
+
function redactValueDetectors(value, maxLength = MAX_VALUE_LENGTH) {
|
|
2733
|
+
let out = truncate(value, MAX_SCAN_LENGTH);
|
|
2734
|
+
out = out.replace(JWT_PATTERN, () => REDACTED);
|
|
2735
|
+
out = out.replace(URL_PATTERN, (match) => {
|
|
2736
|
+
const [core, trailing] = peelTrailingPunctuation(match);
|
|
2737
|
+
return `${redactUrl(core)}${trailing}`;
|
|
2738
|
+
});
|
|
2739
|
+
out = out.replace(USER_HOME_PATTERN, (_match, sep1, folder, sep2) => `${sep1}${folder}${sep2}<user>`);
|
|
2740
|
+
out = out.replace(UNC_PATH_PATTERN, (_match, before, path2) => {
|
|
2741
|
+
const [core, trailing] = peelTrailingPunctuation(path2);
|
|
2742
|
+
return `${before}unc#${pseudonymize(core)}${trailing}`;
|
|
2743
|
+
});
|
|
2744
|
+
out = out.replace(EMAIL_PATTERN, (match) => `email#${pseudonymize(match)}`);
|
|
2745
|
+
out = out.replace(UUID_PATTERN, (match) => `uuid#${pseudonymize(match)}`);
|
|
2746
|
+
out = out.replace(HOST_PORT_PATTERN, (match) => {
|
|
2747
|
+
const split = match.lastIndexOf(":");
|
|
2748
|
+
const host = match.slice(0, split);
|
|
2749
|
+
const extension = host.slice(host.lastIndexOf(".") + 1).toLowerCase();
|
|
2750
|
+
if (SOURCE_FILE_EXTENSIONS.has(extension)) {
|
|
2751
|
+
return match;
|
|
2752
|
+
}
|
|
2753
|
+
return `host#${pseudonymize(host)}:${match.slice(split + 1)}`;
|
|
2754
|
+
});
|
|
2755
|
+
out = out.replace(PADDED_BASE64_PATTERN, () => REDACTED);
|
|
2756
|
+
out = out.replace(BASE64_WITH_PLUS_PATTERN, (match) => match.includes("+") ? REDACTED : match);
|
|
2757
|
+
out = out.replace(LONG_TOKEN_PATTERN, () => REDACTED);
|
|
2758
|
+
return truncate(out, maxLength);
|
|
2759
|
+
}
|
|
2760
|
+
function redactSpanName(name) {
|
|
2761
|
+
return redactValueDetectors(truncate(name, MAX_SCAN_LENGTH).replace(QUOTED_LITERAL_PATTERN, (match) => `${match[0]}<redacted>${match[0]}`));
|
|
2762
|
+
}
|
|
2763
|
+
var HTTP_DEPENDENCY_NAME = /^([A-Z]+) (\/.*)$/s;
|
|
2764
|
+
function redactHttpDependencyName(name) {
|
|
2765
|
+
const parts = HTTP_DEPENDENCY_NAME.exec(name);
|
|
2766
|
+
if (!parts) {
|
|
2767
|
+
return redactMessage(name);
|
|
2768
|
+
}
|
|
2769
|
+
return `${parts[1]} ${redactMessage(parts[2])}`;
|
|
2770
|
+
}
|
|
2771
|
+
function redactMessage(value) {
|
|
2772
|
+
let out = collapseJsonBodies(truncate(value, MAX_SCAN_LENGTH)).replace(QUOTED_LITERAL_PATTERN, (match) => `${match[0]}<redacted>${match[0]}`);
|
|
2773
|
+
for (const supplied of getSuppliedArgumentValues()) {
|
|
2774
|
+
out = out.split(supplied).join(REDACTED);
|
|
2775
|
+
}
|
|
2776
|
+
return redactValueDetectors(out);
|
|
2777
|
+
}
|
|
2778
|
+
var MESSAGE_NAMES = new Set([
|
|
2779
|
+
"message",
|
|
2780
|
+
"errormessage",
|
|
2781
|
+
"errmessage",
|
|
2782
|
+
"error_message",
|
|
2783
|
+
"msg",
|
|
2784
|
+
"detail",
|
|
2785
|
+
"details",
|
|
2786
|
+
"reason",
|
|
2787
|
+
"instructions",
|
|
2788
|
+
"warning"
|
|
2789
|
+
]);
|
|
2790
|
+
function isFreeFormValue(name, value) {
|
|
2791
|
+
return MESSAGE_NAMES.has(name.toLowerCase()) || /['"{[]/.test(value);
|
|
2792
|
+
}
|
|
2793
|
+
function redactError(error) {
|
|
2794
|
+
const safe = new Error(redactMessage(error.message ?? ""));
|
|
2795
|
+
safe.name = error.name;
|
|
2796
|
+
safe.stack = typeof error.stack === "string" ? redactStack(error.stack) : undefined;
|
|
2797
|
+
return safe;
|
|
2798
|
+
}
|
|
2799
|
+
function redactStack(stack) {
|
|
2800
|
+
const bounded = truncate(stack, MAX_STACK_LENGTH);
|
|
2801
|
+
const firstBreak = bounded.indexOf(`
|
|
2802
|
+
`);
|
|
2803
|
+
if (firstBreak === -1) {
|
|
2804
|
+
return redactMessage(bounded);
|
|
2805
|
+
}
|
|
2806
|
+
return `${redactMessage(bounded.slice(0, firstBreak))}
|
|
2807
|
+
${redactValueDetectors(bounded.slice(firstBreak + 1), MAX_STACK_LENGTH)}`;
|
|
2808
|
+
}
|
|
2809
|
+
function nameTokens(name) {
|
|
2810
|
+
return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[\s._-]+/).map((t) => t.toLowerCase()).filter(Boolean);
|
|
2811
|
+
}
|
|
2812
|
+
function isSensitiveName(name) {
|
|
2813
|
+
const tokens = nameTokens(name);
|
|
2814
|
+
for (let i = 0;i < tokens.length; i++) {
|
|
2815
|
+
const token = tokens[i];
|
|
2816
|
+
if (SENSITIVE_NAME_TOKENS.has(token)) {
|
|
2817
|
+
return true;
|
|
2818
|
+
}
|
|
2819
|
+
if (token === "key" || token === "keys") {
|
|
2820
|
+
const prev = tokens[i - 1];
|
|
2821
|
+
if (prev && SENSITIVE_KEY_PREFIXES.has(prev)) {
|
|
2822
|
+
return true;
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
return false;
|
|
2827
|
+
}
|
|
2828
|
+
function redactProperty(name, value) {
|
|
2829
|
+
if (value === undefined || value === null) {
|
|
2830
|
+
return;
|
|
2831
|
+
}
|
|
2832
|
+
if (isSensitiveName(name)) {
|
|
2833
|
+
return REDACTED;
|
|
2834
|
+
}
|
|
2835
|
+
if (typeof value === "boolean" || typeof value === "number") {
|
|
2836
|
+
return value;
|
|
2837
|
+
}
|
|
2838
|
+
if (typeof value !== "string") {
|
|
2839
|
+
return "[OBJECT]";
|
|
2840
|
+
}
|
|
2841
|
+
return isFreeFormValue(name, value) ? redactMessage(value) : redactValueDetectors(value);
|
|
2842
|
+
}
|
|
2843
|
+
function redactProperties(properties) {
|
|
2844
|
+
const out = {};
|
|
2845
|
+
for (const [name, value] of Object.entries(properties)) {
|
|
2846
|
+
const redacted = redactProperty(name, value);
|
|
2847
|
+
if (redacted !== undefined) {
|
|
2848
|
+
out[name] = redacted;
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
return out;
|
|
2852
|
+
}
|
|
2853
|
+
|
|
2854
|
+
// ../common/src/catch-error.ts
|
|
2855
|
+
var MAX_SERIALIZED_LENGTH = 500;
|
|
2856
|
+
var TRUNCATION_SUFFIX = "…(truncated)";
|
|
2857
|
+
var REDACTED2 = "[REDACTED]";
|
|
2858
|
+
function cap(text) {
|
|
2859
|
+
return text.length > MAX_SERIALIZED_LENGTH ? `${text.slice(0, MAX_SERIALIZED_LENGTH)}${TRUNCATION_SUFFIX}` : text;
|
|
2860
|
+
}
|
|
2861
|
+
function omitSensitive(key, value) {
|
|
2862
|
+
return key.length > 0 && isSensitiveName(key) ? REDACTED2 : value;
|
|
2863
|
+
}
|
|
2864
|
+
function describeThrownValue(value) {
|
|
2865
|
+
if (typeof value !== "object" || value === null) {
|
|
2866
|
+
return String(value);
|
|
2867
|
+
}
|
|
2868
|
+
let message;
|
|
2869
|
+
try {
|
|
2870
|
+
message = value.message;
|
|
2871
|
+
} catch {
|
|
2872
|
+
message = undefined;
|
|
2873
|
+
}
|
|
2874
|
+
if (typeof message === "string" && message.length > 0) {
|
|
2875
|
+
return cap(message);
|
|
2876
|
+
}
|
|
2877
|
+
try {
|
|
2878
|
+
const json = JSON.stringify(value, omitSensitive);
|
|
2879
|
+
if (json !== undefined) {
|
|
2880
|
+
return cap(json);
|
|
2881
|
+
}
|
|
2882
|
+
} catch {}
|
|
2883
|
+
return String(value);
|
|
2884
|
+
}
|
|
2885
|
+
function toError(error) {
|
|
2886
|
+
return error instanceof Error ? error : new Error(describeThrownValue(error), { cause: error });
|
|
2887
|
+
}
|
|
2888
|
+
function isPromiseLike(value) {
|
|
2889
|
+
return value !== null && typeof value === "object" && typeof value.then === "function";
|
|
2890
|
+
}
|
|
2891
|
+
function catchError(fnOrPromise) {
|
|
2892
|
+
if (isPromiseLike(fnOrPromise)) {
|
|
2893
|
+
return settlePromiseLike(fnOrPromise);
|
|
2894
|
+
}
|
|
2895
|
+
try {
|
|
2896
|
+
const result = fnOrPromise();
|
|
2897
|
+
if (isPromiseLike(result)) {
|
|
2898
|
+
return settlePromiseLike(result);
|
|
2899
|
+
}
|
|
2900
|
+
return [undefined, result];
|
|
2901
|
+
} catch (error) {
|
|
2902
|
+
return [toError(error), undefined];
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
function settlePromiseLike(thenable) {
|
|
2906
|
+
return Promise.resolve(thenable).then((data) => [undefined, data]).catch((error) => [toError(error), undefined]);
|
|
2907
|
+
}
|
|
2908
|
+
|
|
2909
|
+
// ../common/src/error-handler.ts
|
|
2910
|
+
var NETWORK_ERROR_CODES = new Set([
|
|
2911
|
+
"ECONNREFUSED",
|
|
2912
|
+
"ECONNRESET",
|
|
2913
|
+
"ENOTFOUND",
|
|
2914
|
+
"EAI_AGAIN",
|
|
2915
|
+
"ETIMEDOUT",
|
|
2916
|
+
"EPIPE",
|
|
2917
|
+
"EHOSTUNREACH",
|
|
2918
|
+
"ENETUNREACH",
|
|
2919
|
+
"EAI_FAIL"
|
|
2920
|
+
]);
|
|
2921
|
+
var TLS_ERROR_CODES = new Set([
|
|
2922
|
+
"SELF_SIGNED_CERT_IN_CHAIN",
|
|
2923
|
+
"DEPTH_ZERO_SELF_SIGNED_CERT",
|
|
2924
|
+
"UNABLE_TO_VERIFY_LEAF_SIGNATURE",
|
|
2925
|
+
"UNABLE_TO_GET_ISSUER_CERT_LOCALLY",
|
|
2926
|
+
"UNABLE_TO_GET_ISSUER_CERT",
|
|
2927
|
+
"CERT_HAS_EXPIRED",
|
|
2928
|
+
"CERT_UNTRUSTED",
|
|
2929
|
+
"ERR_TLS_CERT_ALTNAME_INVALID"
|
|
2930
|
+
]);
|
|
2931
|
+
var TLS_INSTRUCTIONS = "The server's TLS certificate could not be verified. Most often a " + "corporate proxy/firewall re-signs HTTPS with a root CA that Node does " + "not trust — set NODE_EXTRA_CA_CERTS to that CA's PEM file (and HTTPS_PROXY " + "if you connect through a proxy). If the certificate is instead expired or " + "its hostname does not match, fix the endpoint URL or the system clock. " + "Then retry.";
|
|
2932
|
+
var NETWORK_INSTRUCTIONS = "Could not reach the UiPath service. Check your network connection and " + "VPN, confirm any HTTP_PROXY/HTTPS_PROXY/NO_PROXY settings are correct, " + "then retry.";
|
|
2933
|
+
var LOCAL_PERMISSION_ERROR_CODES = new Set(["EACCES", "EPERM", "EROFS"]);
|
|
2934
|
+
// ../common/src/exit-code.ts
|
|
2935
|
+
function setExitCode(code) {
|
|
2936
|
+
process.exitCode = code;
|
|
2937
|
+
}
|
|
2938
|
+
|
|
2939
|
+
// ../common/src/output-context.ts
|
|
2940
|
+
function createStorage() {
|
|
2941
|
+
const [error, mod] = catchError(() => __require("node:async_hooks"));
|
|
2942
|
+
if (error || typeof mod?.AsyncLocalStorage !== "function") {
|
|
2943
|
+
return {
|
|
2944
|
+
getStore: () => {
|
|
2945
|
+
return;
|
|
2946
|
+
},
|
|
2947
|
+
run: (_store, fn) => fn()
|
|
2948
|
+
};
|
|
2949
|
+
}
|
|
2950
|
+
return new mod.AsyncLocalStorage;
|
|
2951
|
+
}
|
|
2952
|
+
var storageSingleton = singleton("OutputStorage");
|
|
2953
|
+
var sinkSlot = singleton("OutputSink");
|
|
2954
|
+
var outputStorage = storageSingleton.getOrInit(createStorage, (v) => ("getStore" in v));
|
|
2955
|
+
var CONSOLE_FALLBACK = {
|
|
2956
|
+
writeOut: (str) => process.stdout.write(str),
|
|
2957
|
+
writeErr: (str) => process.stderr.write(str),
|
|
2958
|
+
writeLog: (str) => process.stdout.write(str),
|
|
2959
|
+
capabilities: {
|
|
2960
|
+
isInteractive: false,
|
|
2961
|
+
canReadInput: false,
|
|
2962
|
+
supportsColor: false,
|
|
2963
|
+
outputWidth: 80
|
|
2964
|
+
}
|
|
2965
|
+
};
|
|
2966
|
+
function getOutputSink() {
|
|
2967
|
+
return outputStorage.getStore() ?? sinkSlot.get() ?? CONSOLE_FALLBACK;
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
// ../common/src/logger.ts
|
|
2971
|
+
var logFilePathSlot = singleton("logFilePath");
|
|
2972
|
+
function setGlobalLogFilePath(path2) {
|
|
2973
|
+
logFilePathSlot.set(path2);
|
|
2974
|
+
}
|
|
2975
|
+
function getGlobalLogFilePath() {
|
|
2976
|
+
return logFilePathSlot.get("");
|
|
2977
|
+
}
|
|
2978
|
+
var DEFAULT_LOG_LEVEL = 3 /* ERROR */;
|
|
2979
|
+
|
|
2980
|
+
class SimpleLogger {
|
|
2981
|
+
__brand = "SimpleLogger";
|
|
2982
|
+
level;
|
|
2983
|
+
logFilePath;
|
|
2984
|
+
fileLoggingEnabled;
|
|
2985
|
+
pendingWrites = Promise.resolve();
|
|
2986
|
+
pendingInit = Promise.resolve();
|
|
2322
2987
|
constructor() {
|
|
2323
2988
|
this.level = SimpleLogger.resolveLevel();
|
|
2324
2989
|
this.logFilePath = "";
|
|
@@ -2342,7 +3007,7 @@ class SimpleLogger {
|
|
|
2342
3007
|
}
|
|
2343
3008
|
return DEFAULT_LOG_LEVEL;
|
|
2344
3009
|
}
|
|
2345
|
-
const [localStorageError, hasDebug] =
|
|
3010
|
+
const [localStorageError, hasDebug] = catchError(() => typeof localStorage !== "undefined" && !!localStorage.getItem("debug"));
|
|
2346
3011
|
if (!localStorageError && hasDebug) {
|
|
2347
3012
|
return 0 /* DEBUG */;
|
|
2348
3013
|
}
|
|
@@ -2373,54 +3038,49 @@ class SimpleLogger {
|
|
|
2373
3038
|
return this.fileLoggingEnabled || !!getGlobalLogFilePath();
|
|
2374
3039
|
}
|
|
2375
3040
|
writeToFile(formatted) {
|
|
2376
|
-
const
|
|
2377
|
-
if (!
|
|
3041
|
+
const path2 = this.logFilePath || getGlobalLogFilePath();
|
|
3042
|
+
if (!path2)
|
|
2378
3043
|
return;
|
|
2379
3044
|
const timestamp = new Date().toISOString();
|
|
2380
3045
|
this.pendingWrites = Promise.all([
|
|
2381
3046
|
this.pendingWrites,
|
|
2382
3047
|
this.pendingInit
|
|
2383
|
-
]).then(() => getFileSystem().appendFile(
|
|
3048
|
+
]).then(() => getFileSystem().appendFile(path2, `${timestamp} ${formatted}`).catch(() => {}));
|
|
2384
3049
|
}
|
|
2385
|
-
|
|
2386
|
-
if (this.level > 0 /* DEBUG */)
|
|
2387
|
-
return;
|
|
2388
|
-
const formatted = this.format(`[DEBUG] ${message}`, args);
|
|
3050
|
+
write(formatted) {
|
|
2389
3051
|
if (this.isFileLoggingActive()) {
|
|
2390
3052
|
this.writeToFile(formatted);
|
|
2391
3053
|
} else {
|
|
2392
3054
|
getOutputSink().writeErr(formatted);
|
|
2393
3055
|
}
|
|
2394
3056
|
}
|
|
3057
|
+
debug(message, ...args) {
|
|
3058
|
+
if (this.level > 0 /* DEBUG */)
|
|
3059
|
+
return;
|
|
3060
|
+
const formatted = this.format(`[DEBUG] ${message}`, args);
|
|
3061
|
+
this.write(formatted);
|
|
3062
|
+
}
|
|
2395
3063
|
info(message, ...args) {
|
|
2396
3064
|
if (this.level > 1 /* INFO */)
|
|
2397
3065
|
return;
|
|
2398
3066
|
const formatted = this.format(message, args);
|
|
2399
|
-
|
|
2400
|
-
this.writeToFile(formatted);
|
|
2401
|
-
} else {
|
|
2402
|
-
getOutputSink().writeErr(formatted);
|
|
2403
|
-
}
|
|
3067
|
+
this.write(formatted);
|
|
2404
3068
|
}
|
|
2405
3069
|
warn(message, ...args) {
|
|
2406
3070
|
if (this.level > 2 /* WARN */)
|
|
2407
3071
|
return;
|
|
2408
3072
|
const formatted = this.format(`[WARN] ${message}`, args);
|
|
2409
|
-
|
|
2410
|
-
this.writeToFile(formatted);
|
|
2411
|
-
} else {
|
|
2412
|
-
getOutputSink().writeErr(formatted);
|
|
2413
|
-
}
|
|
3073
|
+
this.write(formatted);
|
|
2414
3074
|
}
|
|
2415
3075
|
error(message, ...args) {
|
|
2416
3076
|
if (this.level > 3 /* ERROR */)
|
|
2417
3077
|
return;
|
|
2418
3078
|
const formatted = this.format(`[ERROR] ${message}`, args);
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
3079
|
+
this.write(formatted);
|
|
3080
|
+
}
|
|
3081
|
+
report(message) {
|
|
3082
|
+
const formatted = this.format(message, []);
|
|
3083
|
+
this.write(formatted);
|
|
2424
3084
|
}
|
|
2425
3085
|
getLevel() {
|
|
2426
3086
|
return this.level;
|
|
@@ -2435,17 +3095,17 @@ class SimpleLogger {
|
|
|
2435
3095
|
setGlobalLogFilePath("");
|
|
2436
3096
|
}
|
|
2437
3097
|
}
|
|
2438
|
-
setLogFile(
|
|
2439
|
-
this.logFilePath =
|
|
2440
|
-
setGlobalLogFilePath(
|
|
2441
|
-
if (!
|
|
3098
|
+
setLogFile(path2) {
|
|
3099
|
+
this.logFilePath = path2;
|
|
3100
|
+
setGlobalLogFilePath(path2);
|
|
3101
|
+
if (!path2)
|
|
2442
3102
|
return;
|
|
2443
3103
|
this.fileLoggingEnabled = true;
|
|
2444
|
-
const
|
|
3104
|
+
const fs2 = getFileSystem();
|
|
2445
3105
|
this.pendingInit = (async () => {
|
|
2446
|
-
const [error] = await
|
|
2447
|
-
await
|
|
2448
|
-
await
|
|
3106
|
+
const [error] = await catchError((async () => {
|
|
3107
|
+
await fs2.mkdir(fs2.path.dirname(path2));
|
|
3108
|
+
await fs2.writeFile(path2, "");
|
|
2449
3109
|
})());
|
|
2450
3110
|
if (error)
|
|
2451
3111
|
this.fileLoggingEnabled = false;
|
|
@@ -2499,12 +3159,12 @@ var jmespathSlot = singleton("JmespathCodec");
|
|
|
2499
3159
|
async function loadOutputCodecsAsync(needed) {
|
|
2500
3160
|
const loads = [];
|
|
2501
3161
|
if (needed.yaml && yamlSlot.get() === undefined) {
|
|
2502
|
-
loads.push(import("./js-yaml-
|
|
3162
|
+
loads.push(import("./js-yaml-88tdqrtd.js").then((mod) => {
|
|
2503
3163
|
yamlSlot.set(mod);
|
|
2504
3164
|
}));
|
|
2505
3165
|
}
|
|
2506
3166
|
if (needed.filter && jmespathSlot.get() === undefined) {
|
|
2507
|
-
loads.push(import("./index-
|
|
3167
|
+
loads.push(import("./index-gpd94m28.js").then((mod) => {
|
|
2508
3168
|
jmespathSlot.set(mod);
|
|
2509
3169
|
}));
|
|
2510
3170
|
}
|
|
@@ -2759,7 +3419,7 @@ function readRegistryValue(keyPath, valueName) {
|
|
|
2759
3419
|
if (process.platform !== "win32") {
|
|
2760
3420
|
return "";
|
|
2761
3421
|
}
|
|
2762
|
-
const [error, output] =
|
|
3422
|
+
const [error, output] = catchError(() => execFileSync("reg", ["query", keyPath, "/v", valueName], {
|
|
2763
3423
|
encoding: "utf-8",
|
|
2764
3424
|
stdio: ["pipe", "pipe", "pipe"]
|
|
2765
3425
|
}));
|
|
@@ -2782,27 +3442,41 @@ class LoggerTelemetryProvider {
|
|
|
2782
3442
|
...this.analyticsUniqueId ? { analyticsUniqueId: this.analyticsUniqueId } : {}
|
|
2783
3443
|
};
|
|
2784
3444
|
}
|
|
2785
|
-
async trackEvent(
|
|
2786
|
-
logger.debug(formatMessage("Event",
|
|
3445
|
+
async trackEvent({ name, properties }) {
|
|
3446
|
+
logger.debug(formatMessage("Event", name, this.enrich(properties)));
|
|
2787
3447
|
}
|
|
2788
|
-
async trackException(
|
|
3448
|
+
async trackException({
|
|
3449
|
+
error,
|
|
3450
|
+
properties
|
|
3451
|
+
}) {
|
|
2789
3452
|
logger.error(formatMessage("Exception", error.message, this.enrich({
|
|
2790
3453
|
...properties,
|
|
2791
3454
|
stack: error.stack
|
|
2792
3455
|
})));
|
|
2793
3456
|
}
|
|
2794
|
-
async trackRequest(
|
|
3457
|
+
async trackRequest({
|
|
3458
|
+
name,
|
|
3459
|
+
durationMs,
|
|
3460
|
+
success,
|
|
3461
|
+
properties
|
|
3462
|
+
}) {
|
|
2795
3463
|
logger.debug(formatMessage("Request", name, this.enrich({
|
|
2796
3464
|
...properties,
|
|
2797
|
-
duration: `${
|
|
3465
|
+
duration: `${durationMs}ms`,
|
|
2798
3466
|
success
|
|
2799
3467
|
})));
|
|
2800
3468
|
}
|
|
2801
|
-
async trackDependency(
|
|
3469
|
+
async trackDependency({
|
|
3470
|
+
name,
|
|
3471
|
+
type,
|
|
3472
|
+
durationMs,
|
|
3473
|
+
success,
|
|
3474
|
+
properties
|
|
3475
|
+
}) {
|
|
2802
3476
|
logger.debug(formatMessage("Dependency", name, this.enrich({
|
|
2803
3477
|
...properties,
|
|
2804
3478
|
type,
|
|
2805
|
-
duration: `${
|
|
3479
|
+
duration: `${durationMs}ms`,
|
|
2806
3480
|
success
|
|
2807
3481
|
})));
|
|
2808
3482
|
}
|
|
@@ -3037,165 +3711,37 @@ function resolveTelemetrySession() {
|
|
|
3037
3711
|
const declaredHandle = getConfiguredTelemetrySessionId();
|
|
3038
3712
|
const resolved = declaredHandle ? { id: declaredHandle, source: "declared" } : getInheritedSession(getProcessEnv2() ?? {}) ?? generateRandomSession();
|
|
3039
3713
|
telemetrySessionSlot.set(resolved);
|
|
3040
|
-
return resolved;
|
|
3041
|
-
}
|
|
3042
|
-
function getTelemetrySessionSource() {
|
|
3043
|
-
return resolveTelemetrySession().source;
|
|
3044
|
-
}
|
|
3045
|
-
function getTelemetryOperationId() {
|
|
3046
|
-
const existing = telemetryOperationIdSlot.get();
|
|
3047
|
-
if (existing) {
|
|
3048
|
-
return existing;
|
|
3049
|
-
}
|
|
3050
|
-
const inboundTraceId = getInboundTraceContext()?.traceId;
|
|
3051
|
-
const generated = inboundTraceId ?? crypto.randomUUID().replaceAll("-", "");
|
|
3052
|
-
telemetryOperationIdSlot.set(generated);
|
|
3053
|
-
return generated;
|
|
3054
|
-
}
|
|
3055
|
-
// ../common/src/telemetry/global-telemetry-properties.ts
|
|
3056
|
-
var telemetryPropsSlot = singleton("TelemetryDefaultProps");
|
|
3057
|
-
function getGlobalTelemetryProperties() {
|
|
3058
|
-
return telemetryPropsSlot.get();
|
|
3059
|
-
}
|
|
3060
|
-
|
|
3061
|
-
// ../common/src/telemetry/pii-redactor.ts
|
|
3062
|
-
var REDACTED = "[REDACTED]";
|
|
3063
|
-
var MAX_VALUE_LENGTH = 200;
|
|
3064
|
-
var SENSITIVE_NAME_TOKENS = new Set([
|
|
3065
|
-
"token",
|
|
3066
|
-
"tokens",
|
|
3067
|
-
"secret",
|
|
3068
|
-
"secrets",
|
|
3069
|
-
"password",
|
|
3070
|
-
"passwords",
|
|
3071
|
-
"pwd",
|
|
3072
|
-
"credential",
|
|
3073
|
-
"credentials",
|
|
3074
|
-
"auth",
|
|
3075
|
-
"authentication",
|
|
3076
|
-
"authorization",
|
|
3077
|
-
"authority",
|
|
3078
|
-
"cert",
|
|
3079
|
-
"certificate",
|
|
3080
|
-
"certificates"
|
|
3081
|
-
]);
|
|
3082
|
-
var SENSITIVE_KEY_PREFIXES = new Set([
|
|
3083
|
-
"api",
|
|
3084
|
-
"access",
|
|
3085
|
-
"client",
|
|
3086
|
-
"private",
|
|
3087
|
-
"public",
|
|
3088
|
-
"signing",
|
|
3089
|
-
"encryption",
|
|
3090
|
-
"session",
|
|
3091
|
-
"master",
|
|
3092
|
-
"shared",
|
|
3093
|
-
"root",
|
|
3094
|
-
"ssh",
|
|
3095
|
-
"rsa",
|
|
3096
|
-
"aes",
|
|
3097
|
-
"hmac",
|
|
3098
|
-
"oauth"
|
|
3099
|
-
]);
|
|
3100
|
-
var UUID_PATTERN = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi;
|
|
3101
|
-
var EMAIL_PATTERN = /\b[^\s@]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
|
|
3102
|
-
var JWT_PATTERN = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;
|
|
3103
|
-
var LONG_TOKEN_PATTERN = /\b[A-Za-z0-9_-]{40,}\b/g;
|
|
3104
|
-
var USER_HOME_PATTERN = /([/\\])(Users|home)([/\\])([^/\\]+)/gi;
|
|
3105
|
-
var URL_PATTERN = /\bhttps?:\/\/[^\s,;]+/gi;
|
|
3106
|
-
var URL_TRAILING_PUNCT = /[.,;:!?)\]}>'"]+$/;
|
|
3107
|
-
function shortHash(input) {
|
|
3108
|
-
let hash = 2166136261;
|
|
3109
|
-
for (let i = 0;i < input.length; i++) {
|
|
3110
|
-
hash ^= input.charCodeAt(i);
|
|
3111
|
-
hash = Math.imul(hash, 16777619);
|
|
3112
|
-
}
|
|
3113
|
-
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
3114
|
-
}
|
|
3115
|
-
function redactUrl(raw) {
|
|
3116
|
-
try {
|
|
3117
|
-
const url = new URL(raw);
|
|
3118
|
-
return `${url.protocol}//${url.host}`;
|
|
3119
|
-
} catch {
|
|
3120
|
-
return `url#${shortHash(raw)}`;
|
|
3121
|
-
}
|
|
3122
|
-
}
|
|
3123
|
-
function redactValueDetectors(value) {
|
|
3124
|
-
let out = value;
|
|
3125
|
-
out = out.replace(JWT_PATTERN, () => REDACTED);
|
|
3126
|
-
out = out.replace(URL_PATTERN, (match) => {
|
|
3127
|
-
const trailing = match.match(URL_TRAILING_PUNCT)?.[0] ?? "";
|
|
3128
|
-
const core = trailing ? match.slice(0, -trailing.length) : match;
|
|
3129
|
-
return `${redactUrl(core)}${trailing}`;
|
|
3130
|
-
});
|
|
3131
|
-
out = out.replace(USER_HOME_PATTERN, (_match, sep1, folder, sep2) => `${sep1}${folder}${sep2}<user>`);
|
|
3132
|
-
out = out.replace(EMAIL_PATTERN, (match) => `email#${shortHash(match)}`);
|
|
3133
|
-
out = out.replace(UUID_PATTERN, (match) => `uuid#${shortHash(match)}`);
|
|
3134
|
-
out = out.replace(LONG_TOKEN_PATTERN, () => REDACTED);
|
|
3135
|
-
if (out.length > MAX_VALUE_LENGTH) {
|
|
3136
|
-
out = `${out.slice(0, MAX_VALUE_LENGTH)}…`;
|
|
3137
|
-
}
|
|
3138
|
-
return out;
|
|
3139
|
-
}
|
|
3140
|
-
function redactValue(value) {
|
|
3141
|
-
return redactValueDetectors(value);
|
|
3142
|
-
}
|
|
3143
|
-
function redactError(error) {
|
|
3144
|
-
const safe = new Error(redactValueDetectors(error.message ?? ""));
|
|
3145
|
-
safe.name = error.name;
|
|
3146
|
-
safe.stack = typeof error.stack === "string" ? redactValueDetectors(error.stack) : undefined;
|
|
3147
|
-
return safe;
|
|
3148
|
-
}
|
|
3149
|
-
function nameTokens(name) {
|
|
3150
|
-
return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[\s._-]+/).map((t) => t.toLowerCase()).filter(Boolean);
|
|
3151
|
-
}
|
|
3152
|
-
function isSensitiveName(name) {
|
|
3153
|
-
const tokens = nameTokens(name);
|
|
3154
|
-
for (let i = 0;i < tokens.length; i++) {
|
|
3155
|
-
const token = tokens[i];
|
|
3156
|
-
if (SENSITIVE_NAME_TOKENS.has(token)) {
|
|
3157
|
-
return true;
|
|
3158
|
-
}
|
|
3159
|
-
if (token === "key" || token === "keys") {
|
|
3160
|
-
const prev = tokens[i - 1];
|
|
3161
|
-
if (prev && SENSITIVE_KEY_PREFIXES.has(prev)) {
|
|
3162
|
-
return true;
|
|
3163
|
-
}
|
|
3164
|
-
}
|
|
3165
|
-
}
|
|
3166
|
-
return false;
|
|
3167
|
-
}
|
|
3168
|
-
function redactProperty(name, value) {
|
|
3169
|
-
if (value === undefined || value === null) {
|
|
3170
|
-
return;
|
|
3171
|
-
}
|
|
3172
|
-
if (isSensitiveName(name)) {
|
|
3173
|
-
return REDACTED;
|
|
3174
|
-
}
|
|
3175
|
-
if (typeof value === "boolean" || typeof value === "number") {
|
|
3176
|
-
return value;
|
|
3177
|
-
}
|
|
3178
|
-
if (typeof value !== "string") {
|
|
3179
|
-
return "[OBJECT]";
|
|
3180
|
-
}
|
|
3181
|
-
return redactValueDetectors(value);
|
|
3714
|
+
return resolved;
|
|
3182
3715
|
}
|
|
3183
|
-
function
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3716
|
+
function getTelemetrySessionSource() {
|
|
3717
|
+
return resolveTelemetrySession().source;
|
|
3718
|
+
}
|
|
3719
|
+
function getTelemetryOperationId() {
|
|
3720
|
+
const existing = telemetryOperationIdSlot.get();
|
|
3721
|
+
if (existing) {
|
|
3722
|
+
return existing;
|
|
3190
3723
|
}
|
|
3191
|
-
|
|
3724
|
+
const inboundTraceId = getInboundTraceContext()?.traceId;
|
|
3725
|
+
const generated = inboundTraceId ?? crypto.randomUUID().replaceAll("-", "");
|
|
3726
|
+
telemetryOperationIdSlot.set(generated);
|
|
3727
|
+
return generated;
|
|
3728
|
+
}
|
|
3729
|
+
// ../common/src/telemetry/global-telemetry-properties.ts
|
|
3730
|
+
var telemetryPropsSlot = singleton("TelemetryDefaultProps");
|
|
3731
|
+
function getGlobalTelemetryProperties() {
|
|
3732
|
+
return telemetryPropsSlot.get();
|
|
3192
3733
|
}
|
|
3193
3734
|
|
|
3194
|
-
// ../common/src/telemetry/
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3735
|
+
// ../common/src/telemetry/span-clock.ts
|
|
3736
|
+
function startSpanClock() {
|
|
3737
|
+
const started = performance.now();
|
|
3738
|
+
return {
|
|
3739
|
+
startedAt: new Date(performance.timeOrigin + started),
|
|
3740
|
+
elapsedMs: () => performance.now() - started
|
|
3741
|
+
};
|
|
3742
|
+
}
|
|
3198
3743
|
|
|
3744
|
+
// ../common/src/telemetry/telemetry-service.ts
|
|
3199
3745
|
class TelemetryService {
|
|
3200
3746
|
telemetryProvider;
|
|
3201
3747
|
contextStorage;
|
|
@@ -3215,36 +3761,39 @@ class TelemetryService {
|
|
|
3215
3761
|
this.defaultProperties = properties === undefined ? undefined : { ...this.defaultProperties, ...properties };
|
|
3216
3762
|
}
|
|
3217
3763
|
trackEvent(name, properties) {
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3764
|
+
this.telemetryProvider.trackEvent({
|
|
3765
|
+
name: redactSpanName(name),
|
|
3766
|
+
properties: this.enrichProperties(properties),
|
|
3767
|
+
...this.leafCorrelation()
|
|
3768
|
+
});
|
|
3221
3769
|
}
|
|
3222
|
-
trackException(error, properties) {
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3770
|
+
trackException(error, properties, context) {
|
|
3771
|
+
this.telemetryProvider.trackException({
|
|
3772
|
+
error: redactError(error),
|
|
3773
|
+
properties: this.enrichProperties(properties),
|
|
3774
|
+
...this.leafCorrelation(context)
|
|
3775
|
+
});
|
|
3226
3776
|
}
|
|
3227
3777
|
async trackRequest(name, fn, properties) {
|
|
3228
|
-
const parentContext = this.
|
|
3778
|
+
const parentContext = this.getActiveContext();
|
|
3229
3779
|
const operationId = parentContext?.operationId ?? this.operationId ?? getTelemetryOperationId();
|
|
3230
3780
|
const parentId = parentContext ? parentContext.id : this.inboundParentIdFor(operationId);
|
|
3781
|
+
const clock = startSpanClock();
|
|
3231
3782
|
const context = {
|
|
3232
3783
|
operationId,
|
|
3233
3784
|
...parentId !== undefined ? { parentId } : {},
|
|
3234
|
-
id: this.generateId()
|
|
3785
|
+
id: this.generateId(),
|
|
3786
|
+
startedAt: clock.startedAt
|
|
3235
3787
|
};
|
|
3236
|
-
const startTime = performance.now();
|
|
3237
3788
|
try {
|
|
3238
3789
|
const result = await this.contextStorage.run(context, fn);
|
|
3239
|
-
const durationMs =
|
|
3240
|
-
|
|
3241
|
-
await this.telemetryProvider.trackRequest(name, durationMs, true, enrichedProperties);
|
|
3790
|
+
const durationMs = clock.elapsedMs();
|
|
3791
|
+
await this.telemetryProvider.trackRequest(this.spanFor(name, durationMs, true, properties, context));
|
|
3242
3792
|
return result;
|
|
3243
3793
|
} catch (error) {
|
|
3244
|
-
const durationMs =
|
|
3794
|
+
const durationMs = clock.elapsedMs();
|
|
3245
3795
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
3246
|
-
|
|
3247
|
-
await this.telemetryProvider.trackRequest(name, durationMs, false, enrichedProperties);
|
|
3796
|
+
await this.telemetryProvider.trackRequest(this.spanFor(name, durationMs, false, { ...properties, errorMessage: err.message }, context));
|
|
3248
3797
|
throw error;
|
|
3249
3798
|
}
|
|
3250
3799
|
}
|
|
@@ -3253,8 +3802,7 @@ class TelemetryService {
|
|
|
3253
3802
|
operationId: this.operationId ?? getTelemetryOperationId(),
|
|
3254
3803
|
id: this.generateId()
|
|
3255
3804
|
};
|
|
3256
|
-
|
|
3257
|
-
this.telemetryProvider.trackRequest(name, durationMs, success, enrichedProperties);
|
|
3805
|
+
this.telemetryProvider.trackRequest(this.spanFor(name, durationMs, success, properties, requestContext));
|
|
3258
3806
|
}
|
|
3259
3807
|
createRequestContext() {
|
|
3260
3808
|
const operationId = this.operationId ?? getTelemetryOperationId();
|
|
@@ -3262,7 +3810,8 @@ class TelemetryService {
|
|
|
3262
3810
|
return {
|
|
3263
3811
|
operationId,
|
|
3264
3812
|
...parentId !== undefined ? { parentId } : {},
|
|
3265
|
-
id: this.generateId()
|
|
3813
|
+
id: this.generateId(),
|
|
3814
|
+
startedAt: startSpanClock().startedAt
|
|
3266
3815
|
};
|
|
3267
3816
|
}
|
|
3268
3817
|
inboundParentIdFor(operationId) {
|
|
@@ -3273,58 +3822,84 @@ class TelemetryService {
|
|
|
3273
3822
|
return this.contextStorage.run(context, fn);
|
|
3274
3823
|
}
|
|
3275
3824
|
createDependencyContext() {
|
|
3276
|
-
const parentContext = this.
|
|
3825
|
+
const parentContext = this.getActiveContext();
|
|
3277
3826
|
if (!parentContext) {
|
|
3278
3827
|
return;
|
|
3279
3828
|
}
|
|
3280
3829
|
return {
|
|
3281
3830
|
operationId: parentContext.operationId,
|
|
3282
3831
|
parentId: parentContext.id,
|
|
3283
|
-
id: this.generateId()
|
|
3832
|
+
id: this.generateId(),
|
|
3833
|
+
startedAt: startSpanClock().startedAt
|
|
3284
3834
|
};
|
|
3285
3835
|
}
|
|
3286
3836
|
trackDependencyResult(name, type, durationMs, success, properties, context, resultCode) {
|
|
3287
|
-
|
|
3288
|
-
|
|
3837
|
+
this.telemetryProvider.trackDependency({
|
|
3838
|
+
...this.spanFor(redactHttpDependencyName(name), durationMs, success, properties, context),
|
|
3839
|
+
type,
|
|
3840
|
+
...resultCode !== undefined ? { resultCode } : {}
|
|
3841
|
+
});
|
|
3289
3842
|
}
|
|
3290
3843
|
async trackDependencyOperation(name, type, fn, properties) {
|
|
3291
|
-
const
|
|
3844
|
+
const clock = startSpanClock();
|
|
3845
|
+
const parentContext = this.getActiveContext();
|
|
3292
3846
|
const childContext = parentContext !== undefined ? {
|
|
3293
3847
|
operationId: parentContext.operationId,
|
|
3294
3848
|
parentId: parentContext.id,
|
|
3295
|
-
id: this.generateId()
|
|
3296
|
-
|
|
3297
|
-
|
|
3849
|
+
id: this.generateId(),
|
|
3850
|
+
startedAt: clock.startedAt
|
|
3851
|
+
} : {
|
|
3852
|
+
...this.createRequestContext(),
|
|
3853
|
+
startedAt: clock.startedAt
|
|
3854
|
+
};
|
|
3298
3855
|
try {
|
|
3299
3856
|
const result = await this.contextStorage.run(childContext, fn);
|
|
3300
|
-
const durationMs =
|
|
3301
|
-
|
|
3302
|
-
|
|
3857
|
+
const durationMs = clock.elapsedMs();
|
|
3858
|
+
await this.telemetryProvider.trackDependency({
|
|
3859
|
+
...this.spanFor(name, durationMs, true, properties, childContext),
|
|
3860
|
+
type
|
|
3861
|
+
});
|
|
3303
3862
|
return result;
|
|
3304
3863
|
} catch (error) {
|
|
3305
|
-
const durationMs =
|
|
3864
|
+
const durationMs = clock.elapsedMs();
|
|
3306
3865
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
3307
|
-
|
|
3308
|
-
|
|
3866
|
+
await this.telemetryProvider.trackDependency({
|
|
3867
|
+
...this.spanFor(name, durationMs, false, { ...properties, errorMessage: err.message }, childContext),
|
|
3868
|
+
type
|
|
3869
|
+
});
|
|
3309
3870
|
throw error;
|
|
3310
3871
|
}
|
|
3311
3872
|
}
|
|
3312
|
-
|
|
3873
|
+
getActiveContext() {
|
|
3313
3874
|
return this.contextStorage.getContext();
|
|
3314
3875
|
}
|
|
3315
|
-
|
|
3876
|
+
leafCorrelation(explicit) {
|
|
3877
|
+
const context = explicit ?? this.getActiveContext();
|
|
3878
|
+
return {
|
|
3879
|
+
operationId: context?.operationId ?? this.operationId ?? getTelemetryOperationId(),
|
|
3880
|
+
...context !== undefined ? { parentId: context.id } : {}
|
|
3881
|
+
};
|
|
3882
|
+
}
|
|
3883
|
+
spanFor(name, durationMs, success, properties, context) {
|
|
3884
|
+
return {
|
|
3885
|
+
name: redactSpanName(name),
|
|
3886
|
+
durationMs,
|
|
3887
|
+
success,
|
|
3888
|
+
properties: this.enrichProperties(properties),
|
|
3889
|
+
operationId: context.operationId,
|
|
3890
|
+
...context.parentId !== undefined ? { parentId: context.parentId } : {},
|
|
3891
|
+
id: context.id,
|
|
3892
|
+
...context.startedAt !== undefined ? { startedAt: context.startedAt } : {}
|
|
3893
|
+
};
|
|
3894
|
+
}
|
|
3895
|
+
enrichProperties(properties) {
|
|
3316
3896
|
const globalProperties = getGlobalTelemetryProperties();
|
|
3317
3897
|
const enriched = {
|
|
3318
3898
|
...getExecutionContextTelemetryProperties(),
|
|
3319
3899
|
...globalProperties,
|
|
3320
3900
|
...this.defaultProperties,
|
|
3321
3901
|
...redactProperties(properties ?? {}),
|
|
3322
|
-
[TELEMETRY_SESSION_SOURCE_PROPERTY]: getTelemetrySessionSource()
|
|
3323
|
-
...context ? {
|
|
3324
|
-
[TELEMETRY_OPERATION_ID_PROPERTY]: context.operationId,
|
|
3325
|
-
...context.parentId !== undefined ? { [TELEMETRY_PARENT_ID_PROPERTY]: context.parentId } : {},
|
|
3326
|
-
[TELEMETRY_SPAN_ID_PROPERTY]: context.id
|
|
3327
|
-
} : {}
|
|
3902
|
+
[TELEMETRY_SESSION_SOURCE_PROPERTY]: getTelemetrySessionSource()
|
|
3328
3903
|
};
|
|
3329
3904
|
return enriched;
|
|
3330
3905
|
}
|
|
@@ -3341,6 +3916,81 @@ class TelemetryService {
|
|
|
3341
3916
|
return hex;
|
|
3342
3917
|
}
|
|
3343
3918
|
}
|
|
3919
|
+
// ../common/src/timings.ts
|
|
3920
|
+
var TIMINGS_ENV_VAR = "UIP_TIMINGS";
|
|
3921
|
+
function createStorage2() {
|
|
3922
|
+
const [error, mod] = catchError(() => __require("node:async_hooks"));
|
|
3923
|
+
if (error || typeof mod?.AsyncLocalStorage !== "function") {
|
|
3924
|
+
return {
|
|
3925
|
+
getStore: () => {
|
|
3926
|
+
return;
|
|
3927
|
+
},
|
|
3928
|
+
run: (_store, fn) => fn()
|
|
3929
|
+
};
|
|
3930
|
+
}
|
|
3931
|
+
return new mod.AsyncLocalStorage;
|
|
3932
|
+
}
|
|
3933
|
+
var storageSlot = singleton("TimingStorage");
|
|
3934
|
+
var stateSlot = singleton("Timings");
|
|
3935
|
+
var rootStartedSlot = singleton("TimingsRootStarted");
|
|
3936
|
+
var longLivedHostSlot = singleton("TimingsLongLivedHost");
|
|
3937
|
+
var storage = storageSlot.getOrInit(createStorage2, (value) => ("getStore" in value));
|
|
3938
|
+
function newState(baseline) {
|
|
3939
|
+
return { baseline, httpMs: 0, httpCalls: 0 };
|
|
3940
|
+
}
|
|
3941
|
+
function getState() {
|
|
3942
|
+
const scoped = storage.getStore();
|
|
3943
|
+
if (scoped) {
|
|
3944
|
+
return scoped;
|
|
3945
|
+
}
|
|
3946
|
+
const pinned = livePinnedState();
|
|
3947
|
+
if (pinned !== undefined) {
|
|
3948
|
+
return pinned;
|
|
3949
|
+
}
|
|
3950
|
+
return newState(processStartIsInvocationStart() ? 0 : performance.now());
|
|
3951
|
+
}
|
|
3952
|
+
function livePinnedState() {
|
|
3953
|
+
const pinned = stateSlot.get();
|
|
3954
|
+
return pinned !== undefined && "httpCalls" in pinned && !pinned.finished ? pinned : undefined;
|
|
3955
|
+
}
|
|
3956
|
+
function processStartIsInvocationStart() {
|
|
3957
|
+
return !rootStartedSlot.get(false) && !longLivedHostSlot.get(false);
|
|
3958
|
+
}
|
|
3959
|
+
function timingsEnabled() {
|
|
3960
|
+
if (typeof process === "undefined") {
|
|
3961
|
+
return false;
|
|
3962
|
+
}
|
|
3963
|
+
const value = process.env?.[TIMINGS_ENV_VAR];
|
|
3964
|
+
if (value === undefined) {
|
|
3965
|
+
return false;
|
|
3966
|
+
}
|
|
3967
|
+
const normalized = value.trim().toLowerCase();
|
|
3968
|
+
return normalized === "1" || normalized === "true";
|
|
3969
|
+
}
|
|
3970
|
+
function recordExitCode(exitCode) {
|
|
3971
|
+
if (!timingsEnabled()) {
|
|
3972
|
+
return;
|
|
3973
|
+
}
|
|
3974
|
+
getState().exitCode = exitCode;
|
|
3975
|
+
}
|
|
3976
|
+
function invocationStartedAt() {
|
|
3977
|
+
return new Date(performance.timeOrigin + getState().baseline);
|
|
3978
|
+
}
|
|
3979
|
+
function invocationElapsedMs() {
|
|
3980
|
+
return performance.now() - getState().baseline;
|
|
3981
|
+
}
|
|
3982
|
+
function markCommandStart() {
|
|
3983
|
+
if (!timingsEnabled()) {
|
|
3984
|
+
return;
|
|
3985
|
+
}
|
|
3986
|
+
getState().commandStart = performance.now();
|
|
3987
|
+
}
|
|
3988
|
+
function recordCommandDuration(durationMs) {
|
|
3989
|
+
if (!timingsEnabled()) {
|
|
3990
|
+
return;
|
|
3991
|
+
}
|
|
3992
|
+
getState().commandMs = durationMs;
|
|
3993
|
+
}
|
|
3344
3994
|
// ../common/src/telemetry/proxy-http-agent.ts
|
|
3345
3995
|
var slot = singleton("ProxyAuthHttpsAgent");
|
|
3346
3996
|
|
|
@@ -3361,6 +4011,9 @@ function getGlobalTelemetryInstance() {
|
|
|
3361
4011
|
}
|
|
3362
4012
|
return;
|
|
3363
4013
|
}
|
|
4014
|
+
function setGlobalTelemetryInstance(instance) {
|
|
4015
|
+
telemetryInstanceSlot.set(instance);
|
|
4016
|
+
}
|
|
3364
4017
|
var _localTelemetryInstance;
|
|
3365
4018
|
function getTelemetryInstance() {
|
|
3366
4019
|
const global = getGlobalTelemetryInstance();
|
|
@@ -3368,6 +4021,7 @@ function getTelemetryInstance() {
|
|
|
3368
4021
|
return global;
|
|
3369
4022
|
if (!_localTelemetryInstance) {
|
|
3370
4023
|
_localTelemetryInstance = new TelemetryService(new LoggerTelemetryProvider, new NodeContextStorage);
|
|
4024
|
+
setGlobalTelemetryInstance(_localTelemetryInstance);
|
|
3371
4025
|
}
|
|
3372
4026
|
return _localTelemetryInstance;
|
|
3373
4027
|
}
|
|
@@ -3380,6 +4034,14 @@ var telemetry = new Proxy({}, {
|
|
|
3380
4034
|
});
|
|
3381
4035
|
|
|
3382
4036
|
// ../common/src/formatter.ts
|
|
4037
|
+
var ANSI_STYLES = {
|
|
4038
|
+
red: "\x1B[31m",
|
|
4039
|
+
dim: "\x1B[2m"
|
|
4040
|
+
};
|
|
4041
|
+
var ANSI_RESET = "\x1B[0m";
|
|
4042
|
+
function styleLine(line, style) {
|
|
4043
|
+
return style ? `${ANSI_STYLES[style]}${line}${ANSI_RESET}` : line;
|
|
4044
|
+
}
|
|
3383
4045
|
var CLI_ERROR_CODES = [
|
|
3384
4046
|
"invalid_argument",
|
|
3385
4047
|
"authentication_required",
|
|
@@ -3418,22 +4080,6 @@ var EXIT_CODES = {
|
|
|
3418
4080
|
ValidationError: 3,
|
|
3419
4081
|
TimeoutError: 4
|
|
3420
4082
|
};
|
|
3421
|
-
class SuccessOutput {
|
|
3422
|
-
Result = RESULTS.Success;
|
|
3423
|
-
Code;
|
|
3424
|
-
Data;
|
|
3425
|
-
Pagination;
|
|
3426
|
-
Instructions;
|
|
3427
|
-
Log;
|
|
3428
|
-
constructor(code, data) {
|
|
3429
|
-
this.Code = code;
|
|
3430
|
-
this.Data = data;
|
|
3431
|
-
const logPath = getLogFilePath();
|
|
3432
|
-
if (logPath) {
|
|
3433
|
-
this.Log = logPath;
|
|
3434
|
-
}
|
|
3435
|
-
}
|
|
3436
|
-
}
|
|
3437
4083
|
function escapeNonAscii(jsonText) {
|
|
3438
4084
|
return jsonText.replace(/[\u0080-\uffff]/g, (c) => {
|
|
3439
4085
|
const hex = c.charCodeAt(0).toString(16).padStart(4, "0");
|
|
@@ -3498,19 +4144,45 @@ function toPascalCaseKey(key) {
|
|
|
3498
4144
|
const lowerCamelKey = toLowerCamelCaseKey(key);
|
|
3499
4145
|
return lowerCamelKey ? lowerCamelKey.charAt(0).toUpperCase() + lowerCamelKey.slice(1) : lowerCamelKey;
|
|
3500
4146
|
}
|
|
3501
|
-
function
|
|
4147
|
+
function collectVerbatimRefs(value, into) {
|
|
4148
|
+
if (typeof value !== "object" || value === null)
|
|
4149
|
+
return;
|
|
4150
|
+
if (into.has(value))
|
|
4151
|
+
return;
|
|
4152
|
+
into.add(value);
|
|
4153
|
+
for (const nested of Array.isArray(value) ? value : Object.values(value)) {
|
|
4154
|
+
collectVerbatimRefs(nested, into);
|
|
4155
|
+
}
|
|
4156
|
+
}
|
|
4157
|
+
function toPascalCaseData(value, verbatimKeys, subtrees) {
|
|
4158
|
+
if (subtrees?.mode === "skip" && typeof value === "object" && value !== null && subtrees.refs.has(value)) {
|
|
4159
|
+
return value;
|
|
4160
|
+
}
|
|
3502
4161
|
if (Array.isArray(value))
|
|
3503
|
-
return value.map(toPascalCaseData);
|
|
4162
|
+
return value.map((entry) => toPascalCaseData(entry, verbatimKeys, subtrees));
|
|
3504
4163
|
if (!isPlainRecord(value))
|
|
3505
4164
|
return value;
|
|
3506
4165
|
const result = {};
|
|
3507
4166
|
for (const [key, nestedValue] of Object.entries(value)) {
|
|
3508
|
-
|
|
4167
|
+
const pascalKey = toPascalCaseKey(key);
|
|
4168
|
+
if (verbatimKeys?.has(pascalKey)) {
|
|
4169
|
+
result[pascalKey] = nestedValue;
|
|
4170
|
+
if (subtrees?.mode === "collect") {
|
|
4171
|
+
collectVerbatimRefs(nestedValue, subtrees.refs);
|
|
4172
|
+
}
|
|
4173
|
+
continue;
|
|
4174
|
+
}
|
|
4175
|
+
result[pascalKey] = toPascalCaseData(nestedValue, verbatimKeys, subtrees);
|
|
3509
4176
|
}
|
|
3510
4177
|
return result;
|
|
3511
4178
|
}
|
|
3512
|
-
function normalizeDataKeys(data) {
|
|
3513
|
-
return toPascalCaseData(data);
|
|
4179
|
+
function normalizeDataKeys(data, verbatimKeys, subtrees) {
|
|
4180
|
+
return toPascalCaseData(data, verbatimKeys, subtrees);
|
|
4181
|
+
}
|
|
4182
|
+
function toVerbatimKeySet(preserve) {
|
|
4183
|
+
if (!Array.isArray(preserve))
|
|
4184
|
+
return;
|
|
4185
|
+
return new Set(preserve.map(toPascalCaseKey));
|
|
3514
4186
|
}
|
|
3515
4187
|
function normalizeOutputKeys(data) {
|
|
3516
4188
|
const result = {};
|
|
@@ -3520,7 +4192,7 @@ function normalizeOutputKeys(data) {
|
|
|
3520
4192
|
}
|
|
3521
4193
|
return result;
|
|
3522
4194
|
}
|
|
3523
|
-
function printOutput(data, format = "json", logFn, asciiSafe = false) {
|
|
4195
|
+
function printOutput(data, format = "json", logFn, asciiSafe = false, tableRowStyle) {
|
|
3524
4196
|
if (!data) {
|
|
3525
4197
|
logFn("Empty response object. No data to display.");
|
|
3526
4198
|
return;
|
|
@@ -3555,7 +4227,7 @@ function printOutput(data, format = "json", logFn, asciiSafe = false) {
|
|
|
3555
4227
|
if (hasData && !(rows !== null && rows.length === 0)) {
|
|
3556
4228
|
const logValue = data.Log;
|
|
3557
4229
|
if (rows !== null) {
|
|
3558
|
-
printResizableTable(rows, logFn, logValue);
|
|
4230
|
+
printResizableTable(rows, logFn, logValue, undefined, tableRowStyle);
|
|
3559
4231
|
} else {
|
|
3560
4232
|
printVerticalTable(data.Data, logFn, logValue);
|
|
3561
4233
|
}
|
|
@@ -3566,10 +4238,11 @@ function printOutput(data, format = "json", logFn, asciiSafe = false) {
|
|
|
3566
4238
|
}
|
|
3567
4239
|
}
|
|
3568
4240
|
}
|
|
3569
|
-
function logOutput(data, format = "json") {
|
|
4241
|
+
function logOutput(data, format = "json", tableRowStyle) {
|
|
3570
4242
|
const sink = getOutputSink();
|
|
4243
|
+
const styleFn = sink.capabilities.isInteractive && sink.capabilities.supportsColor ? tableRowStyle : undefined;
|
|
3571
4244
|
printOutput(data, format, (msg) => sink.writeOut(`${msg}
|
|
3572
|
-
`), needsAsciiSafeJson(sink));
|
|
4245
|
+
`), needsAsciiSafeJson(sink), styleFn);
|
|
3573
4246
|
}
|
|
3574
4247
|
function cellToString(val) {
|
|
3575
4248
|
return val != null && typeof val === "object" ? JSON.stringify(val) : String(val ?? "");
|
|
@@ -3583,7 +4256,7 @@ function wrapText(text, width) {
|
|
|
3583
4256
|
}
|
|
3584
4257
|
return lines;
|
|
3585
4258
|
}
|
|
3586
|
-
function printTable(data, logFn, externalLogValue) {
|
|
4259
|
+
function printTable(data, logFn, externalLogValue, tableRowStyle) {
|
|
3587
4260
|
if (data.length === 0)
|
|
3588
4261
|
return;
|
|
3589
4262
|
const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
|
|
@@ -3593,7 +4266,7 @@ function printTable(data, logFn, externalLogValue) {
|
|
|
3593
4266
|
logFn(keys.map((_, i) => "-".repeat(maxWidths[i])).join("-|-"));
|
|
3594
4267
|
data.forEach((item) => {
|
|
3595
4268
|
const row = keys.map((key, i) => cellToString(item[key]).padEnd(maxWidths[i])).join(" | ");
|
|
3596
|
-
logFn(row);
|
|
4269
|
+
logFn(styleLine(row, tableRowStyle?.(item)));
|
|
3597
4270
|
});
|
|
3598
4271
|
if (externalLogValue) {
|
|
3599
4272
|
logFn("");
|
|
@@ -3636,14 +4309,14 @@ function printVerticalTable(data, logFn = console.log, externalLogValue) {
|
|
|
3636
4309
|
logFn(`Log: ${externalLogValue}`);
|
|
3637
4310
|
}
|
|
3638
4311
|
}
|
|
3639
|
-
function printResizableTable(data, logFn = console.log, externalLogValue, availableWidth) {
|
|
4312
|
+
function printResizableTable(data, logFn = console.log, externalLogValue, availableWidth, tableRowStyle) {
|
|
3640
4313
|
if (data.length === 0)
|
|
3641
4314
|
return;
|
|
3642
4315
|
const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
|
|
3643
4316
|
if (keys.length === 0)
|
|
3644
4317
|
return;
|
|
3645
4318
|
if (!process.stdout.isTTY) {
|
|
3646
|
-
printTable(data, logFn, externalLogValue);
|
|
4319
|
+
printTable(data, logFn, externalLogValue, tableRowStyle);
|
|
3647
4320
|
return;
|
|
3648
4321
|
}
|
|
3649
4322
|
const naturalWidths = keys.map((key) => Math.max(key.length, ...data.map((item) => cellToString(item[key]).length)));
|
|
@@ -3651,7 +4324,7 @@ function printResizableTable(data, logFn = console.log, externalLogValue, availa
|
|
|
3651
4324
|
const totalWidth = naturalWidths.reduce((a, b) => a + b, 0) + separatorTotal;
|
|
3652
4325
|
const termWidth = availableWidth ?? (process.stdout.columns || 120);
|
|
3653
4326
|
if (totalWidth <= termWidth) {
|
|
3654
|
-
printTable(data, logFn, externalLogValue);
|
|
4327
|
+
printTable(data, logFn, externalLogValue, tableRowStyle);
|
|
3655
4328
|
return;
|
|
3656
4329
|
}
|
|
3657
4330
|
const overflow = totalWidth - termWidth;
|
|
@@ -3697,6 +4370,7 @@ function printResizableTable(data, logFn = console.log, externalLogValue, availa
|
|
|
3697
4370
|
logFn(header);
|
|
3698
4371
|
logFn(keys.map((_, i) => "-".repeat(finalWidths[i])).join("-|-"));
|
|
3699
4372
|
data.forEach((item) => {
|
|
4373
|
+
const style = tableRowStyle?.(item);
|
|
3700
4374
|
const cellLines = keys.map((key, i) => wrapText(cellToString(item[key]), finalWidths[i]));
|
|
3701
4375
|
const lineCount = Math.max(...cellLines.map((l) => l.length));
|
|
3702
4376
|
for (let line = 0;line < lineCount; line++) {
|
|
@@ -3704,7 +4378,7 @@ function printResizableTable(data, logFn = console.log, externalLogValue, availa
|
|
|
3704
4378
|
const val = line < cellLines[i].length ? cellLines[i][line] : "";
|
|
3705
4379
|
return val.padEnd(finalWidths[i]);
|
|
3706
4380
|
}).join(" | ");
|
|
3707
|
-
logFn(row);
|
|
4381
|
+
logFn(styleLine(row, style));
|
|
3708
4382
|
}
|
|
3709
4383
|
});
|
|
3710
4384
|
if (externalLogValue) {
|
|
@@ -3848,30 +4522,36 @@ var OutputFormatter;
|
|
|
3848
4522
|
((OutputFormatter) => {
|
|
3849
4523
|
function success(data, options) {
|
|
3850
4524
|
data.Log ??= getLogFilePath() || undefined;
|
|
3851
|
-
const normalize =
|
|
4525
|
+
const normalize = options?.preserveDataKeys !== true;
|
|
4526
|
+
const verbatim = toVerbatimKeySet(options?.preserveDataKeys);
|
|
4527
|
+
const subtrees = verbatim && {
|
|
4528
|
+
refs: new Set,
|
|
4529
|
+
mode: "collect"
|
|
4530
|
+
};
|
|
3852
4531
|
if (normalize) {
|
|
3853
|
-
data.Data = normalizeDataKeys(data.Data);
|
|
4532
|
+
data.Data = normalizeDataKeys(data.Data, verbatim, subtrees);
|
|
3854
4533
|
}
|
|
3855
4534
|
const filter = getOutputFilter();
|
|
3856
4535
|
if (filter) {
|
|
3857
4536
|
const filtered = applyFilter(data.Data, filter);
|
|
3858
|
-
data.Data = normalize ? normalizeDataKeys(filtered) : filtered;
|
|
4537
|
+
data.Data = normalize ? normalizeDataKeys(filtered, verbatim, subtrees && { refs: subtrees.refs, mode: "skip" }) : filtered;
|
|
3859
4538
|
}
|
|
3860
|
-
logOutput(normalizeOutputKeys(data), getOutputFormat());
|
|
4539
|
+
logOutput(normalizeOutputKeys(data), getOutputFormat(), options?.tableRowStyle);
|
|
3861
4540
|
}
|
|
3862
4541
|
OutputFormatter.success = success;
|
|
3863
4542
|
function error(data) {
|
|
3864
4543
|
data.Log ??= getLogFilePath() || undefined;
|
|
3865
4544
|
data.ErrorCode ??= defaultErrorCodeForFailure(data);
|
|
3866
4545
|
data.Retry ??= defaultRetryForErrorCode(data.ErrorCode);
|
|
3867
|
-
|
|
4546
|
+
const exitCode = EXIT_CODES[data.Result] ?? 1;
|
|
4547
|
+
setExitCode(exitCode);
|
|
3868
4548
|
recordCommandFailureTelemetry({
|
|
3869
4549
|
result: data.Result,
|
|
3870
4550
|
errorCode: data.ErrorCode,
|
|
3871
4551
|
retry: data.Retry,
|
|
3872
4552
|
message: data.Message,
|
|
3873
4553
|
context: data.Context,
|
|
3874
|
-
exitCode
|
|
4554
|
+
exitCode,
|
|
3875
4555
|
errorClass: data.TelemetryErrorClass,
|
|
3876
4556
|
terminalOutcome: data.TelemetryTerminalOutcome,
|
|
3877
4557
|
terminalSignal: data.TelemetryTerminalSignal
|
|
@@ -3947,6 +4627,39 @@ var OutputFormatter;
|
|
|
3947
4627
|
}
|
|
3948
4628
|
OutputFormatter.formatToString = formatToString;
|
|
3949
4629
|
})(OutputFormatter ||= {});
|
|
4630
|
+
// ../../node_modules/commander/esm.mjs
|
|
4631
|
+
var import__ = __toESM(require_commander(), 1);
|
|
4632
|
+
var {
|
|
4633
|
+
program,
|
|
4634
|
+
createCommand,
|
|
4635
|
+
createArgument,
|
|
4636
|
+
createOption,
|
|
4637
|
+
CommanderError,
|
|
4638
|
+
InvalidArgumentError,
|
|
4639
|
+
InvalidOptionArgumentError,
|
|
4640
|
+
Command,
|
|
4641
|
+
Argument,
|
|
4642
|
+
Option,
|
|
4643
|
+
Help
|
|
4644
|
+
} = import__.default;
|
|
4645
|
+
|
|
4646
|
+
// ../common/src/command-examples.ts
|
|
4647
|
+
var examplesByCommand = new WeakMap;
|
|
4648
|
+
Command.prototype.examples = function(examples) {
|
|
4649
|
+
examplesByCommand.set(this, examples);
|
|
4650
|
+
return this;
|
|
4651
|
+
};
|
|
4652
|
+
// ../common/src/preview.ts
|
|
4653
|
+
var previewSlot = singleton("PreviewBuild");
|
|
4654
|
+
function isPreviewBuild() {
|
|
4655
|
+
return previewSlot.get(false) ?? false;
|
|
4656
|
+
}
|
|
4657
|
+
Command.prototype.previewCommand = function(nameAndArgs, opts) {
|
|
4658
|
+
if (isPreviewBuild()) {
|
|
4659
|
+
return this.command(nameAndArgs, opts);
|
|
4660
|
+
}
|
|
4661
|
+
return new Command(nameAndArgs.split(/\s+/)[0] ?? nameAndArgs);
|
|
4662
|
+
};
|
|
3950
4663
|
|
|
3951
4664
|
// ../common/src/telemetry/command-attribution.ts
|
|
3952
4665
|
var LEGACY_SKILL_NAMESPACE = "uipath:";
|
|
@@ -4101,6 +4814,57 @@ function buildCommandTelemetryAttribution(commandPath, skillSource) {
|
|
|
4101
4814
|
};
|
|
4102
4815
|
}
|
|
4103
4816
|
|
|
4817
|
+
// ../common/src/telemetry/command-name.ts
|
|
4818
|
+
var TELEMETRY_COMMAND_ROOT = "uip";
|
|
4819
|
+
function commandTelemetryName(parts) {
|
|
4820
|
+
const tokens = [];
|
|
4821
|
+
for (const part of parts) {
|
|
4822
|
+
const pieces = String(part ?? "").split(/\s+/).filter((token) => token && !token.startsWith("-") && token !== TELEMETRY_COMMAND_ROOT);
|
|
4823
|
+
if (pieces.every(isCommandToken)) {
|
|
4824
|
+
tokens.push(...pieces);
|
|
4825
|
+
continue;
|
|
4826
|
+
}
|
|
4827
|
+
tokens.push(UNKNOWN_TOKEN);
|
|
4828
|
+
}
|
|
4829
|
+
return [TELEMETRY_COMMAND_ROOT, ...tokens].join(".");
|
|
4830
|
+
}
|
|
4831
|
+
var COMMAND_TOKEN_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
4832
|
+
var MAX_COMMAND_TOKEN_LENGTH = 32;
|
|
4833
|
+
var GUID_TOKEN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
4834
|
+
function isCommandToken(token) {
|
|
4835
|
+
return token.length <= MAX_COMMAND_TOKEN_LENGTH && COMMAND_TOKEN_PATTERN.test(token) && !GUID_TOKEN.test(token) && !/^\d+$/.test(token);
|
|
4836
|
+
}
|
|
4837
|
+
var UNKNOWN_TOKEN = "<unknown>";
|
|
4838
|
+
|
|
4839
|
+
// ../common/src/telemetry/invocation-request.ts
|
|
4840
|
+
var requestContextSlot = singleton("TelemetryInvocationRequestContext");
|
|
4841
|
+
function activeContext() {
|
|
4842
|
+
return telemetry.getActiveContext?.();
|
|
4843
|
+
}
|
|
4844
|
+
function runWithInvocationRequest(fn) {
|
|
4845
|
+
const context = telemetry.createRequestContext();
|
|
4846
|
+
context.startedAt = invocationStartedAt();
|
|
4847
|
+
requestContextSlot.set(context);
|
|
4848
|
+
return telemetry.runWithContext(context, fn);
|
|
4849
|
+
}
|
|
4850
|
+
function ensureInvocationRequestScope(fn) {
|
|
4851
|
+
if (activeContext() !== undefined) {
|
|
4852
|
+
return fn();
|
|
4853
|
+
}
|
|
4854
|
+
const kept = requestContextSlot.get();
|
|
4855
|
+
return kept === undefined ? runWithInvocationRequest(fn) : telemetry.runWithContext(kept, fn);
|
|
4856
|
+
}
|
|
4857
|
+
function getInvocationRequestContext() {
|
|
4858
|
+
return activeContext() ?? requestContextSlot.get();
|
|
4859
|
+
}
|
|
4860
|
+
function emitInvocationRequest(name, success, properties) {
|
|
4861
|
+
const context = getInvocationRequestContext();
|
|
4862
|
+
telemetry.trackRequestResult(name, invocationElapsedMs(), success, properties, context);
|
|
4863
|
+
if (context !== undefined && requestContextSlot.get() === context) {
|
|
4864
|
+
requestContextSlot.clear();
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
|
|
4104
4868
|
// ../common/src/trackedAction.ts
|
|
4105
4869
|
var pollSignalSlot = singleton("PollSignal");
|
|
4106
4870
|
var cliErrorCodeValues = new Set(CLI_ERROR_CODES);
|
|
@@ -4108,28 +4872,74 @@ var retryHintValues = new Set(RETRY_HINTS);
|
|
|
4108
4872
|
var TELEMETRY_COMMAND_ARG_PREFIX = "uip.cmd.arg.";
|
|
4109
4873
|
var processContext = {
|
|
4110
4874
|
exit: (code) => {
|
|
4111
|
-
|
|
4875
|
+
recordExitCode(code);
|
|
4876
|
+
setExitCode(code);
|
|
4112
4877
|
},
|
|
4113
4878
|
get pollSignal() {
|
|
4114
4879
|
return pollSignalSlot.get();
|
|
4115
4880
|
}
|
|
4116
4881
|
};
|
|
4882
|
+
var TELEMETRY_ARG_VALUE_WITHHELD = "<provided>";
|
|
4883
|
+
var TELEMETRY_ARG_VALUE_DEFAULTED = "<default>";
|
|
4884
|
+
function recordableArgValue(value, choices) {
|
|
4885
|
+
if (typeof value === "boolean" || typeof value === "number") {
|
|
4886
|
+
return value;
|
|
4887
|
+
}
|
|
4888
|
+
if (choices && choices.length > 0) {
|
|
4889
|
+
if (typeof value === "string" && choices.includes(value)) {
|
|
4890
|
+
return value;
|
|
4891
|
+
}
|
|
4892
|
+
if (Array.isArray(value) && value.length > 0 && value.every((entry) => typeof entry === "string" && choices.includes(entry))) {
|
|
4893
|
+
return value.join(",");
|
|
4894
|
+
}
|
|
4895
|
+
}
|
|
4896
|
+
return TELEMETRY_ARG_VALUE_WITHHELD;
|
|
4897
|
+
}
|
|
4117
4898
|
function extractCommandParams(cmd) {
|
|
4118
4899
|
const params = {};
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4900
|
+
forEachSuppliedArgument(cmd, (name, value, choices, defaulted) => {
|
|
4901
|
+
const recordable = recordableArgValue(value, choices);
|
|
4902
|
+
params[`${TELEMETRY_COMMAND_ARG_PREFIX}${name}`] = recordable === TELEMETRY_ARG_VALUE_WITHHELD && defaulted ? TELEMETRY_ARG_VALUE_DEFAULTED : recordable;
|
|
4903
|
+
});
|
|
4904
|
+
return params;
|
|
4905
|
+
}
|
|
4906
|
+
function isDefaultedOption(cmd, name) {
|
|
4907
|
+
const source = cmd.getOptionValueSource?.(name);
|
|
4908
|
+
return source === "default" || source === "implied";
|
|
4909
|
+
}
|
|
4910
|
+
function isDefaultedPositional(cmd, index) {
|
|
4911
|
+
return index >= (cmd.args?.length ?? 0);
|
|
4912
|
+
}
|
|
4913
|
+
function forEachSuppliedArgument(cmd, visit) {
|
|
4124
4914
|
const registered = cmd.registeredArguments ?? [];
|
|
4125
4915
|
const processed = cmd.processedArgs ?? [];
|
|
4126
4916
|
for (let i = 0;i < registered.length; i++) {
|
|
4127
|
-
|
|
4917
|
+
const name = registered[i].name();
|
|
4918
|
+
if (name && processed[i] !== undefined) {
|
|
4919
|
+
visit(name, processed[i], registered[i].argChoices, isDefaultedPositional(cmd, i));
|
|
4920
|
+
}
|
|
4921
|
+
}
|
|
4922
|
+
const choicesByAttribute = new Map;
|
|
4923
|
+
for (const option of cmd.options) {
|
|
4924
|
+
choicesByAttribute.set(option.attributeName(), option.argChoices);
|
|
4128
4925
|
}
|
|
4129
4926
|
for (const [key, value] of Object.entries(cmd.opts())) {
|
|
4130
|
-
|
|
4927
|
+
if (key && value !== undefined) {
|
|
4928
|
+
visit(key, value, choicesByAttribute.get(key), isDefaultedOption(cmd, key));
|
|
4929
|
+
}
|
|
4131
4930
|
}
|
|
4132
|
-
|
|
4931
|
+
}
|
|
4932
|
+
function withheldArgumentValues(cmd) {
|
|
4933
|
+
const values = [];
|
|
4934
|
+
forEachSuppliedArgument(cmd, (_name, value, choices, defaulted) => {
|
|
4935
|
+
if (defaulted) {
|
|
4936
|
+
return;
|
|
4937
|
+
}
|
|
4938
|
+
if (recordableArgValue(value, choices) === TELEMETRY_ARG_VALUE_WITHHELD) {
|
|
4939
|
+
values.push(value);
|
|
4940
|
+
}
|
|
4941
|
+
});
|
|
4942
|
+
return values;
|
|
4133
4943
|
}
|
|
4134
4944
|
function deriveCommandPath(cmd) {
|
|
4135
4945
|
const parts = [];
|
|
@@ -4144,7 +4954,7 @@ function deriveCommandPath(cmd) {
|
|
|
4144
4954
|
if (parts.length > 1) {
|
|
4145
4955
|
parts.shift();
|
|
4146
4956
|
}
|
|
4147
|
-
return
|
|
4957
|
+
return commandTelemetryName(parts);
|
|
4148
4958
|
}
|
|
4149
4959
|
function isCliErrorCode(value) {
|
|
4150
4960
|
return typeof value === "string" && cliErrorCodeValues.has(value);
|
|
@@ -4184,68 +4994,77 @@ Command.prototype.trackedAction = function(context, fn, properties) {
|
|
|
4184
4994
|
});
|
|
4185
4995
|
const telemetryName = deriveCommandPath(command);
|
|
4186
4996
|
const props = typeof properties === "function" ? properties(...args) : properties;
|
|
4187
|
-
|
|
4188
|
-
const
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4997
|
+
markCommandStart();
|
|
4998
|
+
const supplied = recordSuppliedArgumentValues(withheldArgumentValues(command));
|
|
4999
|
+
try {
|
|
5000
|
+
const startTime = performance.now();
|
|
5001
|
+
let errorMessage;
|
|
5002
|
+
let fallbackExitCode = EXIT_CODES.Success;
|
|
5003
|
+
clearRecordedCommandFailureTelemetry();
|
|
5004
|
+
const [error] = await catchError(ensureInvocationRequestScope(() => {
|
|
5005
|
+
const violation = implicitLimitViolation(command);
|
|
5006
|
+
if (violation) {
|
|
5007
|
+
return Promise.reject(violation);
|
|
5008
|
+
}
|
|
5009
|
+
return fn(...args);
|
|
5010
|
+
}));
|
|
5011
|
+
if (error) {
|
|
5012
|
+
errorMessage = error instanceof Error ? error.message : String(error);
|
|
5013
|
+
logger.debug(`[trackedAction] ${telemetryName} failed: ${errorMessage}`);
|
|
5014
|
+
const typed = error;
|
|
5015
|
+
const customInstructions = typeof typed.instructions === "string" ? typed.instructions : undefined;
|
|
5016
|
+
const customResult = typeof typed.result === "string" && typed.result !== RESULTS.Success && Object.values(RESULTS).includes(typed.result) ? typed.result : undefined;
|
|
5017
|
+
const finalResult = customResult ?? RESULTS.Failure;
|
|
5018
|
+
const typedErrorCode = typed.errorCode ?? typed.ErrorCode;
|
|
5019
|
+
const customErrorCode = isCliErrorCode(typedErrorCode) ? typedErrorCode : undefined;
|
|
5020
|
+
const typedRetry = typed.retry ?? typed.Retry;
|
|
5021
|
+
const customRetry = isRetryHint(typedRetry) ? typedRetry : undefined;
|
|
5022
|
+
const typedContext = typed.context ?? typed.Context;
|
|
5023
|
+
const customContext = isErrorContext(typedContext) ? typedContext : undefined;
|
|
5024
|
+
const cancellationExitCode = typed.exitCode === 130 || isPromptCancellation(error) ? 130 : undefined;
|
|
5025
|
+
fallbackExitCode = cancellationExitCode ?? EXIT_CODES[finalResult];
|
|
5026
|
+
OutputFormatter.error({
|
|
5027
|
+
Result: finalResult,
|
|
5028
|
+
...customErrorCode ? { ErrorCode: customErrorCode } : {},
|
|
5029
|
+
Message: errorMessage,
|
|
5030
|
+
Instructions: customInstructions ?? commandHelpHint(telemetryName),
|
|
5031
|
+
...customRetry ? { Retry: customRetry } : {},
|
|
5032
|
+
...customContext ? { Context: customContext } : {}
|
|
5033
|
+
});
|
|
5034
|
+
context.exit(fallbackExitCode);
|
|
5035
|
+
}
|
|
5036
|
+
const durationMs = performance.now() - startTime;
|
|
5037
|
+
recordCommandDuration(durationMs);
|
|
5038
|
+
const exitCode = fallbackExitCode === 130 ? fallbackExitCode : exitCodeFromProcess(fallbackExitCode);
|
|
5039
|
+
const recordedFailure = takeRecordedCommandFailureTelemetry();
|
|
5040
|
+
const success = !error && exitCode === 0;
|
|
5041
|
+
const terminalTelemetry = buildCommandTerminalTelemetryProperties({
|
|
5042
|
+
error,
|
|
5043
|
+
exitCode,
|
|
5044
|
+
recordedFailure,
|
|
5045
|
+
pollSignal: context.pollSignal
|
|
4221
5046
|
});
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
}
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
...buildCommandTelemetryAttribution(telemetryName, process.env.UIPATH_SKILL),
|
|
4244
|
-
command: "true",
|
|
4245
|
-
...terminalTelemetry,
|
|
4246
|
-
...errorMessage ? { errorMessage } : {}
|
|
4247
|
-
});
|
|
4248
|
-
telemetry.trackRequestResult(telemetryName, durationMs, success, baseProperties, requestContext);
|
|
5047
|
+
if (terminalTelemetry.error_class === "internal" && error) {
|
|
5048
|
+
telemetry.trackException(error instanceof Error ? error : new Error(String(error)), { command_name: telemetryName }, getInvocationRequestContext());
|
|
5049
|
+
}
|
|
5050
|
+
const commandParams = extractCommandParams(command);
|
|
5051
|
+
if (props) {
|
|
5052
|
+
for (const key of Object.keys(props)) {
|
|
5053
|
+
delete commandParams[`${TELEMETRY_COMMAND_ARG_PREFIX}${key}`];
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
const baseProperties = redactProperties({
|
|
5057
|
+
...commandParams,
|
|
5058
|
+
...props,
|
|
5059
|
+
...buildCommandTelemetryAttribution(telemetryName, process.env.UIPATH_SKILL),
|
|
5060
|
+
command: "true",
|
|
5061
|
+
...terminalTelemetry,
|
|
5062
|
+
...errorMessage ? { errorMessage } : {}
|
|
5063
|
+
});
|
|
5064
|
+
emitInvocationRequest(telemetryName, success, baseProperties);
|
|
5065
|
+
} finally {
|
|
5066
|
+
releaseSuppliedArgumentValues(supplied);
|
|
5067
|
+
}
|
|
4249
5068
|
});
|
|
4250
5069
|
};
|
|
4251
5070
|
// ../common/src/completer.ts
|
|
@@ -4268,6 +5087,204 @@ var guardInstalledSlot = singleton("ConsoleGuardInstalled");
|
|
|
4268
5087
|
var savedOriginalsSlot = singleton("ConsoleGuardOriginals");
|
|
4269
5088
|
// ../common/src/constants.ts
|
|
4270
5089
|
var DEFAULT_AUTH_TIMEOUT_MS = 5 * 60 * 1000;
|
|
5090
|
+
// ../common/src/entity-name-rules.ts
|
|
5091
|
+
var RESERVED_SQL_KEYWORDS_LOWER = new Set(["group", "order"]);
|
|
5092
|
+
var RESERVED_FIELD_NAMES_LOWER = new Set([
|
|
5093
|
+
"id",
|
|
5094
|
+
"createdby",
|
|
5095
|
+
"createtime",
|
|
5096
|
+
"updatedby",
|
|
5097
|
+
"updatetime",
|
|
5098
|
+
"recordowner",
|
|
5099
|
+
"version"
|
|
5100
|
+
]);
|
|
5101
|
+
var RESERVED_KEYWORDS_LOWER = new Set([
|
|
5102
|
+
"abstract",
|
|
5103
|
+
"as",
|
|
5104
|
+
"base",
|
|
5105
|
+
"bool",
|
|
5106
|
+
"break",
|
|
5107
|
+
"byte",
|
|
5108
|
+
"case",
|
|
5109
|
+
"catch",
|
|
5110
|
+
"char",
|
|
5111
|
+
"checked",
|
|
5112
|
+
"class",
|
|
5113
|
+
"const",
|
|
5114
|
+
"continue",
|
|
5115
|
+
"decimal",
|
|
5116
|
+
"default",
|
|
5117
|
+
"delegate",
|
|
5118
|
+
"do",
|
|
5119
|
+
"double",
|
|
5120
|
+
"else",
|
|
5121
|
+
"enum",
|
|
5122
|
+
"event",
|
|
5123
|
+
"explicit",
|
|
5124
|
+
"extern",
|
|
5125
|
+
"false",
|
|
5126
|
+
"finally",
|
|
5127
|
+
"fixed",
|
|
5128
|
+
"float",
|
|
5129
|
+
"for",
|
|
5130
|
+
"foreach",
|
|
5131
|
+
"goto",
|
|
5132
|
+
"if",
|
|
5133
|
+
"implicit",
|
|
5134
|
+
"in",
|
|
5135
|
+
"int",
|
|
5136
|
+
"interface",
|
|
5137
|
+
"internal",
|
|
5138
|
+
"is",
|
|
5139
|
+
"lock",
|
|
5140
|
+
"long",
|
|
5141
|
+
"namespace",
|
|
5142
|
+
"new",
|
|
5143
|
+
"null",
|
|
5144
|
+
"object",
|
|
5145
|
+
"operator",
|
|
5146
|
+
"out",
|
|
5147
|
+
"override",
|
|
5148
|
+
"params",
|
|
5149
|
+
"private",
|
|
5150
|
+
"protected",
|
|
5151
|
+
"public",
|
|
5152
|
+
"readonly",
|
|
5153
|
+
"ref",
|
|
5154
|
+
"return",
|
|
5155
|
+
"sbyte",
|
|
5156
|
+
"sealed",
|
|
5157
|
+
"short",
|
|
5158
|
+
"sizeof",
|
|
5159
|
+
"stackalloc",
|
|
5160
|
+
"static",
|
|
5161
|
+
"string",
|
|
5162
|
+
"struct",
|
|
5163
|
+
"switch",
|
|
5164
|
+
"this",
|
|
5165
|
+
"throw",
|
|
5166
|
+
"true",
|
|
5167
|
+
"try",
|
|
5168
|
+
"typeof",
|
|
5169
|
+
"uint",
|
|
5170
|
+
"ulong",
|
|
5171
|
+
"unchecked",
|
|
5172
|
+
"unsafe",
|
|
5173
|
+
"ushort",
|
|
5174
|
+
"using",
|
|
5175
|
+
"virtual",
|
|
5176
|
+
"void",
|
|
5177
|
+
"volatile",
|
|
5178
|
+
"while",
|
|
5179
|
+
"addhandler",
|
|
5180
|
+
"addressof",
|
|
5181
|
+
"alias",
|
|
5182
|
+
"and",
|
|
5183
|
+
"andalso",
|
|
5184
|
+
"boolean",
|
|
5185
|
+
"byref",
|
|
5186
|
+
"byval",
|
|
5187
|
+
"call",
|
|
5188
|
+
"cbool",
|
|
5189
|
+
"cbyte",
|
|
5190
|
+
"cchar",
|
|
5191
|
+
"cdate",
|
|
5192
|
+
"cdbl",
|
|
5193
|
+
"cdec",
|
|
5194
|
+
"cint",
|
|
5195
|
+
"clng",
|
|
5196
|
+
"cobj",
|
|
5197
|
+
"csbyte",
|
|
5198
|
+
"cshort",
|
|
5199
|
+
"csng",
|
|
5200
|
+
"cstr",
|
|
5201
|
+
"ctype",
|
|
5202
|
+
"cuint",
|
|
5203
|
+
"culng",
|
|
5204
|
+
"cushort",
|
|
5205
|
+
"date",
|
|
5206
|
+
"declare",
|
|
5207
|
+
"dim",
|
|
5208
|
+
"directcast",
|
|
5209
|
+
"each",
|
|
5210
|
+
"elseif",
|
|
5211
|
+
"end",
|
|
5212
|
+
"endif",
|
|
5213
|
+
"erase",
|
|
5214
|
+
"error",
|
|
5215
|
+
"exit",
|
|
5216
|
+
"friend",
|
|
5217
|
+
"function",
|
|
5218
|
+
"get",
|
|
5219
|
+
"gettype",
|
|
5220
|
+
"getxmlnamespace",
|
|
5221
|
+
"global",
|
|
5222
|
+
"gosub",
|
|
5223
|
+
"goto",
|
|
5224
|
+
"handles",
|
|
5225
|
+
"implements",
|
|
5226
|
+
"imports",
|
|
5227
|
+
"inherits",
|
|
5228
|
+
"integer",
|
|
5229
|
+
"isnot",
|
|
5230
|
+
"let",
|
|
5231
|
+
"lib",
|
|
5232
|
+
"like",
|
|
5233
|
+
"loop",
|
|
5234
|
+
"me",
|
|
5235
|
+
"mod",
|
|
5236
|
+
"module",
|
|
5237
|
+
"mustinherit",
|
|
5238
|
+
"mustoverride",
|
|
5239
|
+
"mybase",
|
|
5240
|
+
"myclass",
|
|
5241
|
+
"narrowing",
|
|
5242
|
+
"next",
|
|
5243
|
+
"not",
|
|
5244
|
+
"nothing",
|
|
5245
|
+
"notinheritable",
|
|
5246
|
+
"notoverridable",
|
|
5247
|
+
"of",
|
|
5248
|
+
"on",
|
|
5249
|
+
"option",
|
|
5250
|
+
"optional",
|
|
5251
|
+
"or",
|
|
5252
|
+
"orelse",
|
|
5253
|
+
"overloads",
|
|
5254
|
+
"overridable",
|
|
5255
|
+
"overrides",
|
|
5256
|
+
"paramarray",
|
|
5257
|
+
"partial",
|
|
5258
|
+
"property",
|
|
5259
|
+
"raiseevent",
|
|
5260
|
+
"redim",
|
|
5261
|
+
"rem",
|
|
5262
|
+
"removehandler",
|
|
5263
|
+
"resume",
|
|
5264
|
+
"select",
|
|
5265
|
+
"set",
|
|
5266
|
+
"shadows",
|
|
5267
|
+
"shared",
|
|
5268
|
+
"single",
|
|
5269
|
+
"step",
|
|
5270
|
+
"stop",
|
|
5271
|
+
"structure",
|
|
5272
|
+
"sub",
|
|
5273
|
+
"synclock",
|
|
5274
|
+
"then",
|
|
5275
|
+
"to",
|
|
5276
|
+
"trycast",
|
|
5277
|
+
"uinteger",
|
|
5278
|
+
"ushort",
|
|
5279
|
+
"variant",
|
|
5280
|
+
"wend",
|
|
5281
|
+
"when",
|
|
5282
|
+
"widening",
|
|
5283
|
+
"with",
|
|
5284
|
+
"withevents",
|
|
5285
|
+
"writeonly",
|
|
5286
|
+
"xor"
|
|
5287
|
+
]);
|
|
4271
5288
|
// ../common/src/host-global-options.ts
|
|
4272
5289
|
var HOST_GLOBAL_OPTIONS_WITH_VALUE = [
|
|
4273
5290
|
"--output",
|
|
@@ -4335,6 +5352,40 @@ var sdkUserAgentHostToken = singleton("SdkUserAgentHostToken");
|
|
|
4335
5352
|
var shippedKeysSlot = singleton("ShipSucceededDedupeKeys");
|
|
4336
5353
|
// ../common/src/tool-provider.ts
|
|
4337
5354
|
var factorySlot = singleton("PackagerFactoryProvider");
|
|
5355
|
+
// ../auth/src/catch-error.ts
|
|
5356
|
+
function isPromiseLike2(value) {
|
|
5357
|
+
return value !== null && typeof value === "object" && typeof value.then === "function";
|
|
5358
|
+
}
|
|
5359
|
+
function catchError2(fnOrPromise) {
|
|
5360
|
+
if (isPromiseLike2(fnOrPromise)) {
|
|
5361
|
+
return settlePromiseLike2(fnOrPromise);
|
|
5362
|
+
}
|
|
5363
|
+
try {
|
|
5364
|
+
const result = fnOrPromise();
|
|
5365
|
+
if (isPromiseLike2(result)) {
|
|
5366
|
+
return settlePromiseLike2(result);
|
|
5367
|
+
}
|
|
5368
|
+
return [undefined, result];
|
|
5369
|
+
} catch (error) {
|
|
5370
|
+
return [
|
|
5371
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
5372
|
+
undefined
|
|
5373
|
+
];
|
|
5374
|
+
}
|
|
5375
|
+
}
|
|
5376
|
+
function settlePromiseLike2(thenable) {
|
|
5377
|
+
return Promise.resolve(thenable).then((data) => [undefined, data]).catch((error) => [
|
|
5378
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
5379
|
+
undefined
|
|
5380
|
+
]);
|
|
5381
|
+
}
|
|
5382
|
+
|
|
5383
|
+
// ../auth/src/constants.ts
|
|
5384
|
+
var UIPATH_HOME_DIR = ".uipath";
|
|
5385
|
+
var AUTH_FILENAME = ".auth";
|
|
5386
|
+
var DEFAULT_BASE_URL = "https://cloud.uipath.com";
|
|
5387
|
+
var DEFAULT_AUTH_TIMEOUT_MS2 = 5 * 60 * 1000;
|
|
5388
|
+
|
|
4338
5389
|
// ../auth/src/config.ts
|
|
4339
5390
|
var DEFAULT_CLIENT_ID = "36dea5b8-e8bb-423d-8e7b-c808df8f1c00";
|
|
4340
5391
|
var AUTH_FILE_CONFIG_KEY = Symbol.for("@uipath/auth/AuthFileConfig");
|
|
@@ -4348,7 +5399,7 @@ class InvalidBaseUrlError extends Error {
|
|
|
4348
5399
|
super(`Invalid base URL: "${url}"
|
|
4349
5400
|
` + `Reason: ${reason}
|
|
4350
5401
|
|
|
4351
|
-
` + `Expected format: an https:// URL, e.g. https://cloud.uipath.com (commercial), https://govcloud.uipath.us (Public Sector), or your Automation Suite host (https://<your-host>).
|
|
5402
|
+
` + `Expected format: an https:// URL (or bare host — https:// is assumed), e.g. https://cloud.uipath.com (commercial), https://govcloud.uipath.us (Public Sector), or your Automation Suite host (https://<your-host>).
|
|
4352
5403
|
` + `You can specify the URL via:
|
|
4353
5404
|
` + ` • --authority flag
|
|
4354
5405
|
` + ` • UIPATH_URL environment variable
|
|
@@ -4369,10 +5420,16 @@ var normalizeAndValidateBaseUrl = (rawUrl) => {
|
|
|
4369
5420
|
while (baseUrl.endsWith("/")) {
|
|
4370
5421
|
baseUrl = baseUrl.slice(0, -1);
|
|
4371
5422
|
}
|
|
5423
|
+
const hasScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(baseUrl);
|
|
5424
|
+
const [hostCandidate] = baseUrl.split(/[/?#]/, 1);
|
|
5425
|
+
if (!hasScheme && hostCandidate.includes(".")) {
|
|
5426
|
+
baseUrl = `https://${baseUrl}`;
|
|
5427
|
+
}
|
|
4372
5428
|
const resolvedBaseUrl = baseUrl;
|
|
4373
|
-
const [urlError, url] =
|
|
5429
|
+
const [urlError, url] = catchError2(() => new URL(resolvedBaseUrl));
|
|
4374
5430
|
if (urlError) {
|
|
4375
|
-
|
|
5431
|
+
const shapeHint = !hasScheme && !hostCandidate.includes(".") ? ` "${rawUrl.trim()}" is not a URL or a host name. Pass the full authority URL — https://<host>, or just <host> (https:// is assumed).` : ` ${urlError instanceof Error ? urlError.message : "Unknown error"}`;
|
|
5432
|
+
throw new InvalidBaseUrlError(baseUrl, `Malformed URL.${shapeHint}`);
|
|
4376
5433
|
}
|
|
4377
5434
|
if (url.protocol !== "https:") {
|
|
4378
5435
|
throw new InvalidBaseUrlError(baseUrl, `Authority must use https:// scheme, got ${url.protocol}//. OIDC token exchange requires TLS end-to-end.`);
|
|
@@ -4427,6 +5484,11 @@ var resolveConfigAsync = async ({
|
|
|
4427
5484
|
};
|
|
4428
5485
|
};
|
|
4429
5486
|
|
|
5487
|
+
// ../auth/src/utils/platform.ts
|
|
5488
|
+
function isBrowser() {
|
|
5489
|
+
return typeof globalThis !== "undefined" && "window" in globalThis && "document" in globalThis;
|
|
5490
|
+
}
|
|
5491
|
+
|
|
4430
5492
|
// ../auth/src/authProfile.ts
|
|
4431
5493
|
var DEFAULT_AUTH_PROFILE = "default";
|
|
4432
5494
|
var PROFILE_DIR = "profiles";
|
|
@@ -4438,7 +5500,7 @@ function isAuthProfileStorage(value) {
|
|
|
4438
5500
|
return value !== null && typeof value === "object" && "getStore" in value && "run" in value;
|
|
4439
5501
|
}
|
|
4440
5502
|
function createProfileStorage() {
|
|
4441
|
-
const [error, mod] =
|
|
5503
|
+
const [error, mod] = catchError2(() => __require("node:async_hooks"));
|
|
4442
5504
|
if (error || typeof mod?.AsyncLocalStorage !== "function") {
|
|
4443
5505
|
return {
|
|
4444
5506
|
getStore: () => {
|
|
@@ -4454,9 +5516,9 @@ function getProfileStorage() {
|
|
|
4454
5516
|
if (isAuthProfileStorage(existing)) {
|
|
4455
5517
|
return existing;
|
|
4456
5518
|
}
|
|
4457
|
-
const
|
|
4458
|
-
globalSlot2[AUTH_PROFILE_STORAGE_KEY] =
|
|
4459
|
-
return
|
|
5519
|
+
const storage2 = createProfileStorage();
|
|
5520
|
+
globalSlot2[AUTH_PROFILE_STORAGE_KEY] = storage2;
|
|
5521
|
+
return storage2;
|
|
4460
5522
|
}
|
|
4461
5523
|
var profileStorage = getProfileStorage();
|
|
4462
5524
|
|
|
@@ -4487,8 +5549,8 @@ function resolveAuthProfileFilePath(profile) {
|
|
|
4487
5549
|
if (normalized === undefined) {
|
|
4488
5550
|
throw new AuthProfileValidationError(`"${DEFAULT_AUTH_PROFILE}" is the built-in profile and does not have a profile file path.`);
|
|
4489
5551
|
}
|
|
4490
|
-
const
|
|
4491
|
-
return
|
|
5552
|
+
const fs2 = getFileSystem();
|
|
5553
|
+
return fs2.path.join(fs2.env.homedir(), UIPATH_HOME_DIR, PROFILE_DIR, normalized, AUTH_FILENAME);
|
|
4492
5554
|
}
|
|
4493
5555
|
function getActiveAuthProfileFilePath() {
|
|
4494
5556
|
const profile = getActiveAuthProfile();
|
|
@@ -4569,7 +5631,7 @@ var getTokenExpiration = (accessToken) => {
|
|
|
4569
5631
|
// ../auth/src/sessionIdentity.ts
|
|
4570
5632
|
var parseAuthFlow = (value) => value === "authorization_code" || value === "client_credentials" || value === "federated_credentials" ? value : undefined;
|
|
4571
5633
|
var decodeClaims = (accessToken) => {
|
|
4572
|
-
const [error, claims] =
|
|
5634
|
+
const [error, claims] = catchError2(() => parseJWT(accessToken));
|
|
4573
5635
|
return error ? undefined : claims;
|
|
4574
5636
|
};
|
|
4575
5637
|
var asString = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
@@ -4653,27 +5715,48 @@ var requireEnv = (name) => {
|
|
|
4653
5715
|
}
|
|
4654
5716
|
return value;
|
|
4655
5717
|
};
|
|
5718
|
+
var OPAQUE_TOKEN_BASE_URL_VAR = "UIPATH_URL";
|
|
5719
|
+
var resolveBaseUrl = (rawUrl, failureContext) => {
|
|
5720
|
+
const [baseUrlError, baseUrl] = catchError2(() => normalizeAndValidateBaseUrl(rawUrl));
|
|
5721
|
+
if (baseUrlError) {
|
|
5722
|
+
if (baseUrlError instanceof InvalidBaseUrlError) {
|
|
5723
|
+
throw baseUrlError;
|
|
5724
|
+
}
|
|
5725
|
+
throw new EnvAuthConfigError(`${failureContext}: ` + `${baseUrlError instanceof Error ? baseUrlError.message : String(baseUrlError)}`);
|
|
5726
|
+
}
|
|
5727
|
+
return baseUrl;
|
|
5728
|
+
};
|
|
4656
5729
|
var readAuthFromEnv = () => {
|
|
4657
5730
|
const accessToken = requireEnv(ENV_AUTH_VARS.token);
|
|
4658
5731
|
const organizationName = requireEnv(ENV_AUTH_VARS.organizationName);
|
|
4659
5732
|
const organizationId = requireEnv(ENV_AUTH_VARS.organizationId);
|
|
4660
5733
|
const tenantName = requireEnv(ENV_AUTH_VARS.tenantName);
|
|
4661
5734
|
const tenantId = requireEnv(ENV_AUTH_VARS.tenantId);
|
|
4662
|
-
const [parseError, payload] =
|
|
5735
|
+
const [parseError, payload] = catchError2(() => parseJWT(accessToken));
|
|
4663
5736
|
if (parseError) {
|
|
4664
|
-
|
|
5737
|
+
const parseErrorMessage = parseError instanceof Error ? parseError.message : String(parseError);
|
|
5738
|
+
const rawUrl = process.env[OPAQUE_TOKEN_BASE_URL_VAR];
|
|
5739
|
+
if (!rawUrl) {
|
|
5740
|
+
throw new EnvAuthConfigError(`${ENV_AUTH_VARS.token} is not a JWT (treating it as an opaque token, ` + `e.g. a Personal Access Token). Set ${OPAQUE_TOKEN_BASE_URL_VAR} to the ` + `UiPath base URL if this is a PAT, or fix the token if it was meant to ` + `be a JWT (parse error: ${parseErrorMessage}).`);
|
|
5741
|
+
}
|
|
5742
|
+
const baseUrl2 = resolveBaseUrl(rawUrl, `Failed to validate ${OPAQUE_TOKEN_BASE_URL_VAR}`);
|
|
5743
|
+
return {
|
|
5744
|
+
loginStatus: "Logged in",
|
|
5745
|
+
accessToken,
|
|
5746
|
+
baseUrl: baseUrl2,
|
|
5747
|
+
organizationName,
|
|
5748
|
+
organizationId,
|
|
5749
|
+
tenantName,
|
|
5750
|
+
tenantId,
|
|
5751
|
+
source: "env-vars" /* EnvironmentVariables */,
|
|
5752
|
+
hint: "Token is opaque (not a JWT) - expiration and identity cannot be " + "determined locally. Commands will fail with 401 once it is revoked or " + `expired. If this was meant to be a JWT instead of a PAT, note: ${parseErrorMessage}`
|
|
5753
|
+
};
|
|
4665
5754
|
}
|
|
4666
5755
|
const iss = payload.iss;
|
|
4667
5756
|
if (typeof iss !== "string" || iss.length === 0) {
|
|
4668
5757
|
throw new EnvAuthConfigError(`${ENV_AUTH_VARS.token} has no 'iss' claim; cannot determine ` + `the UiPath server. Ensure the token was issued by a UiPath identity server.`);
|
|
4669
5758
|
}
|
|
4670
|
-
const
|
|
4671
|
-
if (baseUrlError) {
|
|
4672
|
-
if (baseUrlError instanceof InvalidBaseUrlError) {
|
|
4673
|
-
throw baseUrlError;
|
|
4674
|
-
}
|
|
4675
|
-
throw new EnvAuthConfigError(`Failed to derive server URL from token 'iss' claim: ` + `${baseUrlError instanceof Error ? baseUrlError.message : String(baseUrlError)}`);
|
|
4676
|
-
}
|
|
5759
|
+
const baseUrl = resolveBaseUrl(iss, "Failed to derive server URL from token 'iss' claim");
|
|
4677
5760
|
const expiration = getTokenExpiration(accessToken);
|
|
4678
5761
|
const loginStatus = expiration && expiration <= new Date ? "Expired" : "Logged in";
|
|
4679
5762
|
const identity = resolveSessionIdentity(accessToken);
|
|
@@ -4699,8 +5782,8 @@ var SURFACE_WINDOW_MS = 60 * 60 * 1000;
|
|
|
4699
5782
|
async function refreshTokenFingerprint(refreshToken) {
|
|
4700
5783
|
const bytes = new TextEncoder().encode(refreshToken);
|
|
4701
5784
|
if (globalThis.crypto?.subtle) {
|
|
4702
|
-
const
|
|
4703
|
-
return Array.from(new Uint8Array(
|
|
5785
|
+
const digest2 = await globalThis.crypto.subtle.digest("SHA-256", bytes);
|
|
5786
|
+
return Array.from(new Uint8Array(digest2), (b) => b.toString(16).padStart(2, "0")).join("").slice(0, 16);
|
|
4704
5787
|
}
|
|
4705
5788
|
const { createHash } = await import("node:crypto");
|
|
4706
5789
|
return createHash("sha256").update(refreshToken).digest("hex").slice(0, 16);
|
|
@@ -4709,9 +5792,9 @@ function breakerPathFor(authPath) {
|
|
|
4709
5792
|
return `${authPath}${BREAKER_SUFFIX}`;
|
|
4710
5793
|
}
|
|
4711
5794
|
async function loadRefreshBreaker(authPath) {
|
|
4712
|
-
const
|
|
5795
|
+
const fs2 = getFileSystem();
|
|
4713
5796
|
try {
|
|
4714
|
-
const content = await
|
|
5797
|
+
const content = await fs2.readFile(breakerPathFor(authPath), "utf-8");
|
|
4715
5798
|
if (!content)
|
|
4716
5799
|
return {};
|
|
4717
5800
|
const parsed = JSON.parse(content);
|
|
@@ -4722,20 +5805,20 @@ async function loadRefreshBreaker(authPath) {
|
|
|
4722
5805
|
}
|
|
4723
5806
|
async function saveRefreshBreaker(authPath, state) {
|
|
4724
5807
|
try {
|
|
4725
|
-
const
|
|
4726
|
-
const
|
|
4727
|
-
await
|
|
4728
|
-
const tempPath = `${
|
|
4729
|
-
await
|
|
4730
|
-
await
|
|
5808
|
+
const fs2 = getFileSystem();
|
|
5809
|
+
const path2 = breakerPathFor(authPath);
|
|
5810
|
+
await fs2.mkdir(fs2.path.dirname(path2));
|
|
5811
|
+
const tempPath = `${path2}.tmp`;
|
|
5812
|
+
await fs2.writeFile(tempPath, JSON.stringify(state));
|
|
5813
|
+
await fs2.rename(tempPath, path2);
|
|
4731
5814
|
} catch {}
|
|
4732
5815
|
}
|
|
4733
5816
|
async function clearRefreshBreaker(authPath) {
|
|
4734
|
-
const
|
|
4735
|
-
const
|
|
5817
|
+
const fs2 = getFileSystem();
|
|
5818
|
+
const path2 = breakerPathFor(authPath);
|
|
4736
5819
|
try {
|
|
4737
|
-
if (await
|
|
4738
|
-
await
|
|
5820
|
+
if (await fs2.exists(path2)) {
|
|
5821
|
+
await fs2.rm(path2);
|
|
4739
5822
|
}
|
|
4740
5823
|
} catch {}
|
|
4741
5824
|
}
|
|
@@ -4756,43 +5839,43 @@ var ROBOT_USER_SERVICES_PIPE = "UiPathUserServices";
|
|
|
4756
5839
|
var ROBOT_USER_SERVICES_ALTERNATE_PIPE = `${ROBOT_USER_SERVICES_PIPE}Alternate`;
|
|
4757
5840
|
var PIPE_NAME_MAX_LENGTH = 103;
|
|
4758
5841
|
var getRobotIpcPipeNames = async () => {
|
|
4759
|
-
const
|
|
4760
|
-
const username =
|
|
5842
|
+
const fs2 = getFileSystem();
|
|
5843
|
+
const username = fs2.env.getenv("USER") ?? fs2.env.getenv("USERNAME");
|
|
4761
5844
|
if (!username) {
|
|
4762
5845
|
throw new Error("Unable to determine current username");
|
|
4763
5846
|
}
|
|
4764
|
-
const tempPath =
|
|
4765
|
-
return [ROBOT_USER_SERVICES_PIPE, ROBOT_USER_SERVICES_ALTERNATE_PIPE].map((baseName) =>
|
|
5847
|
+
const tempPath = fs2.env.getenv("TMPDIR") ?? "/tmp/";
|
|
5848
|
+
return [ROBOT_USER_SERVICES_PIPE, ROBOT_USER_SERVICES_ALTERNATE_PIPE].map((baseName) => fs2.path.join(tempPath, `${baseName}_${username}`).substring(0, PIPE_NAME_MAX_LENGTH));
|
|
4766
5849
|
};
|
|
4767
5850
|
var defaultIsRobotIpcAvailable = async () => {
|
|
4768
5851
|
if (process.platform === "win32") {
|
|
4769
5852
|
return true;
|
|
4770
5853
|
}
|
|
4771
|
-
const [pipeNamesError, pipeNames] = await
|
|
5854
|
+
const [pipeNamesError, pipeNames] = await catchError2(getRobotIpcPipeNames());
|
|
4772
5855
|
if (pipeNamesError || !pipeNames) {
|
|
4773
5856
|
return false;
|
|
4774
5857
|
}
|
|
4775
|
-
const
|
|
5858
|
+
const fs2 = getFileSystem();
|
|
4776
5859
|
for (const pipeName of pipeNames) {
|
|
4777
|
-
const [existsError, exists] = await
|
|
5860
|
+
const [existsError, exists] = await catchError2(fs2.exists(pipeName));
|
|
4778
5861
|
if (!existsError && exists === true) {
|
|
4779
5862
|
return true;
|
|
4780
5863
|
}
|
|
4781
5864
|
}
|
|
4782
5865
|
return false;
|
|
4783
5866
|
};
|
|
4784
|
-
var withTimeout = (promise, timeoutMs) => new Promise((
|
|
5867
|
+
var withTimeout = (promise, timeoutMs) => new Promise((resolve2, reject) => {
|
|
4785
5868
|
const timer = setTimeout(() => reject(new Error(`Robot IPC call timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
4786
5869
|
promise.then((value) => {
|
|
4787
5870
|
clearTimeout(timer);
|
|
4788
|
-
|
|
5871
|
+
resolve2(value);
|
|
4789
5872
|
}, (error) => {
|
|
4790
5873
|
clearTimeout(timer);
|
|
4791
5874
|
reject(error);
|
|
4792
5875
|
});
|
|
4793
5876
|
});
|
|
4794
5877
|
var parseResourceUrl = (url) => {
|
|
4795
|
-
const [error, parsed] =
|
|
5878
|
+
const [error, parsed] = catchError2(() => new URL(url));
|
|
4796
5879
|
if (error || !parsed)
|
|
4797
5880
|
return;
|
|
4798
5881
|
const segments = parsed.pathname.split("/").filter(Boolean);
|
|
@@ -4812,7 +5895,7 @@ var defaultLoadModule = async () => {
|
|
|
4812
5895
|
if (!hostLoader) {
|
|
4813
5896
|
return;
|
|
4814
5897
|
}
|
|
4815
|
-
const [error, mod] = await
|
|
5898
|
+
const [error, mod] = await catchError2(() => hostLoader());
|
|
4816
5899
|
if (error || !mod) {
|
|
4817
5900
|
return;
|
|
4818
5901
|
}
|
|
@@ -4838,7 +5921,7 @@ var tryRobotClientFallback = async (options = {}) => {
|
|
|
4838
5921
|
const mod = await loadModule();
|
|
4839
5922
|
if (!mod)
|
|
4840
5923
|
return;
|
|
4841
|
-
const [ctorError, proxy] =
|
|
5924
|
+
const [ctorError, proxy] = catchError2(() => new mod.RobotProxyConstructor);
|
|
4842
5925
|
if (ctorError || !proxy) {
|
|
4843
5926
|
return;
|
|
4844
5927
|
}
|
|
@@ -4861,7 +5944,7 @@ var tryRobotClientFallback = async (options = {}) => {
|
|
|
4861
5944
|
let organizationIdFromToken;
|
|
4862
5945
|
let tenantIdFromToken;
|
|
4863
5946
|
let issuerFromToken;
|
|
4864
|
-
const [jwtError, claims] =
|
|
5947
|
+
const [jwtError, claims] = catchError2(() => parseJWT(accessToken));
|
|
4865
5948
|
if (!jwtError && claims) {
|
|
4866
5949
|
const rawOrgId = claims.prtId ?? claims.organizationId ?? claims.prt_id;
|
|
4867
5950
|
if (typeof rawOrgId === "string" && rawOrgId.length > 0) {
|
|
@@ -4888,7 +5971,7 @@ var tryRobotClientFallback = async (options = {}) => {
|
|
|
4888
5971
|
} catch {
|
|
4889
5972
|
return;
|
|
4890
5973
|
} finally {
|
|
4891
|
-
await
|
|
5974
|
+
await catchError2(() => withTimeout(proxy.CloseAsync(), CLOSE_TIMEOUT_MS));
|
|
4892
5975
|
}
|
|
4893
5976
|
};
|
|
4894
5977
|
|
|
@@ -4958,9 +6041,9 @@ var errorCode = (err) => {
|
|
|
4958
6041
|
}
|
|
4959
6042
|
return "EUNKNOWN";
|
|
4960
6043
|
};
|
|
4961
|
-
var probeAsync = async (
|
|
6044
|
+
var probeAsync = async (fs2, candidate) => {
|
|
4962
6045
|
try {
|
|
4963
|
-
const stats = await
|
|
6046
|
+
const stats = await fs2.stat(candidate);
|
|
4964
6047
|
if (stats === null) {
|
|
4965
6048
|
return { exists: false };
|
|
4966
6049
|
}
|
|
@@ -4987,9 +6070,9 @@ var probeAsync = async (fs, candidate) => {
|
|
|
4987
6070
|
}
|
|
4988
6071
|
};
|
|
4989
6072
|
var resolveEnvFileLocationAsync = async (envFilePath = DEFAULT_ENV_FILENAME, opts) => {
|
|
4990
|
-
const
|
|
4991
|
-
if (
|
|
4992
|
-
const probe2 = await probeAsync(
|
|
6073
|
+
const fs2 = getFileSystem();
|
|
6074
|
+
if (fs2.path.isAbsolute(envFilePath)) {
|
|
6075
|
+
const probe2 = await probeAsync(fs2, envFilePath);
|
|
4993
6076
|
return probe2.exists ? { exists: true, absolutePath: envFilePath, source: "absolute" } : {
|
|
4994
6077
|
exists: false,
|
|
4995
6078
|
absolutePath: envFilePath,
|
|
@@ -4997,11 +6080,11 @@ var resolveEnvFileLocationAsync = async (envFilePath = DEFAULT_ENV_FILENAME, opt
|
|
|
4997
6080
|
...probe2.unusable ? { unusable: probe2.unusable } : {}
|
|
4998
6081
|
};
|
|
4999
6082
|
}
|
|
5000
|
-
const cwd = opts?.cwd ??
|
|
6083
|
+
const cwd = opts?.cwd ?? fs2.env.cwd();
|
|
5001
6084
|
let searchDir = cwd;
|
|
5002
6085
|
while (true) {
|
|
5003
|
-
const candidate =
|
|
5004
|
-
const probe2 = await probeAsync(
|
|
6086
|
+
const candidate = fs2.path.join(searchDir, envFilePath);
|
|
6087
|
+
const probe2 = await probeAsync(fs2, candidate);
|
|
5005
6088
|
if (probe2.exists) {
|
|
5006
6089
|
return {
|
|
5007
6090
|
exists: true,
|
|
@@ -5009,14 +6092,14 @@ var resolveEnvFileLocationAsync = async (envFilePath = DEFAULT_ENV_FILENAME, opt
|
|
|
5009
6092
|
source: searchDir === cwd ? "cwd" : "ancestor"
|
|
5010
6093
|
};
|
|
5011
6094
|
}
|
|
5012
|
-
const parentDir =
|
|
6095
|
+
const parentDir = fs2.path.dirname(searchDir);
|
|
5013
6096
|
if (parentDir === searchDir) {
|
|
5014
6097
|
break;
|
|
5015
6098
|
}
|
|
5016
6099
|
searchDir = parentDir;
|
|
5017
6100
|
}
|
|
5018
|
-
const homePath =
|
|
5019
|
-
const probe = await probeAsync(
|
|
6101
|
+
const homePath = fs2.path.join(fs2.env.homedir(), envFilePath);
|
|
6102
|
+
const probe = await probeAsync(fs2, homePath);
|
|
5020
6103
|
if (probe.exists) {
|
|
5021
6104
|
return { exists: true, absolutePath: homePath, source: "home" };
|
|
5022
6105
|
}
|
|
@@ -5038,12 +6121,12 @@ var resolveEnvFilePathAsync = async (envFilePath = DEFAULT_ENV_FILENAME, opts) =
|
|
|
5038
6121
|
};
|
|
5039
6122
|
};
|
|
5040
6123
|
var loadEnvFileAsync = async ({ envPath }) => {
|
|
5041
|
-
const
|
|
5042
|
-
const absolutePath =
|
|
5043
|
-
if (!await
|
|
6124
|
+
const fs2 = getFileSystem();
|
|
6125
|
+
const absolutePath = fs2.path.isAbsolute(envPath) ? envPath : fs2.path.join(fs2.env.cwd(), envPath);
|
|
6126
|
+
if (!await fs2.exists(absolutePath)) {
|
|
5044
6127
|
throw new Error(`Environment file not found: ${envPath}`);
|
|
5045
6128
|
}
|
|
5046
|
-
const content = await
|
|
6129
|
+
const content = await fs2.readFile(absolutePath, "utf-8");
|
|
5047
6130
|
if (content === null) {
|
|
5048
6131
|
throw new Error(`Environment file not found: ${envPath}`);
|
|
5049
6132
|
}
|
|
@@ -5072,10 +6155,10 @@ var saveEnvFileAsync = async ({
|
|
|
5072
6155
|
data,
|
|
5073
6156
|
merge = true
|
|
5074
6157
|
}) => {
|
|
5075
|
-
const
|
|
5076
|
-
const absolutePath =
|
|
6158
|
+
const fs2 = getFileSystem();
|
|
6159
|
+
const absolutePath = fs2.path.isAbsolute(envPath) ? envPath : fs2.path.join(fs2.env.homedir(), envPath);
|
|
5077
6160
|
let existingData = {};
|
|
5078
|
-
if (merge && await
|
|
6161
|
+
if (merge && await fs2.exists(absolutePath)) {
|
|
5079
6162
|
try {
|
|
5080
6163
|
existingData = await loadEnvFileAsync({ envPath: absolutePath });
|
|
5081
6164
|
} catch {}
|
|
@@ -5093,11 +6176,11 @@ var saveEnvFileAsync = async ({
|
|
|
5093
6176
|
const content = `${lines.join(`
|
|
5094
6177
|
`)}
|
|
5095
6178
|
`;
|
|
5096
|
-
const dir =
|
|
5097
|
-
await
|
|
6179
|
+
const dir = fs2.path.dirname(absolutePath);
|
|
6180
|
+
await fs2.mkdir(dir);
|
|
5098
6181
|
const tempPath = `${absolutePath}.tmp`;
|
|
5099
|
-
await
|
|
5100
|
-
await
|
|
6182
|
+
await fs2.writeFile(tempPath, content);
|
|
6183
|
+
await fs2.rename(tempPath, absolutePath);
|
|
5101
6184
|
};
|
|
5102
6185
|
|
|
5103
6186
|
// ../auth/src/loginStatus.ts
|
|
@@ -5211,11 +6294,11 @@ async function loadFileCredentials(loadEnvFile, absolutePath) {
|
|
|
5211
6294
|
return { credentials };
|
|
5212
6295
|
}
|
|
5213
6296
|
async function getGlobalCredsHint(getFs, loadEnvFile, absolutePath, envFilePath) {
|
|
5214
|
-
const
|
|
5215
|
-
const globalPath =
|
|
6297
|
+
const fs2 = getFs();
|
|
6298
|
+
const globalPath = fs2.path.join(fs2.env.homedir(), envFilePath);
|
|
5216
6299
|
if (absolutePath === globalPath)
|
|
5217
6300
|
return;
|
|
5218
|
-
if (!await
|
|
6301
|
+
if (!await fs2.exists(globalPath))
|
|
5219
6302
|
return;
|
|
5220
6303
|
try {
|
|
5221
6304
|
const globalCreds = await loadEnvFile({ envPath: globalPath });
|
|
@@ -5619,6 +6702,7 @@ var TENANT_SELECTION_CODES = new Set([
|
|
|
5619
6702
|
]);
|
|
5620
6703
|
// src/client.ts
|
|
5621
6704
|
var PM_API_VERSION = "v38";
|
|
6705
|
+
var PMT_API_VERSION = "v6.0";
|
|
5622
6706
|
async function createPmConfig(tenantOverride) {
|
|
5623
6707
|
const ctx = await getAuthContext({
|
|
5624
6708
|
tenant: tenantOverride,
|
|
@@ -5633,8 +6717,11 @@ async function createPmConfig(tenantOverride) {
|
|
|
5633
6717
|
authToken: ctx.accessToken
|
|
5634
6718
|
};
|
|
5635
6719
|
}
|
|
5636
|
-
function buildPmUrl(config,
|
|
5637
|
-
return `${config.baseUrl}/${config.organizationName}/${config.tenantName}/processmining_/api/${PM_API_VERSION}${
|
|
6720
|
+
function buildPmUrl(config, path2) {
|
|
6721
|
+
return `${config.baseUrl}/${config.organizationName}/${config.tenantName}/processmining_/api/${PM_API_VERSION}${path2}`;
|
|
6722
|
+
}
|
|
6723
|
+
function buildPmtUrl(config, path2) {
|
|
6724
|
+
return `${config.baseUrl}/${config.organizationName}/${config.tenantName}/processmining_/api/pmt/${PMT_API_VERSION}${path2}`;
|
|
5638
6725
|
}
|
|
5639
6726
|
function buildHeaders(config) {
|
|
5640
6727
|
return {
|
|
@@ -5662,14 +6749,14 @@ async function toApiError(response) {
|
|
|
5662
6749
|
function parseJsonBody(text) {
|
|
5663
6750
|
if (!text)
|
|
5664
6751
|
return null;
|
|
5665
|
-
const [parseErr, parsed] =
|
|
6752
|
+
const [parseErr, parsed] = catchError(() => JSON.parse(text));
|
|
5666
6753
|
if (parseErr) {
|
|
5667
6754
|
throw new Error(`Failed to parse API response body: ${parseErr.message}`);
|
|
5668
6755
|
}
|
|
5669
6756
|
return parsed;
|
|
5670
6757
|
}
|
|
5671
|
-
async function pmRequest(config, method,
|
|
5672
|
-
const response = await fetch(buildPmUrl(config,
|
|
6758
|
+
async function pmRequest(config, method, path2, body) {
|
|
6759
|
+
const response = await fetch(buildPmUrl(config, path2), {
|
|
5673
6760
|
method,
|
|
5674
6761
|
headers: buildHeaders(config),
|
|
5675
6762
|
body: body === undefined ? undefined : JSON.stringify(body)
|
|
@@ -5678,20 +6765,20 @@ async function pmRequest(config, method, path, body) {
|
|
|
5678
6765
|
throw await toApiError(response);
|
|
5679
6766
|
return parseJsonBody(await response.text());
|
|
5680
6767
|
}
|
|
5681
|
-
async function pmGet(config,
|
|
5682
|
-
const result = await pmRequest(config, "GET",
|
|
6768
|
+
async function pmGet(config, path2) {
|
|
6769
|
+
const result = await pmRequest(config, "GET", path2);
|
|
5683
6770
|
if (result === null)
|
|
5684
6771
|
throw new Error("API returned an empty response body");
|
|
5685
6772
|
return result;
|
|
5686
6773
|
}
|
|
5687
|
-
async function pmPost(config,
|
|
5688
|
-
return pmRequest(config, "POST",
|
|
6774
|
+
async function pmPost(config, path2, body) {
|
|
6775
|
+
return pmRequest(config, "POST", path2, body);
|
|
5689
6776
|
}
|
|
5690
|
-
async function pmDelete(config,
|
|
5691
|
-
return pmRequest(config, "DELETE",
|
|
6777
|
+
async function pmDelete(config, path2, body) {
|
|
6778
|
+
return pmRequest(config, "DELETE", path2, body);
|
|
5692
6779
|
}
|
|
5693
|
-
async function pmGetRaw(config,
|
|
5694
|
-
const response = await fetch(buildPmUrl(config,
|
|
6780
|
+
async function pmGetRaw(config, path2) {
|
|
6781
|
+
const response = await fetch(buildPmUrl(config, path2), {
|
|
5695
6782
|
method: "GET",
|
|
5696
6783
|
headers: { Authorization: `Bearer ${config.authToken}` }
|
|
5697
6784
|
});
|
|
@@ -5702,8 +6789,8 @@ async function pmGetRaw(config, path) {
|
|
|
5702
6789
|
etag: response.headers.get("etag")
|
|
5703
6790
|
};
|
|
5704
6791
|
}
|
|
5705
|
-
async function pmPutJson(config,
|
|
5706
|
-
const response = await fetch(buildPmUrl(config,
|
|
6792
|
+
async function pmPutJson(config, path2, body, etag) {
|
|
6793
|
+
const response = await fetch(buildPmUrl(config, path2), {
|
|
5707
6794
|
method: "PUT",
|
|
5708
6795
|
headers: {
|
|
5709
6796
|
Authorization: `Bearer ${config.authToken}`,
|
|
@@ -5717,14 +6804,76 @@ async function pmPutJson(config, path, body, etag) {
|
|
|
5717
6804
|
throw await toApiError(response);
|
|
5718
6805
|
return parseJsonBody(await response.text());
|
|
5719
6806
|
}
|
|
5720
|
-
|
|
5721
|
-
|
|
6807
|
+
var APP_TOKEN_REFRESH_MARGIN_SECONDS = 60;
|
|
6808
|
+
var APP_TOKEN_FALLBACK_TTL_SECONDS = 300;
|
|
6809
|
+
var appTokenCache = new Map;
|
|
6810
|
+
function appTokenCacheKey(config, appId) {
|
|
6811
|
+
return `${config.baseUrl}|${config.organizationName}|${config.tenantName}|${appId}`;
|
|
6812
|
+
}
|
|
6813
|
+
function readTokenExpirySeconds(token) {
|
|
6814
|
+
const payload = token.split(".")[1];
|
|
6815
|
+
if (!payload)
|
|
6816
|
+
return null;
|
|
6817
|
+
const [err, exp] = catchError(() => {
|
|
6818
|
+
const b64 = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
6819
|
+
const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
|
|
6820
|
+
const claims = JSON.parse(atob(padded));
|
|
6821
|
+
return typeof claims.exp === "number" ? claims.exp : null;
|
|
6822
|
+
});
|
|
6823
|
+
return err ? null : exp;
|
|
6824
|
+
}
|
|
6825
|
+
async function getAppToken(config, appId, forceRefresh = false) {
|
|
6826
|
+
const key = appTokenCacheKey(config, appId);
|
|
6827
|
+
const cached = appTokenCache.get(key);
|
|
6828
|
+
if (!forceRefresh && cached && cached.expiresAtMs > Date.now()) {
|
|
6829
|
+
return cached.token;
|
|
6830
|
+
}
|
|
6831
|
+
appTokenCache.delete(key);
|
|
6832
|
+
const result = await pmGet(config, `/apps/${encodeURIComponent(appId)}/token`);
|
|
6833
|
+
const token = result.accessToken;
|
|
6834
|
+
if (!token) {
|
|
6835
|
+
throw new Error("App token response did not contain an access token");
|
|
6836
|
+
}
|
|
6837
|
+
const expSeconds = readTokenExpirySeconds(token);
|
|
6838
|
+
const ttlSeconds = expSeconds === null ? APP_TOKEN_FALLBACK_TTL_SECONDS : expSeconds - Math.floor(Date.now() / 1000) - APP_TOKEN_REFRESH_MARGIN_SECONDS;
|
|
6839
|
+
if (ttlSeconds > 0) {
|
|
6840
|
+
appTokenCache.set(key, {
|
|
6841
|
+
token,
|
|
6842
|
+
expiresAtMs: Date.now() + ttlSeconds * 1000
|
|
6843
|
+
});
|
|
6844
|
+
}
|
|
6845
|
+
return token;
|
|
6846
|
+
}
|
|
6847
|
+
async function pmtFetch(config, appId, path2, forceRefresh) {
|
|
6848
|
+
const token = await getAppToken(config, appId, forceRefresh);
|
|
6849
|
+
return fetch(buildPmtUrl(config, path2), {
|
|
6850
|
+
method: "GET",
|
|
6851
|
+
headers: {
|
|
6852
|
+
Authorization: `Bearer ${token}`,
|
|
6853
|
+
Accept: "application/json"
|
|
6854
|
+
}
|
|
6855
|
+
});
|
|
6856
|
+
}
|
|
6857
|
+
async function pmtGet(config, appId, path2) {
|
|
6858
|
+
let response = await pmtFetch(config, appId, path2, false);
|
|
6859
|
+
if (response.status === 401) {
|
|
6860
|
+
response = await pmtFetch(config, appId, path2, true);
|
|
6861
|
+
}
|
|
6862
|
+
if (!response.ok)
|
|
6863
|
+
throw await toApiError(response);
|
|
6864
|
+
const result = parseJsonBody(await response.text());
|
|
6865
|
+
if (result === null)
|
|
6866
|
+
throw new Error("API returned an empty response body");
|
|
6867
|
+
return result;
|
|
6868
|
+
}
|
|
6869
|
+
async function pmPutRaw(config, path2, content, etag) {
|
|
6870
|
+
return putRaw(config, path2, content, { "If-Match": etag });
|
|
5722
6871
|
}
|
|
5723
|
-
async function pmCreateRaw(config,
|
|
5724
|
-
return putRaw(config,
|
|
6872
|
+
async function pmCreateRaw(config, path2, content) {
|
|
6873
|
+
return putRaw(config, path2, content);
|
|
5725
6874
|
}
|
|
5726
|
-
async function
|
|
5727
|
-
const response = await fetch(buildPmUrl(config,
|
|
6875
|
+
async function putRawResponse(config, path2, content, extraHeaders) {
|
|
6876
|
+
const response = await fetch(buildPmUrl(config, path2), {
|
|
5728
6877
|
method: "PUT",
|
|
5729
6878
|
headers: {
|
|
5730
6879
|
Authorization: `Bearer ${config.authToken}`,
|
|
@@ -5735,7 +6884,14 @@ async function putRaw(config, path, content, extraHeaders) {
|
|
|
5735
6884
|
});
|
|
5736
6885
|
if (!response.ok)
|
|
5737
6886
|
throw await toApiError(response);
|
|
5738
|
-
return response
|
|
6887
|
+
return response;
|
|
6888
|
+
}
|
|
6889
|
+
async function putRaw(config, path2, content, extraHeaders) {
|
|
6890
|
+
return (await putRawResponse(config, path2, content, extraHeaders)).headers.get("etag");
|
|
6891
|
+
}
|
|
6892
|
+
async function pmPutBinaryJson(config, path2, content) {
|
|
6893
|
+
const response = await putRawResponse(config, path2, content);
|
|
6894
|
+
return parseJsonBody(await response.text());
|
|
5739
6895
|
}
|
|
5740
6896
|
|
|
5741
6897
|
// src/commands/_shared.ts
|
|
@@ -5754,7 +6910,7 @@ function rerunInstructions(command) {
|
|
|
5754
6910
|
return "Someone else changed this resource while the command was running, so the write " + `was rejected. Re-run '${command}' — it reads the latest version and re-applies ` + "your change on top of it.";
|
|
5755
6911
|
}
|
|
5756
6912
|
async function loadConfigOrExit() {
|
|
5757
|
-
const [configErr, config] = await
|
|
6913
|
+
const [configErr, config] = await catchError(createPmConfig());
|
|
5758
6914
|
if (configErr) {
|
|
5759
6915
|
fail(configErr.message, "Run 'uip login' to authenticate first.");
|
|
5760
6916
|
return null;
|
|
@@ -5792,12 +6948,13 @@ async function resolveJsonBody(file, inline, flag = "body") {
|
|
|
5792
6948
|
} else {
|
|
5793
6949
|
throw new Error(`A ${noun} is required: pass --${flag} <json-file> or --${flag}-json <json>.`);
|
|
5794
6950
|
}
|
|
5795
|
-
const [parseErr, parsed] =
|
|
6951
|
+
const [parseErr, parsed] = catchError(() => JSON.parse(raw));
|
|
5796
6952
|
if (parseErr) {
|
|
5797
6953
|
throw new Error(`${Noun} is not valid JSON: ${parseErr.message}`);
|
|
5798
6954
|
}
|
|
5799
6955
|
return parsed;
|
|
5800
6956
|
}
|
|
6957
|
+
var sanitizeKey = (s) => s.replace(/[^A-Za-z0-9]/g, "").toLowerCase();
|
|
5801
6958
|
var TERMINAL_STATUSES2 = new Set([
|
|
5802
6959
|
"SUCCESS",
|
|
5803
6960
|
"SUCCESS_WITH_WARNINGS",
|
|
@@ -5807,7 +6964,7 @@ var TERMINAL_STATUSES2 = new Set([
|
|
|
5807
6964
|
"CANCELLED",
|
|
5808
6965
|
"CANCELED"
|
|
5809
6966
|
]);
|
|
5810
|
-
var sleep = (ms) => new Promise((
|
|
6967
|
+
var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
5811
6968
|
var isTerminal = (status) => status !== undefined && status !== "" && TERMINAL_STATUSES2.has(status.toUpperCase());
|
|
5812
6969
|
var DEFAULT_TIMEOUT_SECONDS = 1800;
|
|
5813
6970
|
var DEFAULT_POLL_INTERVAL_SECONDS = 5;
|
|
@@ -5855,7 +7012,7 @@ async function waitForIngestion(config, appId, stage, options, before = {}) {
|
|
|
5855
7012
|
async function collectFailureMessages(config, appId, stage, ingestionId) {
|
|
5856
7013
|
if (!ingestionId)
|
|
5857
7014
|
return [];
|
|
5858
|
-
const [err, res] = await
|
|
7015
|
+
const [err, res] = await catchError(pmGet(config, `/apps/${appId}/${stage}/logs/${ingestionId}?pageNumber=1&pageSize=200`));
|
|
5859
7016
|
if (err)
|
|
5860
7017
|
return [];
|
|
5861
7018
|
return errorMessagesFrom(res);
|
|
@@ -5914,13 +7071,13 @@ async function waitForBuild(config, appId, options, before = {}) {
|
|
|
5914
7071
|
}
|
|
5915
7072
|
}
|
|
5916
7073
|
async function collectBuildFailureMessages(config, appId) {
|
|
5917
|
-
const [err, res] = await
|
|
7074
|
+
const [err, res] = await catchError(pmGet(config, `/apps/${appId}/dev/transformation/build/logs`));
|
|
5918
7075
|
if (err)
|
|
5919
7076
|
return [];
|
|
5920
7077
|
return errorMessagesFrom(res);
|
|
5921
7078
|
}
|
|
5922
7079
|
async function waitAndReportBuild(config, appId, options, code, before = {}) {
|
|
5923
|
-
const [waitErr, result] = await
|
|
7080
|
+
const [waitErr, result] = await catchError(waitForBuild(config, appId, options, before));
|
|
5924
7081
|
if (waitErr) {
|
|
5925
7082
|
fail(waitErr.message, `Increase --timeout, or check progress with 'uip pm transformations status ${appId}'.`);
|
|
5926
7083
|
return;
|
|
@@ -5939,7 +7096,7 @@ ${messages.join(`
|
|
|
5939
7096
|
});
|
|
5940
7097
|
}
|
|
5941
7098
|
async function waitAndReport(config, appId, options, code, noun, before = {}) {
|
|
5942
|
-
const [waitErr, result] = await
|
|
7099
|
+
const [waitErr, result] = await catchError(waitForIngestion(config, appId, options.stage, options, before));
|
|
5943
7100
|
if (waitErr) {
|
|
5944
7101
|
fail(waitErr.message, "Increase --timeout, or check progress with 'uip pm apps list'.");
|
|
5945
7102
|
return;
|
|
@@ -5975,7 +7132,7 @@ function registerAppTypesCommand(program2) {
|
|
|
5975
7132
|
const config = await loadConfigOrExit();
|
|
5976
7133
|
if (!config)
|
|
5977
7134
|
return;
|
|
5978
|
-
const [apiErr, result] = await
|
|
7135
|
+
const [apiErr, result] = await catchError(pmGet(config, "/appTypes"));
|
|
5979
7136
|
if (apiErr) {
|
|
5980
7137
|
fail(apiErr.message, "Check your authentication and that Process Mining is enabled on this tenant.");
|
|
5981
7138
|
return;
|
|
@@ -5990,7 +7147,7 @@ function registerAppTypesCommand(program2) {
|
|
|
5990
7147
|
const config = await loadConfigOrExit();
|
|
5991
7148
|
if (!config)
|
|
5992
7149
|
return;
|
|
5993
|
-
const [apiErr, result] = await
|
|
7150
|
+
const [apiErr, result] = await catchError(pmGet(config, `/appTypes/${encodeURIComponent(appTypeKey)}/${encodeURIComponent(appTypeVersion)}`));
|
|
5994
7151
|
if (apiErr) {
|
|
5995
7152
|
fail(apiErr.message, "Check the app type key and version (uip pm app-types list).");
|
|
5996
7153
|
return;
|
|
@@ -6072,13 +7229,13 @@ function findDashboard(dashboards, selector) {
|
|
|
6072
7229
|
const known = dashboards.map((entry) => `${entry.id} (${entry.name})`).join(", ");
|
|
6073
7230
|
throw new Error(`No dashboard matched '${selector}'. Known dashboards: ${known || "none"}.`);
|
|
6074
7231
|
}
|
|
6075
|
-
async function readJsonFile(
|
|
6076
|
-
const content = await getFileSystem().readFile(
|
|
7232
|
+
async function readJsonFile(path2) {
|
|
7233
|
+
const content = await getFileSystem().readFile(path2, "utf-8");
|
|
6077
7234
|
if (content === null)
|
|
6078
|
-
throw new Error(`Local file not found: ${
|
|
6079
|
-
const [parseErr, parsed] =
|
|
7235
|
+
throw new Error(`Local file not found: ${path2}`);
|
|
7236
|
+
const [parseErr, parsed] = catchError(() => JSON.parse(String(content)));
|
|
6080
7237
|
if (parseErr) {
|
|
6081
|
-
throw new Error(`${
|
|
7238
|
+
throw new Error(`${path2} is not valid JSON: ${parseErr.message}`);
|
|
6082
7239
|
}
|
|
6083
7240
|
return parsed;
|
|
6084
7241
|
}
|
|
@@ -6128,7 +7285,7 @@ function registerModelDashboardCommands(modelCmd) {
|
|
|
6128
7285
|
const config = await loadConfigOrExit();
|
|
6129
7286
|
if (!config)
|
|
6130
7287
|
return;
|
|
6131
|
-
const [apiErr, result] = await
|
|
7288
|
+
const [apiErr, result] = await catchError(readModel(config, appId, options.stage));
|
|
6132
7289
|
if (apiErr) {
|
|
6133
7290
|
fail(apiErr.message, "Check the app id (uip pm apps list) and your authentication.");
|
|
6134
7291
|
return;
|
|
@@ -6150,14 +7307,14 @@ function registerModelDashboardCommands(modelCmd) {
|
|
|
6150
7307
|
const config = await loadConfigOrExit();
|
|
6151
7308
|
if (!config)
|
|
6152
7309
|
return;
|
|
6153
|
-
const [apiErr, result] = await
|
|
7310
|
+
const [apiErr, result] = await catchError(readModel(config, appId, options.stage));
|
|
6154
7311
|
if (apiErr) {
|
|
6155
7312
|
fail(apiErr.message, "Check the app id (uip pm apps list) and your authentication.");
|
|
6156
7313
|
return;
|
|
6157
7314
|
}
|
|
6158
7315
|
let payload = result.model.view ?? {};
|
|
6159
7316
|
if (options.dashboard !== undefined) {
|
|
6160
|
-
const [selectErr, selected] =
|
|
7317
|
+
const [selectErr, selected] = catchError(() => findDashboard(readDashboards(result.model), options.dashboard));
|
|
6161
7318
|
if (selectErr) {
|
|
6162
7319
|
fail(selectErr.message, `List them with 'uip pm apps model dashboards list ${appId}'.`);
|
|
6163
7320
|
return;
|
|
@@ -6166,7 +7323,7 @@ function registerModelDashboardCommands(modelCmd) {
|
|
|
6166
7323
|
}
|
|
6167
7324
|
const serialized = JSON.stringify(payload, null, 2);
|
|
6168
7325
|
if (options.destination !== undefined) {
|
|
6169
|
-
const [writeErr] = await
|
|
7326
|
+
const [writeErr] = await catchError(getFileSystem().writeFile(options.destination, serialized));
|
|
6170
7327
|
if (writeErr) {
|
|
6171
7328
|
fail(writeErr.message, "Check the destination path and that the disk is writable.");
|
|
6172
7329
|
return;
|
|
@@ -6186,7 +7343,7 @@ function registerModelDashboardCommands(modelCmd) {
|
|
|
6186
7343
|
const config = await loadConfigOrExit();
|
|
6187
7344
|
if (!config)
|
|
6188
7345
|
return;
|
|
6189
|
-
const [err, versions] = await
|
|
7346
|
+
const [err, versions] = await catchError(writeDashboards(config, appId, options));
|
|
6190
7347
|
if (err) {
|
|
6191
7348
|
fail(err.message, isConflictError(err) ? conflictInstructions(`uip pm apps model dashboards get ${appId} --destination <file>`) : "Check the JSON file, and that --etag is the ETag " + `'uip pm apps model dashboards get ${appId}' returns.`);
|
|
6192
7349
|
return;
|
|
@@ -6206,7 +7363,7 @@ function registerModelDashboardCommands(modelCmd) {
|
|
|
6206
7363
|
const config = await loadConfigOrExit();
|
|
6207
7364
|
if (!config)
|
|
6208
7365
|
return;
|
|
6209
|
-
const [apiErr, result] = await
|
|
7366
|
+
const [apiErr, result] = await catchError(readModel(config, appId, options.stage));
|
|
6210
7367
|
if (apiErr) {
|
|
6211
7368
|
fail(apiErr.message, "Check the app id (uip pm apps list) and your authentication.");
|
|
6212
7369
|
return;
|
|
@@ -6339,7 +7496,7 @@ function registerAppsCommand(program2) {
|
|
|
6339
7496
|
const config = await loadConfigOrExit();
|
|
6340
7497
|
if (!config)
|
|
6341
7498
|
return;
|
|
6342
|
-
const [apiErr, result] = await
|
|
7499
|
+
const [apiErr, result] = await catchError(pmGet(config, `/apps?stage=${options.stage}`));
|
|
6343
7500
|
if (apiErr) {
|
|
6344
7501
|
fail(apiErr.message, "Check your authentication and that Process Mining is enabled on this tenant.");
|
|
6345
7502
|
return;
|
|
@@ -6354,7 +7511,7 @@ function registerAppsCommand(program2) {
|
|
|
6354
7511
|
const config = await loadConfigOrExit();
|
|
6355
7512
|
if (!config)
|
|
6356
7513
|
return;
|
|
6357
|
-
const [apiErr, result] = await
|
|
7514
|
+
const [apiErr, result] = await catchError(pmGet(config, `/apps/${appId}/${options.stage}`));
|
|
6358
7515
|
if (apiErr) {
|
|
6359
7516
|
fail(apiErr.message, "Check the app id (uip pm apps list) and your authentication.");
|
|
6360
7517
|
return;
|
|
@@ -6369,7 +7526,7 @@ function registerAppsCommand(program2) {
|
|
|
6369
7526
|
const config = await loadConfigOrExit();
|
|
6370
7527
|
if (!config)
|
|
6371
7528
|
return;
|
|
6372
|
-
const [err, appId] = await
|
|
7529
|
+
const [err, appId] = await catchError(createApp(config, name, options));
|
|
6373
7530
|
if (err) {
|
|
6374
7531
|
fail(err.message, "Check the app type key/version (uip pm app-types list) and the data mapping file.");
|
|
6375
7532
|
return;
|
|
@@ -6386,7 +7543,7 @@ function registerAppsCommand(program2) {
|
|
|
6386
7543
|
const config = await loadConfigOrExit();
|
|
6387
7544
|
if (!config)
|
|
6388
7545
|
return;
|
|
6389
|
-
const [err] = await
|
|
7546
|
+
const [err] = await catchError(pmDelete(config, `/apps/${appId}`));
|
|
6390
7547
|
if (err) {
|
|
6391
7548
|
fail(err.message, "Check the app id (uip pm apps list).");
|
|
6392
7549
|
return;
|
|
@@ -6401,7 +7558,7 @@ function registerAppsCommand(program2) {
|
|
|
6401
7558
|
const config = await loadConfigOrExit();
|
|
6402
7559
|
if (!config)
|
|
6403
7560
|
return;
|
|
6404
|
-
const [err, result] = await
|
|
7561
|
+
const [err, result] = await catchError(publishApp(config, appId));
|
|
6405
7562
|
if (err) {
|
|
6406
7563
|
fail(err.message, "Check the app id (uip pm apps list) and that there are dev changes to publish.");
|
|
6407
7564
|
return;
|
|
@@ -6425,7 +7582,7 @@ function registerAppsCommand(program2) {
|
|
|
6425
7582
|
const config = await loadConfigOrExit();
|
|
6426
7583
|
if (!config)
|
|
6427
7584
|
return;
|
|
6428
|
-
const [err, changes] = await
|
|
7585
|
+
const [err, changes] = await catchError(readDevChanges(config, appId));
|
|
6429
7586
|
if (err) {
|
|
6430
7587
|
fail(err.message, "Check the app id (uip pm apps list).");
|
|
6431
7588
|
return;
|
|
@@ -6446,7 +7603,7 @@ function registerAppsCommand(program2) {
|
|
|
6446
7603
|
if (options.sinceVersion !== undefined)
|
|
6447
7604
|
query.push(`sinceVersion=${encodeURIComponent(options.sinceVersion)}`);
|
|
6448
7605
|
const suffix = query.length === 0 ? "" : `?${query.join("&")}`;
|
|
6449
|
-
const [apiErr, result] = await
|
|
7606
|
+
const [apiErr, result] = await catchError(pmGet(config, `/apps/${appId}/publications${suffix}`));
|
|
6450
7607
|
if (apiErr) {
|
|
6451
7608
|
fail(apiErr.message, "Check the app id (uip pm apps list).");
|
|
6452
7609
|
return;
|
|
@@ -6468,7 +7625,7 @@ function registerAppsCommand(program2) {
|
|
|
6468
7625
|
const config = await loadConfigOrExit();
|
|
6469
7626
|
if (!config)
|
|
6470
7627
|
return;
|
|
6471
|
-
const [err, added] = await
|
|
7628
|
+
const [err, added] = await catchError(addModelTables(config, appId, options));
|
|
6472
7629
|
if (err) {
|
|
6473
7630
|
fail(err.message, isConflictError(err) ? rerunInstructions(`uip pm apps data-model add-table ${appId} --file ${options.file}`) : "Check the app id and the --file JSON shape.");
|
|
6474
7631
|
return;
|
|
@@ -6495,7 +7652,7 @@ function registerAppsCommand(program2) {
|
|
|
6495
7652
|
const config = await loadConfigOrExit();
|
|
6496
7653
|
if (!config)
|
|
6497
7654
|
return;
|
|
6498
|
-
const [err, versions] = await
|
|
7655
|
+
const [err, versions] = await catchError(updateSemanticModel(config, appId, options));
|
|
6499
7656
|
if (err) {
|
|
6500
7657
|
fail(err.message, isConflictError(err) ? conflictInstructions(`uip pm apps model get ${appId} --destination <file>`) : modelWriteHint(err));
|
|
6501
7658
|
return;
|
|
@@ -6515,7 +7672,7 @@ function registerAppsCommand(program2) {
|
|
|
6515
7672
|
const config = await loadConfigOrExit();
|
|
6516
7673
|
if (!config)
|
|
6517
7674
|
return;
|
|
6518
|
-
const [err, file] = await
|
|
7675
|
+
const [err, file] = await catchError(pmGetRaw(config, `/apps/${appId}/${options.stage}/model`));
|
|
6519
7676
|
if (err) {
|
|
6520
7677
|
fail(err.message, "Check the app id (uip pm apps list).");
|
|
6521
7678
|
return;
|
|
@@ -6535,12 +7692,12 @@ function registerAppsCommand(program2) {
|
|
|
6535
7692
|
return;
|
|
6536
7693
|
}
|
|
6537
7694
|
const hasExpression = options.expression !== undefined;
|
|
6538
|
-
const [parseErr, expression] = hasExpression ? await
|
|
7695
|
+
const [parseErr, expression] = hasExpression ? await catchError(readExpressionArg(options.expression)) : [null, undefined];
|
|
6539
7696
|
if (parseErr) {
|
|
6540
7697
|
fail(parseErr.message, "--expression must be a JSON expression node (inline or @file.json).");
|
|
6541
7698
|
return;
|
|
6542
7699
|
}
|
|
6543
|
-
const [err, outcome] = await
|
|
7700
|
+
const [err, outcome] = await catchError(editSemanticModel(config, appId, (model) => upsertModelField(model, fieldId, {
|
|
6544
7701
|
kind: options.kind,
|
|
6545
7702
|
display: options.displayName,
|
|
6546
7703
|
expression,
|
|
@@ -6568,7 +7725,7 @@ function registerAppsCommand(program2) {
|
|
|
6568
7725
|
const config = await loadConfigOrExit();
|
|
6569
7726
|
if (!config)
|
|
6570
7727
|
return;
|
|
6571
|
-
const [err, outcome] = await
|
|
7728
|
+
const [err, outcome] = await catchError(editSemanticModel(config, appId, (model) => removeModelField(model, fieldId)));
|
|
6572
7729
|
if (err) {
|
|
6573
7730
|
fail(err.message, modelWriteHint(err, `uip pm apps model fields remove ${appId} ${fieldId}`));
|
|
6574
7731
|
return;
|
|
@@ -6591,13 +7748,13 @@ function registerAppsCommand(program2) {
|
|
|
6591
7748
|
const config = await loadConfigOrExit();
|
|
6592
7749
|
if (!config)
|
|
6593
7750
|
return;
|
|
6594
|
-
const [err, file] = await
|
|
7751
|
+
const [err, file] = await catchError(pmGetRaw(config, `/apps/${appId}/${options.stage}/inputDataMapping`));
|
|
6595
7752
|
if (err) {
|
|
6596
7753
|
fail(err.message, "Check the app id (uip pm apps list).");
|
|
6597
7754
|
return;
|
|
6598
7755
|
}
|
|
6599
7756
|
if (options.destination !== undefined) {
|
|
6600
|
-
const [writeErr] = await
|
|
7757
|
+
const [writeErr] = await catchError(getFileSystem().writeFile(options.destination, file.content));
|
|
6601
7758
|
if (writeErr) {
|
|
6602
7759
|
fail(writeErr.message, "Check the destination path and that the disk is writable.");
|
|
6603
7760
|
return;
|
|
@@ -6617,7 +7774,7 @@ function registerAppsCommand(program2) {
|
|
|
6617
7774
|
const config = await loadConfigOrExit();
|
|
6618
7775
|
if (!config)
|
|
6619
7776
|
return;
|
|
6620
|
-
const [err, tables] = await
|
|
7777
|
+
const [err, tables] = await catchError(updateDataMapping(config, appId, options));
|
|
6621
7778
|
if (err) {
|
|
6622
7779
|
fail(err.message, isConflictError(err) ? conflictInstructions(`uip pm apps data-mapping get ${appId} --destination <file>`) : "Check the app id, the --file JSON shape, and that " + `--etag is the ETag 'uip pm apps data-mapping get ${appId}' returns.`);
|
|
6623
7780
|
return;
|
|
@@ -6651,8 +7808,8 @@ async function createApp(config, name, options) {
|
|
|
6651
7808
|
}
|
|
6652
7809
|
let dataMapping;
|
|
6653
7810
|
if (options.dataMapping !== undefined) {
|
|
6654
|
-
const
|
|
6655
|
-
const raw = await
|
|
7811
|
+
const fs2 = getFileSystem();
|
|
7812
|
+
const raw = await fs2.readFile(options.dataMapping, "utf-8");
|
|
6656
7813
|
if (raw === null) {
|
|
6657
7814
|
throw new Error(`Data mapping file not found: ${options.dataMapping}`);
|
|
6658
7815
|
}
|
|
@@ -6721,8 +7878,8 @@ async function addModelTables(config, appId, options) {
|
|
|
6721
7878
|
throw new Error(`Table file not found: ${options.file}`);
|
|
6722
7879
|
}
|
|
6723
7880
|
const extra = JSON.parse(String(raw));
|
|
6724
|
-
const
|
|
6725
|
-
const current = await pmGetRaw(config,
|
|
7881
|
+
const path2 = `/apps/${appId}/${options.stage}/dataModel`;
|
|
7882
|
+
const current = await pmGetRaw(config, path2);
|
|
6726
7883
|
if (!current.etag) {
|
|
6727
7884
|
throw new Error(`The data model of app ${appId} was returned without an ETag, so the update cannot be guarded against concurrent edits.`);
|
|
6728
7885
|
}
|
|
@@ -6731,18 +7888,18 @@ async function addModelTables(config, appId, options) {
|
|
|
6731
7888
|
if (added.length === 0) {
|
|
6732
7889
|
throw new Error(`No tables found in ${options.file}: expected a data-model table { name, primaryKey, foreignKeys }, an array of them, or a { tables } object.`);
|
|
6733
7890
|
}
|
|
6734
|
-
await pmPutJson(config,
|
|
7891
|
+
await pmPutJson(config, path2, dataModel, current.etag);
|
|
6735
7892
|
await pmPost(config, `/apps/${appId}/${options.stage}/applyCurrentDatamodel`, {});
|
|
6736
7893
|
return added;
|
|
6737
7894
|
}
|
|
6738
|
-
async function getModelAndMaybeWrite(config,
|
|
6739
|
-
const [err, file] = await
|
|
7895
|
+
async function getModelAndMaybeWrite(config, path2, appId, code, destination) {
|
|
7896
|
+
const [err, file] = await catchError(pmGetRaw(config, path2));
|
|
6740
7897
|
if (err) {
|
|
6741
7898
|
fail(err.message, "Check the app id (uip pm apps list).");
|
|
6742
7899
|
return;
|
|
6743
7900
|
}
|
|
6744
7901
|
if (destination !== undefined) {
|
|
6745
|
-
const [writeErr] = await
|
|
7902
|
+
const [writeErr] = await catchError(getFileSystem().writeFile(destination, file.content));
|
|
6746
7903
|
if (writeErr) {
|
|
6747
7904
|
fail(writeErr.message, "Check the destination path and that the disk is writable.");
|
|
6748
7905
|
return;
|
|
@@ -6779,7 +7936,7 @@ async function readExpressionArg(value) {
|
|
|
6779
7936
|
}
|
|
6780
7937
|
text = String(raw);
|
|
6781
7938
|
}
|
|
6782
|
-
const [parseErr, parsed] =
|
|
7939
|
+
const [parseErr, parsed] = catchError(() => JSON.parse(text));
|
|
6783
7940
|
if (parseErr) {
|
|
6784
7941
|
throw new Error(`Expression is not valid JSON: ${parseErr.message}`);
|
|
6785
7942
|
}
|
|
@@ -6868,14 +8025,14 @@ function removeModelField(model, fieldId) {
|
|
|
6868
8025
|
throw new Error(`Field '${fieldId}' not found (see 'uip pm apps model fields list').`);
|
|
6869
8026
|
}
|
|
6870
8027
|
async function editSemanticModel(config, appId, mutate) {
|
|
6871
|
-
const
|
|
6872
|
-
const current = await pmGetRaw(config,
|
|
8028
|
+
const path2 = `/apps/${appId}/dev/model`;
|
|
8029
|
+
const current = await pmGetRaw(config, path2);
|
|
6873
8030
|
if (!current.etag) {
|
|
6874
8031
|
throw new Error(`The model of app ${appId} was returned without an ETag, so the edit cannot be guarded against concurrent changes.`);
|
|
6875
8032
|
}
|
|
6876
8033
|
const model = JSON.parse(current.content);
|
|
6877
8034
|
const result = mutate(model);
|
|
6878
|
-
const put = await pmPutJson(config,
|
|
8035
|
+
const put = await pmPutJson(config, path2, model, current.etag);
|
|
6879
8036
|
return { result, versions: put?.versions ?? [] };
|
|
6880
8037
|
}
|
|
6881
8038
|
async function updateSemanticModel(config, appId, options) {
|
|
@@ -6883,7 +8040,7 @@ async function updateSemanticModel(config, appId, options) {
|
|
|
6883
8040
|
if (raw === null) {
|
|
6884
8041
|
throw new Error(`Model file not found: ${options.file}`);
|
|
6885
8042
|
}
|
|
6886
|
-
const [parseErr, model] =
|
|
8043
|
+
const [parseErr, model] = catchError(() => JSON.parse(String(raw)));
|
|
6887
8044
|
if (parseErr) {
|
|
6888
8045
|
throw new Error(`Model file is not valid JSON: ${parseErr.message} (${options.file})`);
|
|
6889
8046
|
}
|
|
@@ -6895,7 +8052,7 @@ async function updateDataMapping(config, appId, options) {
|
|
|
6895
8052
|
if (raw === null) {
|
|
6896
8053
|
throw new Error(`Mapping file not found: ${options.file}`);
|
|
6897
8054
|
}
|
|
6898
|
-
const [parseErr, parsed] =
|
|
8055
|
+
const [parseErr, parsed] = catchError(() => JSON.parse(String(raw)));
|
|
6899
8056
|
if (parseErr) {
|
|
6900
8057
|
throw new Error(`Mapping file is not valid JSON: ${parseErr.message} (${options.file})`);
|
|
6901
8058
|
}
|
|
@@ -6956,10 +8113,552 @@ function applyMappingDefaults(mapping) {
|
|
|
6956
8113
|
return mapping;
|
|
6957
8114
|
}
|
|
6958
8115
|
|
|
8116
|
+
// src/commands/conformance.ts
|
|
8117
|
+
var STAGES3 = ["dev", "published"];
|
|
8118
|
+
var CONFORMANCE_STATUS = [
|
|
8119
|
+
"ModelOnly",
|
|
8120
|
+
"LogOnly",
|
|
8121
|
+
"Conforming",
|
|
8122
|
+
"Accepted"
|
|
8123
|
+
];
|
|
8124
|
+
var MODEL_BASED_MINERS = new Set([
|
|
8125
|
+
"inductive",
|
|
8126
|
+
"bpmn",
|
|
8127
|
+
"hybrid-bpmn-inductive"
|
|
8128
|
+
]);
|
|
8129
|
+
var RATE_EXAMPLES = [
|
|
8130
|
+
{
|
|
8131
|
+
Description: "What share of cases follow the reference model",
|
|
8132
|
+
Command: "uip pm conformance rate 9c46289e",
|
|
8133
|
+
Output: {
|
|
8134
|
+
Code: "PmConformanceRate",
|
|
8135
|
+
Data: {
|
|
8136
|
+
ProcessId: "Process",
|
|
8137
|
+
Miner: "inductive",
|
|
8138
|
+
ConformanceRate: 0.666667,
|
|
8139
|
+
ConformingCases: 2,
|
|
8140
|
+
TotalCases: 3
|
|
8141
|
+
}
|
|
8142
|
+
}
|
|
8143
|
+
}
|
|
8144
|
+
];
|
|
8145
|
+
var ACTIVITIES_EXAMPLES = [
|
|
8146
|
+
{
|
|
8147
|
+
Description: "Per-activity conformance: which steps conform, which only the log has, which only the model expected",
|
|
8148
|
+
Command: "uip pm conformance activities 9c46289e",
|
|
8149
|
+
Output: {
|
|
8150
|
+
Code: "PmConformanceActivities",
|
|
8151
|
+
Data: [
|
|
8152
|
+
{ Activity: "Approve", Status: "Conforming", Cases: 2 },
|
|
8153
|
+
{ Activity: "Escalate", Status: "LogOnly", Cases: 1 }
|
|
8154
|
+
]
|
|
8155
|
+
}
|
|
8156
|
+
}
|
|
8157
|
+
];
|
|
8158
|
+
var TRANSITIONS_EXAMPLES = [
|
|
8159
|
+
{
|
|
8160
|
+
Description: "Per-transition conformance between activities",
|
|
8161
|
+
Command: "uip pm conformance transitions 9c46289e",
|
|
8162
|
+
Output: {
|
|
8163
|
+
Code: "PmConformanceTransitions",
|
|
8164
|
+
Data: [
|
|
8165
|
+
{
|
|
8166
|
+
From: "Start",
|
|
8167
|
+
To: "Approve",
|
|
8168
|
+
Status: "Conforming",
|
|
8169
|
+
Cases: 2
|
|
8170
|
+
}
|
|
8171
|
+
]
|
|
8172
|
+
}
|
|
8173
|
+
}
|
|
8174
|
+
];
|
|
8175
|
+
var UPLOAD_MODEL_EXAMPLES = [
|
|
8176
|
+
{
|
|
8177
|
+
Description: "Set the reference model from a BPMN file, then re-ingest so conformance is measured against it",
|
|
8178
|
+
Command: "uip pm conformance upload-model 9c46289e ./order-to-cash.bpmn",
|
|
8179
|
+
Output: {
|
|
8180
|
+
Code: "PmConformanceUploadModel",
|
|
8181
|
+
Data: {
|
|
8182
|
+
AppId: "9c46289e",
|
|
8183
|
+
File: "./order-to-cash.bpmn",
|
|
8184
|
+
Status: "Uploaded",
|
|
8185
|
+
Messages: []
|
|
8186
|
+
}
|
|
8187
|
+
}
|
|
8188
|
+
}
|
|
8189
|
+
];
|
|
8190
|
+
var DEVIATIONS_EXAMPLES = [
|
|
8191
|
+
{
|
|
8192
|
+
Description: "Deviations the data actually shows, with how many cases each costs",
|
|
8193
|
+
Command: "uip pm conformance deviations 9c46289e",
|
|
8194
|
+
Output: {
|
|
8195
|
+
Code: "PmConformanceDeviations",
|
|
8196
|
+
Data: [
|
|
8197
|
+
{
|
|
8198
|
+
Deviation: "Activity Approve is skipped",
|
|
8199
|
+
Type: "Skip",
|
|
8200
|
+
Cases: 1,
|
|
8201
|
+
AverageThroughputTime: 2700
|
|
8202
|
+
}
|
|
8203
|
+
]
|
|
8204
|
+
}
|
|
8205
|
+
}
|
|
8206
|
+
];
|
|
8207
|
+
function registerConformanceCommand(program2) {
|
|
8208
|
+
const cmd = program2.command("conformance").description("A process app's conformance: the reference model it is measured against, the rate, per-activity and per-transition status, and the deviations");
|
|
8209
|
+
register(cmd, {
|
|
8210
|
+
name: "rate",
|
|
8211
|
+
summary: "Share of cases that follow the reference model",
|
|
8212
|
+
code: "PmConformanceRate",
|
|
8213
|
+
examples: RATE_EXAMPLES,
|
|
8214
|
+
run: conformanceRate
|
|
8215
|
+
});
|
|
8216
|
+
register(cmd, {
|
|
8217
|
+
name: "activities",
|
|
8218
|
+
summary: "Conformance status of each activity, with the cases behind it",
|
|
8219
|
+
code: "PmConformanceActivities",
|
|
8220
|
+
examples: ACTIVITIES_EXAMPLES,
|
|
8221
|
+
run: conformanceActivities
|
|
8222
|
+
});
|
|
8223
|
+
register(cmd, {
|
|
8224
|
+
name: "transitions",
|
|
8225
|
+
summary: "Conformance status of each transition between activities, with the cases behind it",
|
|
8226
|
+
code: "PmConformanceTransitions",
|
|
8227
|
+
examples: TRANSITIONS_EXAMPLES,
|
|
8228
|
+
run: conformanceTransitions
|
|
8229
|
+
});
|
|
8230
|
+
register(cmd, {
|
|
8231
|
+
name: "deviations",
|
|
8232
|
+
summary: "Deviations present in the data, with the cases and average throughput time each accounts for",
|
|
8233
|
+
code: "PmConformanceDeviations",
|
|
8234
|
+
examples: DEVIATIONS_EXAMPLES,
|
|
8235
|
+
run: conformanceDeviations
|
|
8236
|
+
});
|
|
8237
|
+
registerUploadModel(cmd);
|
|
8238
|
+
}
|
|
8239
|
+
var MAX_BPMN_BYTES = 6 * 1024 * 1024;
|
|
8240
|
+
function registerUploadModel(group) {
|
|
8241
|
+
group.command("upload-model <app-id> <bpmn-file>").description("Upload a BPMN file as the app's reference model (dev stage; takes effect on the next ingestion)").option("--process-id <id>", "Process the model belongs to; only needed for a multi-process app").examples(UPLOAD_MODEL_EXAMPLES).trackedAction(processContext, async (appId, bpmnFile, options) => {
|
|
8242
|
+
const content = await getFileSystem().readFile(bpmnFile, "utf-8");
|
|
8243
|
+
if (content === null) {
|
|
8244
|
+
fail(`BPMN file not found: ${bpmnFile}`, "Pass the path to a .bpmn file exported from your modelling tool.");
|
|
8245
|
+
return;
|
|
8246
|
+
}
|
|
8247
|
+
const bpmn = String(content);
|
|
8248
|
+
if (Buffer.byteLength(bpmn, "utf-8") > MAX_BPMN_BYTES) {
|
|
8249
|
+
fail(`BPMN file is larger than the 6 MB the API accepts: ${bpmnFile}`, "Trim the model, or split the process so each app carries one.");
|
|
8250
|
+
return;
|
|
8251
|
+
}
|
|
8252
|
+
const config = await loadConfigOrExit();
|
|
8253
|
+
if (!config)
|
|
8254
|
+
return;
|
|
8255
|
+
const query = options.processId ? `?processId=${encodeURIComponent(options.processId)}` : "";
|
|
8256
|
+
const [err, result] = await catchError(pmPutBinaryJson(config, `/apps/${appId}/dev/bpmn${query}`, bpmn));
|
|
8257
|
+
if (err) {
|
|
8258
|
+
fail(err.message, "Check the app id (uip pm apps list), that the file is valid BPMN, and that you have edit permission. Uploads only work on the dev stage.");
|
|
8259
|
+
return;
|
|
8260
|
+
}
|
|
8261
|
+
const payload = result ?? {};
|
|
8262
|
+
const messages = field(payload, "messages") ?? [];
|
|
8263
|
+
if (field(payload, "hasError") === true) {
|
|
8264
|
+
fail(`The BPMN model was rejected: ${JSON.stringify(messages)}`, "Fix the reported problems in the model and upload it again.");
|
|
8265
|
+
return;
|
|
8266
|
+
}
|
|
8267
|
+
OutputFormatter.success({
|
|
8268
|
+
Result: "Success",
|
|
8269
|
+
Code: "PmConformanceUploadModel",
|
|
8270
|
+
Data: {
|
|
8271
|
+
AppId: appId,
|
|
8272
|
+
File: bpmnFile,
|
|
8273
|
+
Status: "Uploaded",
|
|
8274
|
+
Messages: messages
|
|
8275
|
+
}
|
|
8276
|
+
});
|
|
8277
|
+
});
|
|
8278
|
+
}
|
|
8279
|
+
function register(group, spec) {
|
|
8280
|
+
group.command(`${spec.name} <app-id>`).description(spec.summary).option("--process-id <id>", "Process to report on; only needed for a multi-process app").addOption(new Option("--stage <stage>", "App stage").choices(STAGES3).default("dev")).examples(spec.examples).trackedAction(processContext, async (appId, options) => {
|
|
8281
|
+
const config = await loadConfigOrExit();
|
|
8282
|
+
if (!config)
|
|
8283
|
+
return;
|
|
8284
|
+
const [infoErr, process2] = await catchError(resolveProcess(config, appId, options));
|
|
8285
|
+
if (infoErr || !process2) {
|
|
8286
|
+
fail(infoErr?.message ?? "Could not resolve the process.", "Check the app id (uip pm apps list) and that the stage has a completed ingestion. 'uip pm query info' lists the processes.");
|
|
8287
|
+
return;
|
|
8288
|
+
}
|
|
8289
|
+
const [err, data] = await catchError(spec.run(config, appId, options.stage, process2));
|
|
8290
|
+
if (err) {
|
|
8291
|
+
fail(err.message, "Check the app id (uip pm apps list) and that the stage has a completed ingestion.");
|
|
8292
|
+
return;
|
|
8293
|
+
}
|
|
8294
|
+
OutputFormatter.success({
|
|
8295
|
+
Result: "Success",
|
|
8296
|
+
Code: spec.code,
|
|
8297
|
+
Data: data
|
|
8298
|
+
});
|
|
8299
|
+
});
|
|
8300
|
+
}
|
|
8301
|
+
function sub(obj, name) {
|
|
8302
|
+
return field(obj ?? {}, name) ?? {};
|
|
8303
|
+
}
|
|
8304
|
+
var str = (obj, name) => {
|
|
8305
|
+
const value = field(obj, name);
|
|
8306
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
8307
|
+
};
|
|
8308
|
+
async function resolveProcess(config, appId, options) {
|
|
8309
|
+
const info = await pmGet(config, `/query/${appId}/${options.stage}/info`);
|
|
8310
|
+
const internal = sub(info, "internalFields");
|
|
8311
|
+
const processes = field(internal, "processes") ?? [];
|
|
8312
|
+
if (processes.length === 0) {
|
|
8313
|
+
throw new Error(`App '${appId}' exposes no processes, so it has no conformance data.`);
|
|
8314
|
+
}
|
|
8315
|
+
const wanted = options.processId;
|
|
8316
|
+
const match = wanted ? processes.find((p) => str(p, "processId") === wanted) : processes[0];
|
|
8317
|
+
if (!match) {
|
|
8318
|
+
const known = processes.map((p) => str(p, "processId") ?? "?").join(", ");
|
|
8319
|
+
throw new Error(`Process '${wanted}' not found on app '${appId}'. Available: ${known}.`);
|
|
8320
|
+
}
|
|
8321
|
+
const cases = sub(match, "cases");
|
|
8322
|
+
const events = sub(match, "events");
|
|
8323
|
+
const transitions = sub(match, "transitions");
|
|
8324
|
+
const deviations = sub(match, "variationDeviations");
|
|
8325
|
+
const processId = str(match, "processId") ?? "";
|
|
8326
|
+
const miner = str(match, "miner") ?? "";
|
|
8327
|
+
const caseConforming = str(cases, "caseConforming");
|
|
8328
|
+
if (caseConforming === null || !MODEL_BASED_MINERS.has(miner)) {
|
|
8329
|
+
throw new Error(`Process '${processId}' uses the '${miner || "unknown"}' miner and has no reference model, so it has no conformance data. ` + "Conformance needs a model-based app — create one with 'uip pm apps create --miner inductive' (or bpmn).");
|
|
8330
|
+
}
|
|
8331
|
+
return {
|
|
8332
|
+
processId,
|
|
8333
|
+
miner,
|
|
8334
|
+
caseId: str(cases, "caseId") ?? "",
|
|
8335
|
+
caseConforming,
|
|
8336
|
+
caseThroughputTime: str(cases, "caseThroughputTime"),
|
|
8337
|
+
activity: str(events, "activity") ?? "",
|
|
8338
|
+
nodeId: str(events, "nodeId") ?? "",
|
|
8339
|
+
eventConformance: str(events, "eventConformance"),
|
|
8340
|
+
fromNodeId: str(transitions, "fromNodeId") ?? "",
|
|
8341
|
+
toNodeId: str(transitions, "toNodeId") ?? "",
|
|
8342
|
+
transitionConformance: str(transitions, "transitionConformance"),
|
|
8343
|
+
deviation: str(deviations, "deviation"),
|
|
8344
|
+
deviationType: str(deviations, "deviationType")
|
|
8345
|
+
};
|
|
8346
|
+
}
|
|
8347
|
+
async function runQuery(config, appId, stage, body) {
|
|
8348
|
+
const result = await pmPost(config, `/query/${appId}/${stage}`, body);
|
|
8349
|
+
return result ?? {};
|
|
8350
|
+
}
|
|
8351
|
+
function cell(response, id) {
|
|
8352
|
+
const target = sanitizeKey(id);
|
|
8353
|
+
for (const [key, value] of Object.entries(response)) {
|
|
8354
|
+
if (sanitizeKey(key) === target) {
|
|
8355
|
+
return value ?? {};
|
|
8356
|
+
}
|
|
8357
|
+
}
|
|
8358
|
+
return {};
|
|
8359
|
+
}
|
|
8360
|
+
var values = (c) => field(c, "values") ?? [];
|
|
8361
|
+
var ungrouped = (c) => field(c, "ungrouped") ?? null;
|
|
8362
|
+
function statusName(value) {
|
|
8363
|
+
if (typeof value === "number")
|
|
8364
|
+
return CONFORMANCE_STATUS[value] ?? value;
|
|
8365
|
+
return value ?? null;
|
|
8366
|
+
}
|
|
8367
|
+
var asNumber = (value) => typeof value === "number" ? value : null;
|
|
8368
|
+
async function conformanceRate(config, appId, stage, process2) {
|
|
8369
|
+
const aggregates = [
|
|
8370
|
+
{
|
|
8371
|
+
id: "rate",
|
|
8372
|
+
argument: process2.caseConforming,
|
|
8373
|
+
aggregation: "PERCENTAGE"
|
|
8374
|
+
},
|
|
8375
|
+
{
|
|
8376
|
+
id: "total_cases",
|
|
8377
|
+
argument: process2.caseId,
|
|
8378
|
+
aggregation: "DISTINCT_COUNT"
|
|
8379
|
+
}
|
|
8380
|
+
];
|
|
8381
|
+
const response = await runQuery(config, appId, stage, {
|
|
8382
|
+
groupBy: [],
|
|
8383
|
+
aggregates
|
|
8384
|
+
});
|
|
8385
|
+
const rateCell = cell(response, "rate");
|
|
8386
|
+
const totalCell = cell(response, "total_cases");
|
|
8387
|
+
const rate = asNumber(ungrouped(rateCell) ?? values(rateCell)[0]);
|
|
8388
|
+
const total = asNumber(ungrouped(totalCell) ?? values(totalCell)[0]);
|
|
8389
|
+
return {
|
|
8390
|
+
ProcessId: process2.processId,
|
|
8391
|
+
Miner: process2.miner,
|
|
8392
|
+
ConformanceRate: rate,
|
|
8393
|
+
ConformingCases: rate !== null && total !== null ? Math.round(rate * total) : null,
|
|
8394
|
+
TotalCases: total
|
|
8395
|
+
};
|
|
8396
|
+
}
|
|
8397
|
+
async function conformanceActivities(config, appId, stage, process2) {
|
|
8398
|
+
if (!process2.eventConformance) {
|
|
8399
|
+
throw new Error(`Process '${process2.processId}' has no event conformance field, so per-activity status is unavailable.`);
|
|
8400
|
+
}
|
|
8401
|
+
const aggregates = [
|
|
8402
|
+
{
|
|
8403
|
+
id: "cases",
|
|
8404
|
+
argument: process2.caseId,
|
|
8405
|
+
aggregation: "DISTINCT_COUNT"
|
|
8406
|
+
},
|
|
8407
|
+
{
|
|
8408
|
+
id: "status",
|
|
8409
|
+
argument: process2.eventConformance,
|
|
8410
|
+
aggregation: "MAX"
|
|
8411
|
+
}
|
|
8412
|
+
];
|
|
8413
|
+
const response = await runQuery(config, appId, stage, {
|
|
8414
|
+
groupBy: [process2.activity],
|
|
8415
|
+
aggregates,
|
|
8416
|
+
isProcessGraph: true
|
|
8417
|
+
});
|
|
8418
|
+
const activities = values(cell(response, process2.activity));
|
|
8419
|
+
const cases = values(cell(response, "cases"));
|
|
8420
|
+
const status = values(cell(response, "status"));
|
|
8421
|
+
return activities.map((name, i) => ({
|
|
8422
|
+
Activity: name ?? null,
|
|
8423
|
+
Status: statusName(status[i]),
|
|
8424
|
+
Cases: asNumber(cases[i])
|
|
8425
|
+
}));
|
|
8426
|
+
}
|
|
8427
|
+
async function conformanceTransitions(config, appId, stage, process2) {
|
|
8428
|
+
if (!process2.transitionConformance) {
|
|
8429
|
+
throw new Error(`Process '${process2.processId}' has no transition conformance field, so per-transition status is unavailable.`);
|
|
8430
|
+
}
|
|
8431
|
+
const aggregates = [
|
|
8432
|
+
{
|
|
8433
|
+
id: "cases",
|
|
8434
|
+
argument: process2.caseId,
|
|
8435
|
+
aggregation: "DISTINCT_COUNT"
|
|
8436
|
+
},
|
|
8437
|
+
{
|
|
8438
|
+
id: "status",
|
|
8439
|
+
argument: process2.transitionConformance,
|
|
8440
|
+
aggregation: "MAX"
|
|
8441
|
+
}
|
|
8442
|
+
];
|
|
8443
|
+
const response = await runQuery(config, appId, stage, {
|
|
8444
|
+
groupBy: [process2.fromNodeId, process2.toNodeId],
|
|
8445
|
+
aggregates,
|
|
8446
|
+
isProcessGraph: true
|
|
8447
|
+
});
|
|
8448
|
+
const from = values(cell(response, process2.fromNodeId));
|
|
8449
|
+
const to = values(cell(response, process2.toNodeId));
|
|
8450
|
+
const cases = values(cell(response, "cases"));
|
|
8451
|
+
const status = values(cell(response, "status"));
|
|
8452
|
+
return from.map((fromNode, i) => ({
|
|
8453
|
+
FromNodeId: fromNode ?? null,
|
|
8454
|
+
ToNodeId: to[i] ?? null,
|
|
8455
|
+
Status: statusName(status[i]),
|
|
8456
|
+
Cases: asNumber(cases[i])
|
|
8457
|
+
}));
|
|
8458
|
+
}
|
|
8459
|
+
async function conformanceDeviations(config, appId, stage, process2) {
|
|
8460
|
+
if (!process2.deviation || !process2.deviationType) {
|
|
8461
|
+
throw new Error(`Process '${process2.processId}' exposes no deviation fields, so there are no deviations to report.`);
|
|
8462
|
+
}
|
|
8463
|
+
const aggregates = [
|
|
8464
|
+
{
|
|
8465
|
+
id: "cases",
|
|
8466
|
+
argument: process2.caseId,
|
|
8467
|
+
aggregation: "DISTINCT_COUNT"
|
|
8468
|
+
}
|
|
8469
|
+
];
|
|
8470
|
+
if (process2.caseThroughputTime) {
|
|
8471
|
+
aggregates.push({
|
|
8472
|
+
id: "throughput",
|
|
8473
|
+
argument: process2.caseThroughputTime,
|
|
8474
|
+
aggregation: "AVERAGE"
|
|
8475
|
+
});
|
|
8476
|
+
}
|
|
8477
|
+
const response = await runQuery(config, appId, stage, {
|
|
8478
|
+
groupBy: [process2.deviation, process2.deviationType],
|
|
8479
|
+
aggregates
|
|
8480
|
+
});
|
|
8481
|
+
const deviations = values(cell(response, process2.deviation));
|
|
8482
|
+
const types = values(cell(response, process2.deviationType));
|
|
8483
|
+
const cases = values(cell(response, "cases"));
|
|
8484
|
+
const throughput = values(cell(response, "throughput"));
|
|
8485
|
+
return deviations.map((deviation, i) => ({
|
|
8486
|
+
Deviation: deviation ?? null,
|
|
8487
|
+
Type: types[i] ?? null,
|
|
8488
|
+
Cases: asNumber(cases[i]),
|
|
8489
|
+
AverageThroughputTime: asNumber(throughput[i])
|
|
8490
|
+
})).filter((row) => row.Deviation !== null);
|
|
8491
|
+
}
|
|
8492
|
+
|
|
8493
|
+
// src/commands/deviations.ts
|
|
8494
|
+
var STAGES4 = ["dev", "published"];
|
|
8495
|
+
var DEFAULT_PROCESS_ID = "Process";
|
|
8496
|
+
var STATUSES = ["Applied", "AppliedButDeleted", "NotApplied"];
|
|
8497
|
+
var DEVIATIONS_LIST_EXAMPLES = [
|
|
8498
|
+
{
|
|
8499
|
+
Description: "List the deviations accepted on an app, with whether the last ingestion has them",
|
|
8500
|
+
Command: "uip pm deviations list 9c46289e",
|
|
8501
|
+
Output: {
|
|
8502
|
+
Code: "PmDeviationsList",
|
|
8503
|
+
Data: [
|
|
8504
|
+
{
|
|
8505
|
+
Type: "activity_missing",
|
|
8506
|
+
Activities: ["Approve order"],
|
|
8507
|
+
ParentProcess: [],
|
|
8508
|
+
Status: "NotApplied"
|
|
8509
|
+
}
|
|
8510
|
+
]
|
|
8511
|
+
}
|
|
8512
|
+
}
|
|
8513
|
+
];
|
|
8514
|
+
var DEVIATIONS_ACCEPT_EXAMPLES = [
|
|
8515
|
+
{
|
|
8516
|
+
Description: "Accept a deviation, then re-run transformations to apply it (until then it lists as NotApplied)",
|
|
8517
|
+
Command: 'uip pm deviations accept 9c46289e --type activity_missing --activities "Approve order"',
|
|
8518
|
+
Output: {
|
|
8519
|
+
Code: "PmDeviationsAccept",
|
|
8520
|
+
Data: {
|
|
8521
|
+
AppId: "9c46289e",
|
|
8522
|
+
Type: "activity_missing",
|
|
8523
|
+
Activities: ["Approve order"],
|
|
8524
|
+
Status: "Accepted"
|
|
8525
|
+
}
|
|
8526
|
+
}
|
|
8527
|
+
}
|
|
8528
|
+
];
|
|
8529
|
+
var DEVIATIONS_DELETE_EXAMPLES = [
|
|
8530
|
+
{
|
|
8531
|
+
Description: "Stop accepting a deviation",
|
|
8532
|
+
Command: 'uip pm deviations delete 9c46289e --type activity_missing --activities "Approve order"',
|
|
8533
|
+
Output: {
|
|
8534
|
+
Code: "PmDeviationsDelete",
|
|
8535
|
+
Data: {
|
|
8536
|
+
AppId: "9c46289e",
|
|
8537
|
+
Type: "activity_missing",
|
|
8538
|
+
Activities: ["Approve order"],
|
|
8539
|
+
Status: "Deleted"
|
|
8540
|
+
}
|
|
8541
|
+
}
|
|
8542
|
+
}
|
|
8543
|
+
];
|
|
8544
|
+
function registerDeviationsCommand(program2) {
|
|
8545
|
+
const devCmd = program2.command("deviations").description("Manage the deviations accepted on a process app: list, accept, delete");
|
|
8546
|
+
devCmd.command("list <app-id>").description("List the accepted deviations and whether the last ingestion has them applied").addOption(processIdOption()).addOption(new Option("--stage <stage>", "App stage").choices(STAGES4).default("dev")).examples(DEVIATIONS_LIST_EXAMPLES).trackedAction(processContext, async (appId, options) => {
|
|
8547
|
+
const config = await loadConfigOrExit();
|
|
8548
|
+
if (!config)
|
|
8549
|
+
return;
|
|
8550
|
+
const [err, result] = await catchError(pmGet(config, deviationsPath(appId, options)));
|
|
8551
|
+
if (err) {
|
|
8552
|
+
fail(err.message, LIST_INSTRUCTIONS);
|
|
8553
|
+
return;
|
|
8554
|
+
}
|
|
8555
|
+
OutputFormatter.success({
|
|
8556
|
+
Result: "Success",
|
|
8557
|
+
Code: "PmDeviationsList",
|
|
8558
|
+
Data: normalizeDeviations(unwrapData(result))
|
|
8559
|
+
});
|
|
8560
|
+
});
|
|
8561
|
+
devCmd.command("accept <app-id>").description("Accept a deviation so conformance stops counting it against the app").requiredOption("--type <deviation-type>", "Deviation type, as reported in the app's deviation data").requiredOption("--activities <activities...>", "Activity names the deviation covers (space-separated; quote names containing spaces)").addOption(processIdOption()).examples(DEVIATIONS_ACCEPT_EXAMPLES).trackedAction(processContext, async (appId, options) => {
|
|
8562
|
+
const config = await loadConfigOrExit();
|
|
8563
|
+
if (!config)
|
|
8564
|
+
return;
|
|
8565
|
+
const body = buildDeviationBody(options);
|
|
8566
|
+
const [err] = await catchError(pmPost(config, deviationsPath(appId, options), body));
|
|
8567
|
+
if (err) {
|
|
8568
|
+
fail(err.message, WRITE_INSTRUCTIONS + " A deviation that is already accepted is rejected as a duplicate — see 'uip pm deviations list'.");
|
|
8569
|
+
return;
|
|
8570
|
+
}
|
|
8571
|
+
OutputFormatter.success({
|
|
8572
|
+
Result: "Success",
|
|
8573
|
+
Code: "PmDeviationsAccept",
|
|
8574
|
+
Data: {
|
|
8575
|
+
AppId: appId,
|
|
8576
|
+
Type: body.type,
|
|
8577
|
+
Activities: body.activities,
|
|
8578
|
+
Status: "Accepted"
|
|
8579
|
+
}
|
|
8580
|
+
});
|
|
8581
|
+
});
|
|
8582
|
+
devCmd.command("delete <app-id>").description("Stop accepting a deviation").requiredOption("--type <deviation-type>", "Deviation type, as reported in the app's deviation data").requiredOption("--activities <activities...>", "Activity names the deviation covers (space-separated; quote names containing spaces)").addOption(processIdOption()).examples(DEVIATIONS_DELETE_EXAMPLES).trackedAction(processContext, async (appId, options) => {
|
|
8583
|
+
const config = await loadConfigOrExit();
|
|
8584
|
+
if (!config)
|
|
8585
|
+
return;
|
|
8586
|
+
const body = buildDeviationBody(options);
|
|
8587
|
+
const [err] = await catchError(pmDelete(config, deviationsPath(appId, options), body));
|
|
8588
|
+
if (err) {
|
|
8589
|
+
fail(err.message, WRITE_INSTRUCTIONS + " The type, activities and parent process must match an accepted deviation exactly — list them with 'uip pm deviations list'.");
|
|
8590
|
+
return;
|
|
8591
|
+
}
|
|
8592
|
+
OutputFormatter.success({
|
|
8593
|
+
Result: "Success",
|
|
8594
|
+
Code: "PmDeviationsDelete",
|
|
8595
|
+
Data: {
|
|
8596
|
+
AppId: appId,
|
|
8597
|
+
Type: body.type,
|
|
8598
|
+
Activities: body.activities,
|
|
8599
|
+
Status: "Deleted"
|
|
8600
|
+
}
|
|
8601
|
+
});
|
|
8602
|
+
});
|
|
8603
|
+
devCmd.command("delete-all <app-id>").description("Stop accepting every deviation on the app").option("-y, --yes", "Confirm this irreversible operation (required; the CLI never prompts)").addOption(processIdOption()).trackedAction(processContext, async (appId, options) => {
|
|
8604
|
+
if (!requireConfirmation(options, `delete every accepted deviation on process app '${appId}'`))
|
|
8605
|
+
return;
|
|
8606
|
+
const config = await loadConfigOrExit();
|
|
8607
|
+
if (!config)
|
|
8608
|
+
return;
|
|
8609
|
+
const [err] = await catchError(pmDelete(config, `${deviationsPath(appId, options)}/all`));
|
|
8610
|
+
if (err) {
|
|
8611
|
+
fail(err.message, WRITE_INSTRUCTIONS);
|
|
8612
|
+
return;
|
|
8613
|
+
}
|
|
8614
|
+
OutputFormatter.success({
|
|
8615
|
+
Result: "Success",
|
|
8616
|
+
Code: "PmDeviationsDeleteAll",
|
|
8617
|
+
Data: { AppId: appId, Status: "Deleted" }
|
|
8618
|
+
});
|
|
8619
|
+
});
|
|
8620
|
+
}
|
|
8621
|
+
function processIdOption() {
|
|
8622
|
+
return new Option("--process-id <id>", "Process id (from 'uip pm query info'); only matters for a multi-process app").default(DEFAULT_PROCESS_ID);
|
|
8623
|
+
}
|
|
8624
|
+
function deviationsPath(appId, options) {
|
|
8625
|
+
const stage = options.stage ?? "dev";
|
|
8626
|
+
return `/apps/${appId}/${stage}/${options.processId}/accepted-deviations`;
|
|
8627
|
+
}
|
|
8628
|
+
function buildDeviationBody(options) {
|
|
8629
|
+
return {
|
|
8630
|
+
type: options.type,
|
|
8631
|
+
activities: (options.activities ?? []).filter((value) => value.length > 0),
|
|
8632
|
+
parentProcess: []
|
|
8633
|
+
};
|
|
8634
|
+
}
|
|
8635
|
+
function normalizeDeviations(payload) {
|
|
8636
|
+
if (!Array.isArray(payload))
|
|
8637
|
+
return payload;
|
|
8638
|
+
return payload.map((row) => {
|
|
8639
|
+
if (row === null || typeof row !== "object")
|
|
8640
|
+
return row;
|
|
8641
|
+
const r = row;
|
|
8642
|
+
return {
|
|
8643
|
+
Type: field(r, "type") ?? null,
|
|
8644
|
+
Activities: field(r, "activity") ?? field(r, "activities") ?? [],
|
|
8645
|
+
ParentProcess: field(r, "parentProcess") ?? [],
|
|
8646
|
+
Status: readStatus(field(r, "status"))
|
|
8647
|
+
};
|
|
8648
|
+
});
|
|
8649
|
+
}
|
|
8650
|
+
function readStatus(status) {
|
|
8651
|
+
if (typeof status === "number")
|
|
8652
|
+
return STATUSES[status] ?? status;
|
|
8653
|
+
return status ?? null;
|
|
8654
|
+
}
|
|
8655
|
+
var LIST_INSTRUCTIONS = "Check the app id (uip pm apps list), that the stage has a completed ingestion, " + "and the --process-id (uip pm query info lists the processes).";
|
|
8656
|
+
var WRITE_INSTRUCTIONS = "Writes only work on the dev stage and need edit permission on the app. " + "Check the app id (uip pm apps list) and the --process-id (uip pm query info).";
|
|
8657
|
+
|
|
6959
8658
|
// src/commands/files.ts
|
|
6960
8659
|
var CHUNK_SIZE = 5 * 1024 * 1024;
|
|
6961
8660
|
var MAX_CONCURRENT_UPLOADS = 4;
|
|
6962
|
-
var
|
|
8661
|
+
var STAGES5 = ["dev", "published"];
|
|
6963
8662
|
var FILES_UPLOAD_EXAMPLES = [
|
|
6964
8663
|
{
|
|
6965
8664
|
Description: "Upload an event-log CSV from a sample dataset",
|
|
@@ -6972,11 +8671,11 @@ var FILES_UPLOAD_EXAMPLES = [
|
|
|
6972
8671
|
];
|
|
6973
8672
|
function registerFilesCommand(program2) {
|
|
6974
8673
|
const filesCmd = program2.command("files").description("Upload data files to a process app");
|
|
6975
|
-
filesCmd.command("upload <app-id> <file-path>").description("Upload a data file to a process app via chunked blob upload").addOption(new Option("--stage <stage>", "App stage to upload to").choices(
|
|
8674
|
+
filesCmd.command("upload <app-id> <file-path>").description("Upload a data file to a process app via chunked blob upload").addOption(new Option("--stage <stage>", "App stage to upload to").choices(STAGES5).default("dev")).option("--input-table <name>", "Target input table the file belongs to (e.g. 'Event_log')").examples(FILES_UPLOAD_EXAMPLES).trackedAction(processContext, async (appId, filePath, options) => {
|
|
6976
8675
|
const config = await loadConfigOrExit();
|
|
6977
8676
|
if (!config)
|
|
6978
8677
|
return;
|
|
6979
|
-
const [err, result] = await
|
|
8678
|
+
const [err, result] = await catchError(uploadFile(config, appId, filePath, options));
|
|
6980
8679
|
if (err) {
|
|
6981
8680
|
fail(err.message, "Check the app id, file path, and that no ingestion is currently in progress.");
|
|
6982
8681
|
return;
|
|
@@ -6989,13 +8688,13 @@ function registerFilesCommand(program2) {
|
|
|
6989
8688
|
});
|
|
6990
8689
|
}
|
|
6991
8690
|
async function uploadFile(config, appId, filePath, options) {
|
|
6992
|
-
const
|
|
6993
|
-
const bytes = await
|
|
8691
|
+
const fs2 = getFileSystem();
|
|
8692
|
+
const bytes = await fs2.readFile(filePath);
|
|
6994
8693
|
if (bytes === null) {
|
|
6995
8694
|
throw new Error(`File not found: ${filePath}`);
|
|
6996
8695
|
}
|
|
6997
8696
|
const size = bytes.length;
|
|
6998
|
-
const filename =
|
|
8697
|
+
const filename = fs2.path.basename(filePath);
|
|
6999
8698
|
const startResponse = await pmPost(config, `/upload/${appId}/${options.stage}`, { filename, size, inputTable: options.inputTable });
|
|
7000
8699
|
if (startResponse === null) {
|
|
7001
8700
|
throw new Error("Start-upload returned an empty response.");
|
|
@@ -7062,7 +8761,7 @@ async function uploadPart(config, part, content) {
|
|
|
7062
8761
|
}
|
|
7063
8762
|
|
|
7064
8763
|
// src/commands/ingestions.ts
|
|
7065
|
-
var
|
|
8764
|
+
var STAGES6 = ["dev", "published"];
|
|
7066
8765
|
var FILE_FORMATS = ["csv", "tsv"];
|
|
7067
8766
|
var ENCODINGS = ["utf-8", "iso-8859-1"];
|
|
7068
8767
|
var INGESTIONS_CREATE_EXAMPLES = [
|
|
@@ -7101,20 +8800,20 @@ var INGESTIONS_LOGS_EXAMPLES = [
|
|
|
7101
8800
|
];
|
|
7102
8801
|
function registerIngestionsCommand(program2) {
|
|
7103
8802
|
const ingestionsCmd = program2.command("ingestions").description("Trigger and inspect data ingestions of a process app");
|
|
7104
|
-
ingestionsCmd.command("create <app-id>").description("Trigger an ingestion of the uploaded data files").addOption(new Option("--stage <stage>", "App stage to ingest into").choices(
|
|
8803
|
+
ingestionsCmd.command("create <app-id>").description("Trigger an ingestion of the uploaded data files").addOption(new Option("--stage <stage>", "App stage to ingest into").choices(STAGES6).default("dev")).addOption(new Option("--file-format <format>", "Data file format").choices(FILE_FORMATS).default("csv")).option("--field-delimiter <char>", "Field delimiter in the data files", ",").option("--quote-character <char>", "Quote character enclosing fields", '"').addOption(new Option("--encoding <encoding>", "File encoding").choices(ENCODINGS).default("utf-8")).option("--wait", "Block until the ingestion reaches a terminal state; exit non-zero on failure").option("--timeout <seconds>", "Max seconds to wait when --wait is set", "1800").option("--poll-interval <seconds>", "Seconds between status polls when --wait is set", "5").examples(INGESTIONS_CREATE_EXAMPLES).trackedAction(processContext, async (appId, options) => {
|
|
7105
8804
|
const config = await loadConfigOrExit();
|
|
7106
8805
|
if (!config)
|
|
7107
8806
|
return;
|
|
7108
8807
|
let before = {};
|
|
7109
8808
|
if (options.wait) {
|
|
7110
|
-
const [readErr, snapshot] = await
|
|
8809
|
+
const [readErr, snapshot] = await catchError(readLastIngestion(config, appId, options.stage));
|
|
7111
8810
|
if (readErr) {
|
|
7112
8811
|
fail(readErr.message, "Check the app id (uip pm apps list) and your authentication.");
|
|
7113
8812
|
return;
|
|
7114
8813
|
}
|
|
7115
8814
|
before = snapshot;
|
|
7116
8815
|
}
|
|
7117
|
-
const [err, result] = await
|
|
8816
|
+
const [err, result] = await catchError(pmPost(config, `/apps/${appId}/${options.stage}/ingest`, {
|
|
7118
8817
|
fileFormat: options.fileFormat,
|
|
7119
8818
|
fileFormatOptions: {
|
|
7120
8819
|
fieldDelimiter: options.fieldDelimiter,
|
|
@@ -7139,11 +8838,11 @@ function registerIngestionsCommand(program2) {
|
|
|
7139
8838
|
}
|
|
7140
8839
|
});
|
|
7141
8840
|
});
|
|
7142
|
-
ingestionsCmd.command("cancel <app-id> <ingestion-id>").description("Cancel an ingestion that is still running").addOption(new Option("--stage <stage>", "App stage the ingestion runs on").choices(
|
|
8841
|
+
ingestionsCmd.command("cancel <app-id> <ingestion-id>").description("Cancel an ingestion that is still running").addOption(new Option("--stage <stage>", "App stage the ingestion runs on").choices(STAGES6).default("dev")).examples(INGESTIONS_CANCEL_EXAMPLES).trackedAction(processContext, async (appId, ingestionId, options) => {
|
|
7143
8842
|
const config = await loadConfigOrExit();
|
|
7144
8843
|
if (!config)
|
|
7145
8844
|
return;
|
|
7146
|
-
const [err] = await
|
|
8845
|
+
const [err] = await catchError(pmPost(config, `/apps/${appId}/${options.stage}/ingestions/${ingestionId}/cancel`));
|
|
7147
8846
|
if (err) {
|
|
7148
8847
|
fail(err.message, `Check the ingestion id ('uip pm apps get ${appId}' shows LastIngestion) and that it is still running.`);
|
|
7149
8848
|
return;
|
|
@@ -7158,7 +8857,7 @@ function registerIngestionsCommand(program2) {
|
|
|
7158
8857
|
}
|
|
7159
8858
|
});
|
|
7160
8859
|
});
|
|
7161
|
-
ingestionsCmd.command("logs <app-id> <ingestion-id>").description("Get the logs of an ingestion run").addOption(new Option("--stage <stage>", "App stage the ingestion ran on").choices(
|
|
8860
|
+
ingestionsCmd.command("logs <app-id> <ingestion-id>").description("Get the logs of an ingestion run").addOption(new Option("--stage <stage>", "App stage the ingestion ran on").choices(STAGES6).default("dev")).option("--limit <number>", "Max log entries to fetch (page size)", "100").option("--offset <number>", "Number of log entries to skip before the page", "0").examples(INGESTIONS_LOGS_EXAMPLES).trackedAction(processContext, async (appId, ingestionId, options) => {
|
|
7162
8861
|
const config = await loadConfigOrExit();
|
|
7163
8862
|
if (!config)
|
|
7164
8863
|
return;
|
|
@@ -7166,7 +8865,7 @@ function registerIngestionsCommand(program2) {
|
|
|
7166
8865
|
const offset = Number.parseInt(options.offset, 10);
|
|
7167
8866
|
const pageSize = limit > 0 ? limit : 100;
|
|
7168
8867
|
const pageNumber = offset > 0 ? Math.floor(offset / pageSize) + 1 : 1;
|
|
7169
|
-
const [err, result] = await
|
|
8868
|
+
const [err, result] = await catchError(pmGet(config, `/apps/${appId}/${options.stage}/logs/${ingestionId}?pageNumber=${pageNumber}&pageSize=${pageSize}`));
|
|
7170
8869
|
if (err) {
|
|
7171
8870
|
fail(err.message, "Check the app id and ingestion id (uip pm apps list shows LastIngestion).");
|
|
7172
8871
|
return;
|
|
@@ -7180,7 +8879,7 @@ function registerIngestionsCommand(program2) {
|
|
|
7180
8879
|
}
|
|
7181
8880
|
|
|
7182
8881
|
// src/commands/query.ts
|
|
7183
|
-
var
|
|
8882
|
+
var STAGES7 = ["dev", "published"];
|
|
7184
8883
|
var LAYOUT_TYPES = ["graph", "process-model"];
|
|
7185
8884
|
var QUERY_RUN_EXAMPLES = [
|
|
7186
8885
|
{
|
|
@@ -7192,14 +8891,36 @@ var QUERY_RUN_EXAMPLES = [
|
|
|
7192
8891
|
}
|
|
7193
8892
|
},
|
|
7194
8893
|
{
|
|
7195
|
-
Description: "Raw aggregate body. groupBy/argument take field ids from 'query info';
|
|
7196
|
-
Command: `uip pm query run 9c46289e --body-json '{"groupBy":["F__Cases__Priority__..."],"aggregates":[{"id":"n","argument":"Case_ID","aggregation":"
|
|
8894
|
+
Description: "Raw aggregate body. groupBy/argument take field ids from 'query info'; see --metric for the aggregations",
|
|
8895
|
+
Command: `uip pm query run 9c46289e --body-json '{"groupBy":["F__Cases__Priority__..."],"aggregates":[{"id":"n","argument":"Case_ID","aggregation":"COUNT"}]}'`,
|
|
7197
8896
|
Output: {
|
|
7198
8897
|
Code: "PmQueryRun",
|
|
7199
8898
|
Data: {
|
|
7200
8899
|
n: { Ungrouped: 1043 }
|
|
7201
8900
|
}
|
|
7202
8901
|
}
|
|
8902
|
+
},
|
|
8903
|
+
{
|
|
8904
|
+
Description: "Conformance rate: the share of cases that follow the reference model (the process' conforming field comes from 'query info')",
|
|
8905
|
+
Command: "uip pm query run 9c46289e --metric Case_conforming:percentage",
|
|
8906
|
+
Output: {
|
|
8907
|
+
Code: "PmQueryRun",
|
|
8908
|
+
Data: [{ percentage_Case_conforming: 82.4 }]
|
|
8909
|
+
}
|
|
8910
|
+
},
|
|
8911
|
+
{
|
|
8912
|
+
Description: "Skipped steps: activities the model expected that a case did not take, counted by case. Drop --conformance for the same query over what the log did do",
|
|
8913
|
+
Command: "uip pm query run 9c46289e --group-by Node_id,Node_label --metric Case_ID:distinct_count --process-graph --conformance",
|
|
8914
|
+
Output: {
|
|
8915
|
+
Code: "PmQueryRun",
|
|
8916
|
+
Data: [
|
|
8917
|
+
{
|
|
8918
|
+
Node_id: 3,
|
|
8919
|
+
Node_label: "Approve order",
|
|
8920
|
+
distinct_count_Case_ID: 87
|
|
8921
|
+
}
|
|
8922
|
+
]
|
|
8923
|
+
}
|
|
7203
8924
|
}
|
|
7204
8925
|
];
|
|
7205
8926
|
var QUERY_RCA_EXAMPLES = [
|
|
@@ -7232,7 +8953,19 @@ var QUERY_PERCENTILE_EXAMPLES = [
|
|
|
7232
8953
|
}
|
|
7233
8954
|
}
|
|
7234
8955
|
];
|
|
7235
|
-
var AGGREGATIONS = new
|
|
8956
|
+
var AGGREGATIONS = new Map([
|
|
8957
|
+
["any", "ANY"],
|
|
8958
|
+
["average", "AVERAGE"],
|
|
8959
|
+
["count", "COUNT"],
|
|
8960
|
+
["distinct_count", "DISTINCT_COUNT"],
|
|
8961
|
+
["forall", "FORALL"],
|
|
8962
|
+
["forany", "FORANY"],
|
|
8963
|
+
["max", "MAX"],
|
|
8964
|
+
["median", "MEDIAN"],
|
|
8965
|
+
["min", "MIN"],
|
|
8966
|
+
["percentage", "PERCENTAGE"],
|
|
8967
|
+
["sum", "SUM"]
|
|
8968
|
+
]);
|
|
7236
8969
|
function registerQueryCommand(program2) {
|
|
7237
8970
|
const queryCmd = program2.command("query").description("Query a process app: aggregate data, details, RCA, insights, " + "percentiles, layout and query metadata");
|
|
7238
8971
|
registerBodyQuery(queryCmd, {
|
|
@@ -7266,11 +8999,11 @@ function registerQueryCommand(program2) {
|
|
|
7266
8999
|
summary: "Run process insights (body needs 'processId' and 1..10 'metrics')",
|
|
7267
9000
|
withLimit: true
|
|
7268
9001
|
});
|
|
7269
|
-
queryCmd.command("info <app-id>").description("Get query metadata: the fields, metrics and processes available to build query bodies").addOption(new Option("--stage <stage>", "App stage").choices(
|
|
9002
|
+
queryCmd.command("info <app-id>").description("Get query metadata: the fields, metrics and processes available to build query bodies").addOption(new Option("--stage <stage>", "App stage").choices(STAGES7).default("dev")).examples(QUERY_INFO_EXAMPLES).trackedAction(processContext, async (appId, options) => {
|
|
7270
9003
|
const config = await loadConfigOrExit();
|
|
7271
9004
|
if (!config)
|
|
7272
9005
|
return;
|
|
7273
|
-
const [err, result] = await
|
|
9006
|
+
const [err, result] = await catchError(pmGet(config, `/query/${appId}/${options.stage}/info`));
|
|
7274
9007
|
if (err) {
|
|
7275
9008
|
fail(err.message, "Check the app id (uip pm apps list) and that the stage has a completed ingestion.");
|
|
7276
9009
|
return;
|
|
@@ -7281,12 +9014,12 @@ function registerQueryCommand(program2) {
|
|
|
7281
9014
|
Data: result
|
|
7282
9015
|
});
|
|
7283
9016
|
});
|
|
7284
|
-
queryCmd.command("layout <app-id>").description("Get the persisted global graph layout of a process app").addOption(new Option("--type <type>", "Layout to read: the process 'graph' or the 'process-model'").choices(LAYOUT_TYPES).default("graph")).addOption(new Option("--stage <stage>", "App stage").choices(
|
|
9017
|
+
queryCmd.command("layout <app-id>").description("Get the persisted global graph layout of a process app").addOption(new Option("--type <type>", "Layout to read: the process 'graph' or the 'process-model'").choices(LAYOUT_TYPES).default("graph")).addOption(new Option("--stage <stage>", "App stage").choices(STAGES7).default("dev")).trackedAction(processContext, async (appId, options) => {
|
|
7285
9018
|
const config = await loadConfigOrExit();
|
|
7286
9019
|
if (!config)
|
|
7287
9020
|
return;
|
|
7288
9021
|
const endpoint = options.type === "process-model" ? "processModelGlobalLayout" : "graphLayout";
|
|
7289
|
-
const [err, result] = await
|
|
9022
|
+
const [err, result] = await catchError(pmGet(config, `/query/${appId}/${options.stage}/${endpoint}`));
|
|
7290
9023
|
if (err) {
|
|
7291
9024
|
fail(err.message, "Check the app id (uip pm apps list) and that the stage has a completed ingestion.");
|
|
7292
9025
|
return;
|
|
@@ -7297,16 +9030,16 @@ function registerQueryCommand(program2) {
|
|
|
7297
9030
|
Data: result
|
|
7298
9031
|
});
|
|
7299
9032
|
});
|
|
7300
|
-
queryCmd.command("percentile <app-id>").description("Compute percentiles of a numeric field").requiredOption("--field <field-id>", "Field id to compute percentiles over (uip pm query info)").requiredOption("--values <list>", "Comma-separated percentile points in 0..1, e.g. '0.5,0.9,0.95'").option("--filters <json-file>", "Path to a JSON file with a filter spec (array of AND-ed filter groups)").option("--filters-json <json>", "Inline JSON filter spec").addOption(new Option("--stage <stage>", "App stage").choices(
|
|
9033
|
+
queryCmd.command("percentile <app-id>").description("Compute percentiles of a numeric field").requiredOption("--field <field-id>", "Field id to compute percentiles over (uip pm query info)").requiredOption("--values <list>", "Comma-separated percentile points in 0..1, e.g. '0.5,0.9,0.95'").option("--filters <json-file>", "Path to a JSON file with a filter spec (array of AND-ed filter groups)").option("--filters-json <json>", "Inline JSON filter spec").addOption(new Option("--stage <stage>", "App stage").choices(STAGES7).default("dev")).examples(QUERY_PERCENTILE_EXAMPLES).trackedAction(processContext, async (appId, options) => {
|
|
7301
9034
|
const config = await loadConfigOrExit();
|
|
7302
9035
|
if (!config)
|
|
7303
9036
|
return;
|
|
7304
|
-
const [buildErr, body] = await
|
|
9037
|
+
const [buildErr, body] = await catchError(buildPercentileBody(options));
|
|
7305
9038
|
if (buildErr) {
|
|
7306
9039
|
fail(buildErr.message, "Pass --values as comma-separated numbers in 0..1 and a valid --filters/--filters-json spec.");
|
|
7307
9040
|
return;
|
|
7308
9041
|
}
|
|
7309
|
-
const [err, result] = await
|
|
9042
|
+
const [err, result] = await catchError(pmPost(config, `/query/${appId}/${options.stage}/percentile`, body));
|
|
7310
9043
|
if (err) {
|
|
7311
9044
|
fail(err.message, "Check the app id, the field id (uip pm query info) and that the stage has a completed ingestion.");
|
|
7312
9045
|
return;
|
|
@@ -7319,12 +9052,12 @@ function registerQueryCommand(program2) {
|
|
|
7319
9052
|
});
|
|
7320
9053
|
}
|
|
7321
9054
|
function registerBodyQuery(queryCmd, spec) {
|
|
7322
|
-
const cmd = queryCmd.command(`${spec.name} <app-id>`).description(spec.summary).option("--body <json-file>", "Path to a JSON file with the request body").option("--body-json <json>", "Inline JSON request body").addOption(new Option("--stage <stage>", "App stage").choices(
|
|
9055
|
+
const cmd = queryCmd.command(`${spec.name} <app-id>`).description(spec.summary).option("--body <json-file>", "Path to a JSON file with the request body").option("--body-json <json>", "Inline JSON request body").addOption(new Option("--stage <stage>", "App stage").choices(STAGES7).default("dev"));
|
|
7323
9056
|
if (spec.withLimit) {
|
|
7324
9057
|
cmd.option("--limit <n>", "Max rows to return (server clamps to 1..1000)");
|
|
7325
9058
|
}
|
|
7326
9059
|
if (spec.withSugar) {
|
|
7327
|
-
cmd.option("--group-by <cols>", "Comma-separated field columns (names or ids) to group by").option("--metric <col:fn[:alias]>",
|
|
9060
|
+
cmd.option("--group-by <cols>", "Comma-separated field columns (names or ids) to group by").option("--metric <col:fn[:alias]>", `Aggregate a field; fn is ${[...AGGREGATIONS.keys()].join("|")}. Repeatable.`, (val, prev) => [...prev, val], []).option("--process-graph", "Answer over the process graph (activities and transitions) rather than the plain data model").option("--conformance", "Answer over the model-only side: the steps the reference model expected of a case that the case did not take, so a skipped activity shows up against the cases that skipped it. Without it the query answers over what the log did do");
|
|
7328
9061
|
}
|
|
7329
9062
|
if (spec.examples) {
|
|
7330
9063
|
cmd.examples(spec.examples);
|
|
@@ -7333,14 +9066,14 @@ function registerBodyQuery(queryCmd, spec) {
|
|
|
7333
9066
|
const config = await loadConfigOrExit();
|
|
7334
9067
|
if (!config)
|
|
7335
9068
|
return;
|
|
7336
|
-
const [prepErr, prepared] = await
|
|
9069
|
+
const [prepErr, prepared] = await catchError(resolveRunBody(config, appId, spec, options));
|
|
7337
9070
|
if (prepErr || !prepared) {
|
|
7338
9071
|
fail(prepErr?.message ?? "Failed to resolve the query body.", "Pass a body with --body/--body-json, or use --group-by/--metric (names from 'uip pm query info') — the two are mutually exclusive.");
|
|
7339
9072
|
return;
|
|
7340
9073
|
}
|
|
7341
9074
|
const { body, reshape } = prepared;
|
|
7342
9075
|
const query = options.limit === undefined ? "" : `?limit=${encodeURIComponent(options.limit)}`;
|
|
7343
|
-
const [apiErr, result] = await
|
|
9076
|
+
const [apiErr, result] = await catchError(pmPost(config, `/query/${appId}/${options.stage}${spec.subpath}${query}`, body));
|
|
7344
9077
|
if (apiErr) {
|
|
7345
9078
|
fail(apiErr.message, "Check the app id (uip pm apps list), that the stage has a completed ingestion, and the request body shape.");
|
|
7346
9079
|
return;
|
|
@@ -7355,6 +9088,9 @@ function registerBodyQuery(queryCmd, spec) {
|
|
|
7355
9088
|
async function resolveRunBody(config, appId, spec, options) {
|
|
7356
9089
|
const usingSugar = spec.withSugar === true && (options.groupBy !== undefined || (options.metric?.length ?? 0) > 0);
|
|
7357
9090
|
if (!usingSugar) {
|
|
9091
|
+
if (options.processGraph === true || options.conformance === true) {
|
|
9092
|
+
throw new Error("--process-graph/--conformance only apply to the --group-by/--metric sugar. " + "A raw body already carries 'isProcessGraph'/'isConformance'.");
|
|
9093
|
+
}
|
|
7358
9094
|
return {
|
|
7359
9095
|
body: await resolveJsonBody(options.body, options.bodyJson),
|
|
7360
9096
|
reshape: null
|
|
@@ -7379,24 +9115,24 @@ async function buildAggregateBody(config, appId, options) {
|
|
|
7379
9115
|
if (!config)
|
|
7380
9116
|
return null;
|
|
7381
9117
|
const info = await pmGet(config, `/query/${appId}/${options.stage}/info`);
|
|
7382
|
-
const
|
|
9118
|
+
const resolve2 = buildFieldResolver(info);
|
|
7383
9119
|
const groupCols = (options.groupBy ?? "").split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
7384
|
-
const groupIds = groupCols.map(
|
|
9120
|
+
const groupIds = groupCols.map(resolve2);
|
|
7385
9121
|
const metrics = (options.metric ?? []).map(parseMetricSpec);
|
|
7386
9122
|
const aggregates = metrics.map((m) => ({
|
|
7387
9123
|
id: m.alias,
|
|
7388
|
-
argument:
|
|
9124
|
+
argument: resolve2(m.column),
|
|
7389
9125
|
aggregation: m.fn
|
|
7390
9126
|
}));
|
|
7391
9127
|
if (groupIds.length === 0 && aggregates.length === 0) {
|
|
7392
9128
|
throw new Error("Provide at least one --group-by column or --metric.");
|
|
7393
9129
|
}
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
};
|
|
9130
|
+
const body = { groupBy: groupIds, aggregates };
|
|
9131
|
+
if (options.processGraph === true)
|
|
9132
|
+
body.isProcessGraph = true;
|
|
9133
|
+
if (options.conformance === true)
|
|
9134
|
+
body.isConformance = true;
|
|
9135
|
+
return { body, groupCols, groupIds, metrics };
|
|
7400
9136
|
}
|
|
7401
9137
|
function parseMetricSpec(spec) {
|
|
7402
9138
|
const parts = spec.split(":").map((s) => s.trim());
|
|
@@ -7404,13 +9140,14 @@ function parseMetricSpec(spec) {
|
|
|
7404
9140
|
if (!column || !fn) {
|
|
7405
9141
|
throw new Error(`Invalid --metric '${spec}': expected 'column:fn' (e.g. 'Event_count:average').`);
|
|
7406
9142
|
}
|
|
7407
|
-
|
|
7408
|
-
|
|
9143
|
+
const name = fn.toLowerCase().replace(/-/g, "_");
|
|
9144
|
+
const wireFn = AGGREGATIONS.get(name);
|
|
9145
|
+
if (wireFn === undefined) {
|
|
9146
|
+
throw new Error(`Invalid aggregation '${fn}' in --metric '${spec}': use ${[...AGGREGATIONS.keys()].join(", ")}.`);
|
|
7409
9147
|
}
|
|
7410
9148
|
const safeCol = column.replace(/[^A-Za-z0-9]/g, "_");
|
|
7411
|
-
return { alias: alias || `${
|
|
9149
|
+
return { alias: alias || `${name}_${safeCol}`, column, fn: wireFn };
|
|
7412
9150
|
}
|
|
7413
|
-
var sanitizeKey = (s) => s.replace(/[^A-Za-z0-9]/g, "").toLowerCase();
|
|
7414
9151
|
function buildFieldResolver(info) {
|
|
7415
9152
|
const byName = new Map;
|
|
7416
9153
|
const ids = new Set;
|
|
@@ -7443,14 +9180,14 @@ function reshapeAggregate(result, groupCols, groupIds, metrics) {
|
|
|
7443
9180
|
const keyMap = new Map;
|
|
7444
9181
|
for (const k of Object.keys(data))
|
|
7445
9182
|
keyMap.set(sanitizeKey(k), k);
|
|
7446
|
-
const
|
|
9183
|
+
const cell2 = (id) => {
|
|
7447
9184
|
const k = keyMap.get(sanitizeKey(id));
|
|
7448
9185
|
return k ? data[k] : undefined;
|
|
7449
9186
|
};
|
|
7450
9187
|
const valuesOf = (c) => field(c ?? {}, "values") ?? [];
|
|
7451
9188
|
const ungroupedOf = (c) => field(c ?? {}, "ungrouped") ?? null;
|
|
7452
|
-
const groupCells = groupIds.map((id) =>
|
|
7453
|
-
const metricCells = metrics.map((m) =>
|
|
9189
|
+
const groupCells = groupIds.map((id) => cell2(id));
|
|
9190
|
+
const metricCells = metrics.map((m) => cell2(m.alias));
|
|
7454
9191
|
if (groupCols.length === 0) {
|
|
7455
9192
|
const totals = {};
|
|
7456
9193
|
metrics.forEach((m, i) => {
|
|
@@ -7475,19 +9212,64 @@ function reshapeAggregate(result, groupCols, groupIds, metrics) {
|
|
|
7475
9212
|
return rows;
|
|
7476
9213
|
}
|
|
7477
9214
|
async function buildPercentileBody(options) {
|
|
7478
|
-
const
|
|
7479
|
-
if (
|
|
9215
|
+
const values2 = options.values.split(",").map((s) => s.trim()).filter((s) => s.length > 0).map(Number);
|
|
9216
|
+
if (values2.length === 0 || values2.some((v) => !Number.isFinite(v))) {
|
|
7480
9217
|
throw new Error(`Invalid --values '${options.values}': expected comma-separated numbers.`);
|
|
7481
9218
|
}
|
|
7482
9219
|
let filters = [];
|
|
7483
9220
|
if (options.filters !== undefined || options.filtersJson !== undefined) {
|
|
7484
9221
|
filters = await resolveJsonBody(options.filters, options.filtersJson, "filters");
|
|
7485
9222
|
}
|
|
7486
|
-
return { field: options.field, values, filters };
|
|
9223
|
+
return { field: options.field, values: values2, filters };
|
|
9224
|
+
}
|
|
9225
|
+
|
|
9226
|
+
// src/commands/simulations.ts
|
|
9227
|
+
var STAGES8 = ["dev", "published"];
|
|
9228
|
+
var SIMULATIONS_LIST_EXAMPLES = [
|
|
9229
|
+
{
|
|
9230
|
+
Description: "List the simulations saved on a process app's dev stage",
|
|
9231
|
+
Command: "uip pm simulations list 9c46289e",
|
|
9232
|
+
Output: {
|
|
9233
|
+
Code: "PmSimulationsList",
|
|
9234
|
+
Data: [
|
|
9235
|
+
{
|
|
9236
|
+
DefinitionMetadata: {
|
|
9237
|
+
Name: "Two more approvers",
|
|
9238
|
+
SimulationId: "bfd3d274-a5cc-429c-9d65-9671a71a1a52",
|
|
9239
|
+
IngestionId: "7792c4cd-d302-4747-b7f3-2b4f67547a91",
|
|
9240
|
+
ProcessId: "Process"
|
|
9241
|
+
},
|
|
9242
|
+
RunMetadata: {
|
|
9243
|
+
Status: "successWithWarnings",
|
|
9244
|
+
NumberOfCases: 1000,
|
|
9245
|
+
NumberOfRuns: 40
|
|
9246
|
+
}
|
|
9247
|
+
}
|
|
9248
|
+
]
|
|
9249
|
+
}
|
|
9250
|
+
}
|
|
9251
|
+
];
|
|
9252
|
+
function registerSimulationsCommand(program2) {
|
|
9253
|
+
const simulationsCmd = program2.command("simulations").description("Read the process simulations (what-if scenarios) saved on a process app");
|
|
9254
|
+
simulationsCmd.command("list <app-id>").description("List the simulations saved on a process app stage").addOption(new Option("--stage <stage>", "App stage").choices(STAGES8).default("dev")).examples(SIMULATIONS_LIST_EXAMPLES).trackedAction(processContext, async (appId, options) => {
|
|
9255
|
+
const config = await loadConfigOrExit();
|
|
9256
|
+
if (!config)
|
|
9257
|
+
return;
|
|
9258
|
+
const [apiErr, result] = await catchError(pmtGet(config, appId, `/apps/${encodeURIComponent(appId)}/${options.stage}/simulations`));
|
|
9259
|
+
if (apiErr) {
|
|
9260
|
+
fail(apiErr.message, "Check the app id (uip pm apps list), that you have access to it, and that process simulation is enabled on this tenant.");
|
|
9261
|
+
return;
|
|
9262
|
+
}
|
|
9263
|
+
OutputFormatter.success({
|
|
9264
|
+
Result: "Success",
|
|
9265
|
+
Code: "PmSimulationsList",
|
|
9266
|
+
Data: unwrapData(result)
|
|
9267
|
+
});
|
|
9268
|
+
});
|
|
7487
9269
|
}
|
|
7488
9270
|
|
|
7489
9271
|
// src/commands/transformations.ts
|
|
7490
|
-
var
|
|
9272
|
+
var STAGES9 = ["dev", "published"];
|
|
7491
9273
|
var TRANSFORMATIONS_RUN_EXAMPLES = [
|
|
7492
9274
|
{
|
|
7493
9275
|
Description: "Rebuild a single dbt model and its dependents on dev",
|
|
@@ -7543,11 +9325,11 @@ var TRANSFORMATIONS_APPLY_EXAMPLES = [
|
|
|
7543
9325
|
];
|
|
7544
9326
|
function registerTransformationsCommand(program2) {
|
|
7545
9327
|
const transformationsCmd = program2.command("transformations").description("Work with the dbt SQL transformations of a process app");
|
|
7546
|
-
transformationsCmd.command("list <app-id>").description("List the transformation files of a process app").addOption(new Option("--stage <stage>", "App stage to read from").choices(
|
|
9328
|
+
transformationsCmd.command("list <app-id>").description("List the transformation files of a process app").addOption(new Option("--stage <stage>", "App stage to read from").choices(STAGES9).default("dev")).trackedAction(processContext, async (appId, options) => {
|
|
7547
9329
|
const config = await loadConfigOrExit();
|
|
7548
9330
|
if (!config)
|
|
7549
9331
|
return;
|
|
7550
|
-
const [apiErr, result] = await
|
|
9332
|
+
const [apiErr, result] = await catchError(pmGet(config, `/apps/${appId}/${options.stage}/transformation/tree`));
|
|
7551
9333
|
if (apiErr) {
|
|
7552
9334
|
fail(apiErr.message, "Check the app id (uip pm apps list) and your authentication.");
|
|
7553
9335
|
return;
|
|
@@ -7558,17 +9340,17 @@ function registerTransformationsCommand(program2) {
|
|
|
7558
9340
|
Data: result
|
|
7559
9341
|
});
|
|
7560
9342
|
});
|
|
7561
|
-
transformationsCmd.command("get <app-id> <path>").description("Get the content of a transformation file, plus its ETag — which " + "`update` requires as --etag: it is what proves the edit was " + "based on this version").addOption(new Option("--stage <stage>", "App stage").choices(
|
|
9343
|
+
transformationsCmd.command("get <app-id> <path>").description("Get the content of a transformation file, plus its ETag — which " + "`update` requires as --etag: it is what proves the edit was " + "based on this version").addOption(new Option("--stage <stage>", "App stage").choices(STAGES9).default("dev")).option("--destination <local-file>", "Write content to this local file instead of the output envelope").trackedAction(processContext, async (appId, path2, options) => {
|
|
7562
9344
|
const config = await loadConfigOrExit();
|
|
7563
9345
|
if (!config)
|
|
7564
9346
|
return;
|
|
7565
|
-
const [err, file] = await
|
|
9347
|
+
const [err, file] = await catchError(pmGetRaw(config, `/apps/${appId}/${options.stage}/transformation/tree/${path2}`));
|
|
7566
9348
|
if (err) {
|
|
7567
9349
|
fail(err.message, "Check the file path (uip pm transformations list).");
|
|
7568
9350
|
return;
|
|
7569
9351
|
}
|
|
7570
9352
|
if (options.destination !== undefined) {
|
|
7571
|
-
const [writeErr] = await
|
|
9353
|
+
const [writeErr] = await catchError(getFileSystem().writeFile(options.destination, file.content));
|
|
7572
9354
|
if (writeErr) {
|
|
7573
9355
|
fail(writeErr.message, "Check the destination path and that the disk is writable.");
|
|
7574
9356
|
return;
|
|
@@ -7578,28 +9360,28 @@ function registerTransformationsCommand(program2) {
|
|
|
7578
9360
|
Result: "Success",
|
|
7579
9361
|
Code: "PmTransformationsGet",
|
|
7580
9362
|
Data: {
|
|
7581
|
-
Path:
|
|
9363
|
+
Path: path2,
|
|
7582
9364
|
ETag: file.etag,
|
|
7583
9365
|
...options.destination !== undefined ? { Destination: options.destination } : { Content: file.content }
|
|
7584
9366
|
}
|
|
7585
9367
|
});
|
|
7586
9368
|
});
|
|
7587
|
-
transformationsCmd.command("update <app-id> <path>").description("Update a transformation file from a local file (ETag-safe) — pass " + "the --etag that `get` returned for the version you edited, so a " + "concurrent change is refused instead of overwritten").requiredOption("--file <local-file>", "Local file with the new content").requiredOption("--etag <etag>", "ETag of the file this edit is based on, as returned by " + "'uip pm transformations get'").addOption(new Option("--stage <stage>", "App stage").choices(
|
|
9369
|
+
transformationsCmd.command("update <app-id> <path>").description("Update a transformation file from a local file (ETag-safe) — pass " + "the --etag that `get` returned for the version you edited, so a " + "concurrent change is refused instead of overwritten").requiredOption("--file <local-file>", "Local file with the new content").requiredOption("--etag <etag>", "ETag of the file this edit is based on, as returned by " + "'uip pm transformations get'").addOption(new Option("--stage <stage>", "App stage").choices(STAGES9).default("dev")).examples(TRANSFORMATIONS_UPDATE_EXAMPLES).trackedAction(processContext, async (appId, path2, options) => {
|
|
7588
9370
|
const config = await loadConfigOrExit();
|
|
7589
9371
|
if (!config)
|
|
7590
9372
|
return;
|
|
7591
|
-
const [err, etag] = await
|
|
9373
|
+
const [err, etag] = await catchError(updateFile(config, appId, path2, options));
|
|
7592
9374
|
if (err) {
|
|
7593
|
-
fail(err.message, isConflictError(err) ? conflictInstructions(`uip pm transformations get ${appId} ${
|
|
9375
|
+
fail(err.message, isConflictError(err) ? conflictInstructions(`uip pm transformations get ${appId} ${path2} --destination <file>`) : "Check the file path, and that --etag is the ETag " + `'uip pm transformations get ${appId} ${path2}' returns.`);
|
|
7594
9376
|
return;
|
|
7595
9377
|
}
|
|
7596
9378
|
OutputFormatter.success({
|
|
7597
9379
|
Result: "Success",
|
|
7598
9380
|
Code: "PmTransformationsUpdate",
|
|
7599
|
-
Data: { Path:
|
|
9381
|
+
Data: { Path: path2, ETag: etag }
|
|
7600
9382
|
});
|
|
7601
9383
|
});
|
|
7602
|
-
transformationsCmd.command("create <app-id> <path>").description("Create a new transformation file from a local file " + "(use 'update' to modify an existing one)").requiredOption("--file <local-file>", "Local file with the new content").addOption(new Option("--stage <stage>", "App stage").choices(
|
|
9384
|
+
transformationsCmd.command("create <app-id> <path>").description("Create a new transformation file from a local file " + "(use 'update' to modify an existing one)").requiredOption("--file <local-file>", "Local file with the new content").addOption(new Option("--stage <stage>", "App stage").choices(STAGES9).default("dev")).examples(TRANSFORMATIONS_CREATE_EXAMPLES).trackedAction(processContext, async (appId, path2, options) => {
|
|
7603
9385
|
const config = await loadConfigOrExit();
|
|
7604
9386
|
if (!config)
|
|
7605
9387
|
return;
|
|
@@ -7608,7 +9390,7 @@ function registerTransformationsCommand(program2) {
|
|
|
7608
9390
|
fail(`Local file not found: ${options.file}`, "Check the --file path.");
|
|
7609
9391
|
return;
|
|
7610
9392
|
}
|
|
7611
|
-
const [err, etag] = await
|
|
9393
|
+
const [err, etag] = await catchError(pmCreateRaw(config, `/apps/${appId}/${options.stage}/transformation/tree/${path2}?type=File`, String(content)));
|
|
7612
9394
|
if (err) {
|
|
7613
9395
|
fail(err.message, "Check the app id and that the path does not already exist (use 'update' to modify an existing file).");
|
|
7614
9396
|
return;
|
|
@@ -7616,7 +9398,7 @@ function registerTransformationsCommand(program2) {
|
|
|
7616
9398
|
OutputFormatter.success({
|
|
7617
9399
|
Result: "Success",
|
|
7618
9400
|
Code: "PmTransformationsCreate",
|
|
7619
|
-
Data: { Path:
|
|
9401
|
+
Data: { Path: path2, ETag: etag }
|
|
7620
9402
|
});
|
|
7621
9403
|
});
|
|
7622
9404
|
transformationsCmd.command("run <app-id>").description("Run the dbt transformations on the dev stage").addOption(new Option("--stage <stage>", "App stage (only 'dev' supported)").choices(["dev"]).default("dev")).option("--model <model-path>", "Run only this model (e.g. 'models/Cases.sql') and its dependents").option("--wait", "Block until the build reaches a terminal state; exit non-zero on failure (auto-prints the dbt error)").option("--timeout <seconds>", "Max seconds to wait when --wait is set", "1800").option("--poll-interval <seconds>", "Seconds between status polls when --wait is set", "5").examples(TRANSFORMATIONS_RUN_EXAMPLES).trackedAction(processContext, async (appId, options) => {
|
|
@@ -7625,14 +9407,14 @@ function registerTransformationsCommand(program2) {
|
|
|
7625
9407
|
return;
|
|
7626
9408
|
let before = {};
|
|
7627
9409
|
if (options.wait) {
|
|
7628
|
-
const [readErr, snapshot] = await
|
|
9410
|
+
const [readErr, snapshot] = await catchError(readBuildStatus(config, appId));
|
|
7629
9411
|
if (readErr) {
|
|
7630
9412
|
fail(readErr.message, "Check the app id (uip pm apps list) and your authentication.");
|
|
7631
9413
|
return;
|
|
7632
9414
|
}
|
|
7633
9415
|
before = snapshot;
|
|
7634
9416
|
}
|
|
7635
|
-
const [err] = await
|
|
9417
|
+
const [err] = await catchError(pmPost(config, `/apps/${appId}/${options.stage}/transformation/build`, options.model === undefined ? { type: 0 } : { type: 1, modelPath: options.model }));
|
|
7636
9418
|
if (err) {
|
|
7637
9419
|
fail(err.message, "Check that data was ingested and no other build is running.");
|
|
7638
9420
|
return;
|
|
@@ -7654,7 +9436,7 @@ function registerTransformationsCommand(program2) {
|
|
|
7654
9436
|
const config = await loadConfigOrExit();
|
|
7655
9437
|
if (!config)
|
|
7656
9438
|
return;
|
|
7657
|
-
const [err] = await
|
|
9439
|
+
const [err] = await catchError(pmPost(config, `/apps/${appId}/dev/transformation/build/cancel`));
|
|
7658
9440
|
if (err) {
|
|
7659
9441
|
fail(err.message, `Check the app id and that a build is running ('uip pm transformations status ${appId}').`);
|
|
7660
9442
|
return;
|
|
@@ -7665,20 +9447,20 @@ function registerTransformationsCommand(program2) {
|
|
|
7665
9447
|
Data: { AppId: appId, Status: "Cancelling" }
|
|
7666
9448
|
});
|
|
7667
9449
|
});
|
|
7668
|
-
transformationsCmd.command("apply <app-id>").description("Re-run the full data transformation on already-ingested data " + "(unlike 'run', which builds only changed dev models)").addOption(new Option("--stage <stage>", "App stage").choices(
|
|
9450
|
+
transformationsCmd.command("apply <app-id>").description("Re-run the full data transformation on already-ingested data " + "(unlike 'run', which builds only changed dev models)").addOption(new Option("--stage <stage>", "App stage").choices(STAGES9).default("dev")).option("--wait", "Block until the transform reaches a terminal state; exit non-zero on failure (auto-prints the dbt error)").option("--timeout <seconds>", "Max seconds to wait when --wait is set", "1800").option("--poll-interval <seconds>", "Seconds between status polls when --wait is set", "5").examples(TRANSFORMATIONS_APPLY_EXAMPLES).trackedAction(processContext, async (appId, options) => {
|
|
7669
9451
|
const config = await loadConfigOrExit();
|
|
7670
9452
|
if (!config)
|
|
7671
9453
|
return;
|
|
7672
9454
|
let before = {};
|
|
7673
9455
|
if (options.wait) {
|
|
7674
|
-
const [readErr, snapshot] = await
|
|
9456
|
+
const [readErr, snapshot] = await catchError(readLastIngestion(config, appId, options.stage));
|
|
7675
9457
|
if (readErr) {
|
|
7676
9458
|
fail(readErr.message, "Check the app id (uip pm apps list) and your authentication.");
|
|
7677
9459
|
return;
|
|
7678
9460
|
}
|
|
7679
9461
|
before = snapshot;
|
|
7680
9462
|
}
|
|
7681
|
-
const [err] = await
|
|
9463
|
+
const [err] = await catchError(pmPost(config, `/apps/${appId}/${options.stage}/transform`));
|
|
7682
9464
|
if (err) {
|
|
7683
9465
|
fail(err.message, "Check the app id and that data has been ingested (uip pm apps list).");
|
|
7684
9466
|
return;
|
|
@@ -7700,7 +9482,7 @@ function registerTransformationsCommand(program2) {
|
|
|
7700
9482
|
const config = await loadConfigOrExit();
|
|
7701
9483
|
if (!config)
|
|
7702
9484
|
return;
|
|
7703
|
-
const [err, result] = await
|
|
9485
|
+
const [err, result] = await catchError(pmGet(config, `/apps/${appId}/dev/transformation/build/status`));
|
|
7704
9486
|
if (err) {
|
|
7705
9487
|
fail(err.message, "Check the app id.");
|
|
7706
9488
|
return;
|
|
@@ -7715,7 +9497,7 @@ function registerTransformationsCommand(program2) {
|
|
|
7715
9497
|
const config = await loadConfigOrExit();
|
|
7716
9498
|
if (!config)
|
|
7717
9499
|
return;
|
|
7718
|
-
const [err, result] = await
|
|
9500
|
+
const [err, result] = await catchError(pmGet(config, `/apps/${appId}/dev/transformation/build/logs`));
|
|
7719
9501
|
if (err) {
|
|
7720
9502
|
fail(err.message, "Check the app id.");
|
|
7721
9503
|
return;
|
|
@@ -7727,12 +9509,12 @@ function registerTransformationsCommand(program2) {
|
|
|
7727
9509
|
});
|
|
7728
9510
|
});
|
|
7729
9511
|
}
|
|
7730
|
-
async function updateFile(config, appId,
|
|
9512
|
+
async function updateFile(config, appId, path2, options) {
|
|
7731
9513
|
const content = await getFileSystem().readFile(options.file, "utf-8");
|
|
7732
9514
|
if (content === null) {
|
|
7733
9515
|
throw new Error(`Local file not found: ${options.file}`);
|
|
7734
9516
|
}
|
|
7735
|
-
return pmPutRaw(config, `/apps/${appId}/${options.stage}/transformation/tree/${
|
|
9517
|
+
return pmPutRaw(config, `/apps/${appId}/${options.stage}/transformation/tree/${path2}?type=File`, String(content), options.etag);
|
|
7736
9518
|
}
|
|
7737
9519
|
|
|
7738
9520
|
// src/tool.ts
|
|
@@ -7745,12 +9527,15 @@ var metadata = {
|
|
|
7745
9527
|
var registerCommands = async (program2) => {
|
|
7746
9528
|
registerAppsCommand(program2);
|
|
7747
9529
|
registerAppTypesCommand(program2);
|
|
9530
|
+
registerConformanceCommand(program2);
|
|
9531
|
+
registerDeviationsCommand(program2);
|
|
7748
9532
|
registerFilesCommand(program2);
|
|
7749
9533
|
registerIngestionsCommand(program2);
|
|
7750
9534
|
registerQueryCommand(program2);
|
|
9535
|
+
registerSimulationsCommand(program2);
|
|
7751
9536
|
registerTransformationsCommand(program2);
|
|
7752
9537
|
};
|
|
7753
9538
|
|
|
7754
9539
|
export { Command, metadata, registerCommands };
|
|
7755
9540
|
|
|
7756
|
-
//# debugId=
|
|
9541
|
+
//# debugId=4E7CA921094D69AF64756E2164756E21
|