@uipath/function-tool 1.205.0-preview.267 → 1.205.0-preview.269
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/README.md +0 -8
- package/dist/THIRD-PARTY-NOTICES.md +22 -10
- package/dist/{cliRunner-23vh097s.js → cliRunner-6t7v6dqr.js} +1114 -445
- package/dist/{index-d5j82d97.js → index-at7vc5xq.js} +4 -4
- package/dist/{index-vrbn7etk.js → index-h092rmmt.js} +2 -2
- package/dist/{index-7gz8y4st.js → index-jhfvqtwr.js} +4 -4
- package/dist/index-q8r0mcyb.js +10221 -0
- package/dist/{packager-tool-n4sgccez.js → packager-tool-1shggyya.js} +5 -5
- package/dist/packager-tool.js +1 -1
- package/dist/tool.js +13 -13
- package/package.json +2 -2
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
__require,
|
|
3
|
+
__toESM
|
|
4
|
+
} from "./packager-tool-1de529jm.js";
|
|
2
5
|
|
|
3
6
|
// ../../node_modules/@uipath/coded-functions-js-cli/dist/cliRunner.js
|
|
4
7
|
import { createRequire } from "node:module";
|
|
5
8
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
6
|
-
import { dirname as
|
|
9
|
+
import { dirname as dirname7, join as join22 } from "node:path";
|
|
7
10
|
import { readFileSync as readFileSync17 } from "node:fs";
|
|
8
11
|
import { execSync } from "node:child_process";
|
|
9
12
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
10
13
|
import { join } from "node:path";
|
|
11
14
|
import { homedir } from "node:os";
|
|
12
|
-
import { existsSync as existsSync3, writeFileSync as
|
|
15
|
+
import { existsSync as existsSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
13
16
|
import { join as join4, resolve } from "node:path";
|
|
14
17
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
15
18
|
import { join as join2 } from "node:path";
|
|
16
19
|
import { spawnSync } from "node:child_process";
|
|
17
|
-
import { copyFileSync, existsSync as existsSync2, readFileSync as readFileSync2
|
|
20
|
+
import { copyFileSync, existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
18
21
|
import { basename, extname, isAbsolute, join as join3 } from "node:path";
|
|
19
|
-
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as
|
|
22
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "node:fs";
|
|
20
23
|
import { basename as basename3, join as join9, resolve as resolve3 } from "node:path";
|
|
21
24
|
import { spawn } from "node:child_process";
|
|
22
|
-
import { writeFileSync as
|
|
25
|
+
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync3 } from "node:fs";
|
|
23
26
|
import { extname as extname2, join as join5 } from "node:path";
|
|
24
27
|
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
|
|
25
28
|
import { join as join6 } from "node:path";
|
|
26
|
-
import ts2 from "typescript";
|
|
27
29
|
import { dirname, resolve as resolve2 } from "node:path";
|
|
28
|
-
import ts from "typescript";
|
|
29
30
|
import { basename as basename2, dirname as dirname2 } from "node:path";
|
|
30
|
-
import
|
|
31
|
-
import { existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync4, readFileSync as readFileSync4, readdirSync, symlinkSync, writeFileSync as writeFileSync6, cpSync } from "node:fs";
|
|
31
|
+
import { existsSync as existsSync5, linkSync, lstatSync, mkdirSync as mkdirSync4, readFileSync as readFileSync4, readdirSync, symlinkSync, writeFileSync as writeFileSync5, cpSync } from "node:fs";
|
|
32
32
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
33
33
|
import { createRequire as createRequire2 } from "node:module";
|
|
34
34
|
import { join as join7 } from "node:path";
|
|
35
35
|
import { pathToFileURL } from "node:url";
|
|
36
36
|
import { execSync as execSync2 } from "node:child_process";
|
|
37
|
-
import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync2, writeFileSync as
|
|
37
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync2, writeFileSync as writeFileSync6 } from "node:fs";
|
|
38
38
|
import { extname as extname3, join as join8 } from "node:path";
|
|
39
|
-
import { mkdirSync as mkdirSync5, readFileSync as readFileSync9, readdirSync as readdirSync3, rmSync, statSync, writeFileSync as
|
|
39
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync9, readdirSync as readdirSync3, rmSync, statSync, writeFileSync as writeFileSync9 } from "node:fs";
|
|
40
40
|
import { join as join13, resolve as resolve5 } from "node:path";
|
|
41
41
|
import { randomUUID } from "node:crypto";
|
|
42
42
|
import { createRequire as createRequire3 } from "module";
|
|
@@ -77,29 +77,29 @@ import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:
|
|
|
77
77
|
import { join as join12 } from "node:path";
|
|
78
78
|
import { createRequire as createRequire4 } from "node:module";
|
|
79
79
|
import { register } from "node:module";
|
|
80
|
-
import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as
|
|
80
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync8 } from "node:fs";
|
|
81
81
|
import { join as join11 } from "node:path";
|
|
82
82
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
83
83
|
import { existsSync as existsSync11, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync2 } from "node:fs";
|
|
84
84
|
import { emitKeypressEvents } from "node:readline";
|
|
85
85
|
import { join as join14, resolve as resolve6 } from "node:path";
|
|
86
|
-
import { existsSync as existsSync14, readFileSync as readFileSync13, writeFileSync as
|
|
86
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13, writeFileSync as writeFileSync11 } from "node:fs";
|
|
87
87
|
import { join as join17, resolve as resolve7 } from "node:path";
|
|
88
88
|
import { createHash } from "node:crypto";
|
|
89
89
|
import { existsSync as existsSync13, readFileSync as readFileSync12, readdirSync as readdirSync5, statSync as statSync3 } from "node:fs";
|
|
90
90
|
import { join as join16, relative as relative2 } from "node:path";
|
|
91
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as
|
|
91
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync10 } from "node:fs";
|
|
92
92
|
import { dirname as dirname4, join as join15 } from "node:path";
|
|
93
|
-
import { existsSync as existsSync16, mkdirSync as mkdirSync8, readFileSync as readFileSync15, renameSync, rmSync as
|
|
93
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync8, readFileSync as readFileSync15, renameSync, rmSync as rmSync3, writeFileSync as writeFileSync13 } from "node:fs";
|
|
94
94
|
import { join as join19, resolve as resolve9 } from "node:path";
|
|
95
95
|
import { spawn as spawn2 } from "node:child_process";
|
|
96
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync7, readFileSync as readFileSync14, writeFileSync as
|
|
97
|
-
import { isAbsolute as isAbsolute3, join as join18, relative as relative3, resolve as resolve8 } from "node:path";
|
|
98
|
-
import { mkdirSync as mkdirSync9, writeFileSync as
|
|
96
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync7, readFileSync as readFileSync14, rmSync as rmSync2, writeFileSync as writeFileSync12 } from "node:fs";
|
|
97
|
+
import { basename as basename5, dirname as dirname5, isAbsolute as isAbsolute3, join as join18, relative as relative3, resolve as resolve8 } from "node:path";
|
|
98
|
+
import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync14 } from "node:fs";
|
|
99
99
|
import { join as join20, resolve as resolve10 } from "node:path";
|
|
100
100
|
import { resolve as resolve11 } from "node:path";
|
|
101
|
-
import { existsSync as existsSync17, mkdirSync as mkdirSync10, readFileSync as readFileSync16, readdirSync as readdirSync6, writeFileSync as
|
|
102
|
-
import { dirname as
|
|
101
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync10, readFileSync as readFileSync16, readdirSync as readdirSync6, writeFileSync as writeFileSync15 } from "node:fs";
|
|
102
|
+
import { dirname as dirname6, join as join21, resolve as resolve12 } from "node:path";
|
|
103
103
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
104
104
|
import { spawn as spawn3 } from "node:child_process";
|
|
105
105
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -113,7 +113,7 @@ function __accessProp(key) {
|
|
|
113
113
|
}
|
|
114
114
|
var __toESMCache_node;
|
|
115
115
|
var __toESMCache_esm;
|
|
116
|
-
var
|
|
116
|
+
var __toESM2 = (mod, isNodeMode, target) => {
|
|
117
117
|
var canCache = mod != null && typeof mod === "object";
|
|
118
118
|
if (canCache) {
|
|
119
119
|
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
@@ -134,7 +134,7 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
134
134
|
return to;
|
|
135
135
|
};
|
|
136
136
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
137
|
-
var
|
|
137
|
+
var __require2 = /* @__PURE__ */ createRequire(import.meta.url);
|
|
138
138
|
var require_error = __commonJS((exports) => {
|
|
139
139
|
|
|
140
140
|
class CommanderError extends Error {
|
|
@@ -703,11 +703,11 @@ var require_suggestSimilar = __commonJS((exports) => {
|
|
|
703
703
|
exports.suggestSimilar = suggestSimilar;
|
|
704
704
|
});
|
|
705
705
|
var require_command = __commonJS((exports) => {
|
|
706
|
-
var EventEmitter =
|
|
707
|
-
var childProcess4 =
|
|
708
|
-
var path3 =
|
|
709
|
-
var fs7 =
|
|
710
|
-
var process22 =
|
|
706
|
+
var EventEmitter = __require2("node:events").EventEmitter;
|
|
707
|
+
var childProcess4 = __require2("node:child_process");
|
|
708
|
+
var path3 = __require2("node:path");
|
|
709
|
+
var fs7 = __require2("node:fs");
|
|
710
|
+
var process22 = __require2("node:process");
|
|
711
711
|
var { Argument, humanReadableArgName } = require_argument();
|
|
712
712
|
var { CommanderError } = require_error();
|
|
713
713
|
var { Help } = require_help();
|
|
@@ -1961,7 +1961,7 @@ var require_commander = __commonJS((exports) => {
|
|
|
1961
1961
|
exports.InvalidArgumentError = InvalidArgumentError;
|
|
1962
1962
|
exports.InvalidOptionArgumentError = InvalidArgumentError;
|
|
1963
1963
|
});
|
|
1964
|
-
var import__ =
|
|
1964
|
+
var import__ = __toESM2(require_commander(), 1);
|
|
1965
1965
|
var {
|
|
1966
1966
|
program,
|
|
1967
1967
|
createCommand,
|
|
@@ -2459,37 +2459,43 @@ async function copyProjectFiles(fs7, sourcePath, destPath, lockFile, packOptions
|
|
|
2459
2459
|
}
|
|
2460
2460
|
await walk(sourcePath, destPath);
|
|
2461
2461
|
}
|
|
2462
|
+
var NPM_PRODUCTION_FLAGS = ["--omit=dev", "--ignore-scripts", "--allow-git=none"];
|
|
2463
|
+
var BUN_PRODUCTION_FLAGS = ["--production", "--ignore-scripts"];
|
|
2464
|
+
var STRICT_INSTALL_ENV = "UIPATH_FUNCTIONS_REQUIRE_LOCK_FILE";
|
|
2462
2465
|
var COMMANDS = {
|
|
2463
2466
|
npm: {
|
|
2464
2467
|
bin: "npm",
|
|
2465
|
-
args: ({ production
|
|
2468
|
+
args: ({ production }) => [
|
|
2466
2469
|
"install",
|
|
2467
|
-
...production === true ?
|
|
2468
|
-
...preferOffline === true ? ["--prefer-offline"] : []
|
|
2470
|
+
...production === true ? NPM_PRODUCTION_FLAGS : []
|
|
2469
2471
|
],
|
|
2472
|
+
strictArgs: ({ production }) => [
|
|
2473
|
+
"ci",
|
|
2474
|
+
...production === true ? NPM_PRODUCTION_FLAGS : []
|
|
2475
|
+
],
|
|
2476
|
+
strictlyReads: ["npm"],
|
|
2470
2477
|
verifyArgs: ["ci", "--dry-run", "--no-audit", "--no-fund"],
|
|
2471
2478
|
saysLockDiffers: (output) => output.includes("EUSAGE")
|
|
2472
2479
|
},
|
|
2473
2480
|
bun: {
|
|
2474
2481
|
bin: "bun",
|
|
2475
|
-
args: ({ production
|
|
2482
|
+
args: ({ production }) => [
|
|
2483
|
+
"install",
|
|
2484
|
+
...production === true ? BUN_PRODUCTION_FLAGS : []
|
|
2485
|
+
],
|
|
2486
|
+
strictArgs: ({ production }) => [
|
|
2476
2487
|
"install",
|
|
2477
|
-
...production === true ?
|
|
2478
|
-
|
|
2488
|
+
...production === true ? BUN_PRODUCTION_FLAGS : [],
|
|
2489
|
+
"--frozen-lockfile"
|
|
2479
2490
|
],
|
|
2491
|
+
strictlyReads: ["bun", "npm"],
|
|
2480
2492
|
verifyArgs: ["install", "--frozen-lockfile", "--dry-run"],
|
|
2481
2493
|
saysLockDiffers: (output) => output.includes("lockfile had changes")
|
|
2482
2494
|
}
|
|
2483
2495
|
};
|
|
2484
2496
|
var FALLBACK_ORDER = ["npm", "bun"];
|
|
2497
|
+
var DESIGN_TIME_MANAGER = SUPPORTED_MANAGERS.find((manager) => manager.name === "npm");
|
|
2485
2498
|
var PACKAGE_MANAGER_NAMES = Object.keys(COMMANDS);
|
|
2486
|
-
var RUNNER_REGISTRY_CONFIG = `@uipath:registry=https://npm.pkg.github.com
|
|
2487
|
-
//npm.pkg.github.com/:_authToken=\${GITHUB_TOKEN}`;
|
|
2488
|
-
function writeRunnerRegistryConfig(dir) {
|
|
2489
|
-
if (process.env["GITHUB_TOKEN"] === undefined || process.env["GITHUB_TOKEN"] === "")
|
|
2490
|
-
return;
|
|
2491
|
-
writeFileSync3(join3(dir, REGISTRY_CONFIG_FILE), RUNNER_REGISTRY_CONFIG, "utf-8");
|
|
2492
|
-
}
|
|
2493
2499
|
function shareRegistryConfig(fromDir, toDir) {
|
|
2494
2500
|
if (fromDir === toDir)
|
|
2495
2501
|
return;
|
|
@@ -2543,7 +2549,7 @@ function detectProjectManager(cwd) {
|
|
|
2543
2549
|
}
|
|
2544
2550
|
function resolvePackageManager(cwd, required) {
|
|
2545
2551
|
const { name, bin, shell } = required === undefined ? chosenInvocation(cwd) : requiredInvocation(required);
|
|
2546
|
-
const { args, verifyArgs, saysLockDiffers } = COMMANDS[name];
|
|
2552
|
+
const { args, strictArgs, verifyArgs, saysLockDiffers } = COMMANDS[name];
|
|
2547
2553
|
return {
|
|
2548
2554
|
name,
|
|
2549
2555
|
verifyLock(dir) {
|
|
@@ -2561,11 +2567,17 @@ ${result.stderr ?? ""}`;
|
|
|
2561
2567
|
},
|
|
2562
2568
|
runInstall(dir, options = {}) {
|
|
2563
2569
|
shareRegistryConfig(cwd, dir);
|
|
2564
|
-
|
|
2570
|
+
let argv = args(options);
|
|
2571
|
+
if (options.production === true) {
|
|
2572
|
+
const mode = chooseInstallMode(name, dir);
|
|
2573
|
+
console.log(mode.report);
|
|
2574
|
+
if (mode.strict)
|
|
2575
|
+
argv = strictArgs(options);
|
|
2576
|
+
}
|
|
2565
2577
|
console.log(`Running: ${bin} ${argv.join(" ")}`);
|
|
2566
2578
|
const result = spawnSync(bin, argv, {
|
|
2567
2579
|
cwd: dir,
|
|
2568
|
-
stdio: "inherit",
|
|
2580
|
+
stdio: ["inherit", 2, "inherit"],
|
|
2569
2581
|
shell
|
|
2570
2582
|
});
|
|
2571
2583
|
if (result.status !== 0) {
|
|
@@ -2574,6 +2586,18 @@ ${result.stderr ?? ""}`;
|
|
|
2574
2586
|
}
|
|
2575
2587
|
};
|
|
2576
2588
|
}
|
|
2589
|
+
function chooseInstallMode(name, dir) {
|
|
2590
|
+
const present = presentLockFiles(dir);
|
|
2591
|
+
const reproducible = COMMANDS[name].strictlyReads.map((owner) => SUPPORTED_MANAGERS.find((manager) => manager.name === owner).lockFile).find((lockFile) => present.has(lockFile));
|
|
2592
|
+
if (reproducible !== undefined) {
|
|
2593
|
+
return { strict: true, report: `Install mode: strict, reproducing ${reproducible} with ${name}.` };
|
|
2594
|
+
}
|
|
2595
|
+
const missing = present.size === 0 ? "the project has no lock file" : `${name} cannot install strictly from ${[...present].join(" and ")}`;
|
|
2596
|
+
if (/^(1|true)$/i.test(process.env[STRICT_INSTALL_ENV] ?? "")) {
|
|
2597
|
+
return { strict: true, report: `Install mode: strict, as the host requires, although ${missing}.` };
|
|
2598
|
+
}
|
|
2599
|
+
return { strict: false, report: `Install mode: regular, ${missing}.` };
|
|
2600
|
+
}
|
|
2577
2601
|
function chooseManager(cwd) {
|
|
2578
2602
|
const available = detectAvailableManagers();
|
|
2579
2603
|
const desired = detectProjectManager(cwd);
|
|
@@ -2622,17 +2646,27 @@ function checkDependenciesInstalled(cwd) {
|
|
|
2622
2646
|
return {
|
|
2623
2647
|
ready: false,
|
|
2624
2648
|
problem: "node_modules not found.",
|
|
2625
|
-
remedyCommand: describeInstallCommand(
|
|
2649
|
+
remedyCommand: describeInstallCommand()
|
|
2650
|
+
};
|
|
2651
|
+
}
|
|
2652
|
+
function checkDesignTimeManager(cwd) {
|
|
2653
|
+
const present = presentLockFiles(cwd);
|
|
2654
|
+
const foreign = SUPPORTED_MANAGERS.filter((manager) => manager !== DESIGN_TIME_MANAGER && present.has(manager.lockFile)).map((manager) => manager.lockFile);
|
|
2655
|
+
if (foreign.length === 0)
|
|
2656
|
+
return { ready: true, problem: null, remedyCommand: null };
|
|
2657
|
+
const found = foreign.join(" and ");
|
|
2658
|
+
return {
|
|
2659
|
+
ready: false,
|
|
2660
|
+
problem: `Found ${found}. Projects built and run on a developer machine use ` + `${DESIGN_TIME_MANAGER.name}'s ${DESIGN_TIME_MANAGER.lockFile}: delete ${found}.`,
|
|
2661
|
+
remedyCommand: describeInstallCommand()
|
|
2626
2662
|
};
|
|
2627
2663
|
}
|
|
2628
2664
|
function checkLockCurrent(cwd) {
|
|
2629
|
-
const
|
|
2630
|
-
if (
|
|
2631
|
-
|
|
2632
|
-
return { ready: false, problem, remedyCommand };
|
|
2665
|
+
const { lockFile } = DESIGN_TIME_MANAGER;
|
|
2666
|
+
if (!existsSync2(join3(cwd, lockFile))) {
|
|
2667
|
+
return { ready: false, problem: `${lockFile} not found.`, remedyCommand: describeInstallCommand() };
|
|
2633
2668
|
}
|
|
2634
|
-
const {
|
|
2635
|
-
const { verdict, detail } = resolvePackageManager(cwd).verifyLock(cwd);
|
|
2669
|
+
const { verdict, detail } = resolveDesignTimePackageManager(cwd).verifyLock(cwd);
|
|
2636
2670
|
if (verdict === "current")
|
|
2637
2671
|
return { ready: true, problem: null, remedyCommand: null };
|
|
2638
2672
|
if (verdict === "unknown") {
|
|
@@ -2645,14 +2679,41 @@ function checkLockCurrent(cwd) {
|
|
|
2645
2679
|
return {
|
|
2646
2680
|
ready: false,
|
|
2647
2681
|
problem: detail === "" ? `${lockFile} is out of date.` : `${lockFile} is out of date: ${detail}`,
|
|
2648
|
-
remedyCommand:
|
|
2682
|
+
remedyCommand: describeInstallCommand()
|
|
2683
|
+
};
|
|
2684
|
+
}
|
|
2685
|
+
function npmGitDependencyQuery(shell) {
|
|
2686
|
+
return ["query", shell ? '":type(git)"' : ":type(git)", "--package-lock-only"];
|
|
2687
|
+
}
|
|
2688
|
+
function checkNoGitDependencies(cwd) {
|
|
2689
|
+
const { lockFile } = DESIGN_TIME_MANAGER;
|
|
2690
|
+
const { bin, shell } = requiredInvocation(DESIGN_TIME_MANAGER.name);
|
|
2691
|
+
const result = spawnSync(bin, npmGitDependencyQuery(shell), { cwd, encoding: "utf-8", shell });
|
|
2692
|
+
if (result.status !== 0) {
|
|
2693
|
+
const detail = firstComplaint(`${result.stdout ?? ""}
|
|
2694
|
+
${result.stderr ?? ""}`);
|
|
2695
|
+
return {
|
|
2696
|
+
ready: false,
|
|
2697
|
+
problem: `Could not check ${lockFile} for git dependencies${detail === "" ? "." : `: ${detail}`}`,
|
|
2698
|
+
remedyCommand: null
|
|
2699
|
+
};
|
|
2700
|
+
}
|
|
2701
|
+
const names = new Set(JSON.parse(result.stdout).map(({ location }) => location.split("node_modules/").at(-1)));
|
|
2702
|
+
if (names.size === 0)
|
|
2703
|
+
return { ready: true, problem: null, remedyCommand: null };
|
|
2704
|
+
return {
|
|
2705
|
+
ready: false,
|
|
2706
|
+
problem: `Git dependencies cannot be packaged: ${[...names].sort().join(", ")}. Depend on a registry version of each.`,
|
|
2707
|
+
remedyCommand: describeInstallCommand()
|
|
2649
2708
|
};
|
|
2650
2709
|
}
|
|
2651
|
-
function describeInstallCommand(
|
|
2652
|
-
const
|
|
2653
|
-
const { bin, args } = COMMANDS[name];
|
|
2710
|
+
function describeInstallCommand() {
|
|
2711
|
+
const { bin, args } = COMMANDS[DESIGN_TIME_MANAGER.name];
|
|
2654
2712
|
return `${bin} ${args({}).join(" ")}`;
|
|
2655
2713
|
}
|
|
2714
|
+
function resolveDesignTimePackageManager(cwd) {
|
|
2715
|
+
return resolvePackageManager(cwd, DESIGN_TIME_MANAGER.name);
|
|
2716
|
+
}
|
|
2656
2717
|
function affectsDependencyInstall(fileName) {
|
|
2657
2718
|
return CANDIDATE_LOCK_FILES.includes(fileName);
|
|
2658
2719
|
}
|
|
@@ -2672,6 +2733,13 @@ function registerNewCommand(program2) {
|
|
|
2672
2733
|
process.exit(1);
|
|
2673
2734
|
}
|
|
2674
2735
|
ensureSetup();
|
|
2736
|
+
let manager;
|
|
2737
|
+
try {
|
|
2738
|
+
manager = resolveDesignTimePackageManager(projectDir);
|
|
2739
|
+
} catch (err) {
|
|
2740
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
2741
|
+
process.exit(1);
|
|
2742
|
+
}
|
|
2675
2743
|
const withSample = !opts.empty;
|
|
2676
2744
|
const sampleFile = `functions/${SAMPLE_FUNCTION.name}.${lang}`;
|
|
2677
2745
|
scaffoldProject({
|
|
@@ -2681,13 +2749,13 @@ function registerNewCommand(program2) {
|
|
|
2681
2749
|
functions: withSample ? { [SAMPLE_FUNCTION.name]: `${sampleFile}:${SAMPLE_FUNCTION.entryExport}` } : {}
|
|
2682
2750
|
});
|
|
2683
2751
|
if (withSample) {
|
|
2684
|
-
|
|
2752
|
+
writeFileSync3(join4(projectDir, sampleFile), lang === "ts" ? HELLO_TS : HELLO_JS, "utf-8");
|
|
2685
2753
|
}
|
|
2686
2754
|
console.log(`
|
|
2687
2755
|
Created ${projectName}/`);
|
|
2688
2756
|
console.log("Installing dependencies...");
|
|
2689
2757
|
try {
|
|
2690
|
-
|
|
2758
|
+
manager.runInstall(projectDir);
|
|
2691
2759
|
} catch (err) {
|
|
2692
2760
|
console.error(err instanceof Error ? err.message : String(err));
|
|
2693
2761
|
process.exit(1);
|
|
@@ -2705,12 +2773,12 @@ Ready. Next steps:`);
|
|
|
2705
2773
|
}
|
|
2706
2774
|
var SERVER_RUNNER_DIR = ".uipath/server-runner";
|
|
2707
2775
|
var DESIGN_TIME_ENV = "DESIGN_TIME";
|
|
2708
|
-
var RUNTIME_VERSION = "^0.
|
|
2776
|
+
var RUNTIME_VERSION = "^0.10.0";
|
|
2709
2777
|
var TSX_VERSION = "^4.0.0";
|
|
2710
2778
|
var COREIPC_VERSION = "2.5.3";
|
|
2711
2779
|
var SIGNALR_VERSION = "8.0.7";
|
|
2712
2780
|
var TRACE_MAPPING_VERSION = "0.3.25";
|
|
2713
|
-
function generateAggregator(functionsMap, cwd, variant,
|
|
2781
|
+
function generateAggregator(functionsMap, cwd, variant, contractsByFile = {}) {
|
|
2714
2782
|
const lang = detectLanguage(functionsMap);
|
|
2715
2783
|
const ext = lang === "javascript" ? "js" : "ts";
|
|
2716
2784
|
const fileToFunctions = new Map;
|
|
@@ -2744,9 +2812,9 @@ function generateAggregator(functionsMap, cwd, variant, derivedByPath = {}) {
|
|
|
2744
2812
|
}
|
|
2745
2813
|
const imports = files.map((file, i) => `import f${i} from "${importPrefix}${file}";`).join(`
|
|
2746
2814
|
`);
|
|
2747
|
-
const
|
|
2815
|
+
const relevantContracts = {};
|
|
2748
2816
|
for (const file of files) {
|
|
2749
|
-
const d =
|
|
2817
|
+
const d = contractsByFile[file];
|
|
2750
2818
|
if (!d)
|
|
2751
2819
|
continue;
|
|
2752
2820
|
const entry = {};
|
|
@@ -2755,22 +2823,23 @@ function generateAggregator(functionsMap, cwd, variant, derivedByPath = {}) {
|
|
|
2755
2823
|
if (d.output !== undefined)
|
|
2756
2824
|
entry.output = d.output;
|
|
2757
2825
|
if (entry.input !== undefined || entry.output !== undefined)
|
|
2758
|
-
|
|
2826
|
+
relevantContracts[file] = entry;
|
|
2759
2827
|
}
|
|
2760
|
-
const
|
|
2828
|
+
const hasContracts = Object.keys(relevantContracts).length > 0;
|
|
2761
2829
|
const entries = files.map((file, i) => {
|
|
2762
|
-
const def =
|
|
2830
|
+
const def = hasContracts ? `__lower(f${i}, "${file}")` : `f${i}`;
|
|
2763
2831
|
return `{ functionDef: ${def}, functionPath: "${file}" }`;
|
|
2764
2832
|
}).join(", ");
|
|
2765
2833
|
const header = lang === "javascript" ? `// @ts-check
|
|
2766
2834
|
` : "";
|
|
2767
|
-
const loweringBlock =
|
|
2835
|
+
const loweringBlock = hasContracts ? `const __contracts = ${JSON.stringify(relevantContracts, null, 2)};
|
|
2836
|
+
` + `const __lowers = (v) => v !== undefined && !(typeof v === "object" && v !== null && "~standard" in v);
|
|
2768
2837
|
` + `function __lower(def, path) {
|
|
2769
|
-
` + ` const d =
|
|
2838
|
+
` + ` const d = __contracts[path];
|
|
2770
2839
|
` + ` if (!d) return def;
|
|
2771
2840
|
` + ` const out = { ...def };
|
|
2772
|
-
` + ` if (d.input !== undefined) out.input = d.input;
|
|
2773
|
-
` + ` if (d.output !== undefined) out.output = d.output;
|
|
2841
|
+
` + ` if (__lowers(def.input) && d.input !== undefined) out.input = d.input;
|
|
2842
|
+
` + ` if (__lowers(def.output) && d.output !== undefined) out.output = d.output;
|
|
2774
2843
|
` + ` return out;
|
|
2775
2844
|
` + `}
|
|
2776
2845
|
|
|
@@ -2781,7 +2850,7 @@ function generateAggregator(functionsMap, cwd, variant, derivedByPath = {}) {
|
|
|
2781
2850
|
|
|
2782
2851
|
` + `${loweringBlock}` + `export default createApp([${entries}]);
|
|
2783
2852
|
`;
|
|
2784
|
-
|
|
2853
|
+
writeFileSync4(outputFile, content, "utf-8");
|
|
2785
2854
|
return outputFile;
|
|
2786
2855
|
}
|
|
2787
2856
|
function detectLanguage(functionsMap) {
|
|
@@ -2846,70 +2915,89 @@ function findRouteConflicts(routes) {
|
|
|
2846
2915
|
}
|
|
2847
2916
|
return pairs;
|
|
2848
2917
|
}
|
|
2849
|
-
|
|
2850
|
-
|
|
2918
|
+
var TS;
|
|
2919
|
+
async function loadTypeScript() {
|
|
2920
|
+
TS ??= (await import("typescript")).default;
|
|
2921
|
+
return TS;
|
|
2922
|
+
}
|
|
2923
|
+
function typeToSchema(type, checker, topLevel = true, options = {}) {
|
|
2924
|
+
if (!topLevel && type.flags & TS.TypeFlags.Unknown)
|
|
2851
2925
|
return {};
|
|
2852
|
-
if (type.flags &
|
|
2926
|
+
if (!topLevel && type.flags & TS.TypeFlags.Null)
|
|
2927
|
+
return { type: "null" };
|
|
2928
|
+
if (type.flags & TS.TypeFlags.Boolean)
|
|
2853
2929
|
return { type: "boolean" };
|
|
2854
|
-
if (type.flags &
|
|
2930
|
+
if (type.flags & TS.TypeFlags.BooleanLiteral)
|
|
2855
2931
|
return { type: "boolean" };
|
|
2856
|
-
if (type.flags &
|
|
2932
|
+
if (type.flags & TS.TypeFlags.String)
|
|
2857
2933
|
return { type: "string" };
|
|
2858
|
-
if (type.flags &
|
|
2934
|
+
if (type.flags & TS.TypeFlags.Number)
|
|
2859
2935
|
return { type: "number" };
|
|
2860
|
-
if (type.flags &
|
|
2936
|
+
if (type.flags & TS.TypeFlags.StringLiteral)
|
|
2861
2937
|
return { type: "string", const: type.value };
|
|
2862
|
-
if (type.flags &
|
|
2938
|
+
if (type.flags & TS.TypeFlags.NumberLiteral)
|
|
2863
2939
|
return { type: "number", const: type.value };
|
|
2864
|
-
if (type.flags &
|
|
2940
|
+
if (type.flags & TS.TypeFlags.EnumLiteral && !type.isUnion()) {
|
|
2865
2941
|
const value = type.value;
|
|
2866
2942
|
return typeof value === "number" ? { type: "number", const: value } : { type: "string", const: value };
|
|
2867
2943
|
}
|
|
2868
|
-
if (isDate(type))
|
|
2869
|
-
|
|
2944
|
+
if (isDate(type)) {
|
|
2945
|
+
if (options.allowDate)
|
|
2946
|
+
return { type: "string", format: "date-time" };
|
|
2947
|
+
throw new ContractTypeError("Date", "JSON has no Date; the value arrives as an ISO 8601 string", DIAGNOSTIC_CODES.UNSUPPORTED_DATE);
|
|
2948
|
+
}
|
|
2870
2949
|
if (checker.isArrayType(type)) {
|
|
2871
2950
|
const [elem] = checker.getTypeArguments(type);
|
|
2872
2951
|
if (!elem)
|
|
2873
2952
|
throw new Error("Array type has no element type argument");
|
|
2874
|
-
return { type: "array", items: typeToSchema(elem, checker, false) };
|
|
2953
|
+
return { type: "array", items: atPath("[]", () => typeToSchema(elem, checker, false, options)) };
|
|
2875
2954
|
}
|
|
2876
2955
|
if (isTupleType(type))
|
|
2877
2956
|
reject(type, checker, "tuple types are not supported — use an array or an object");
|
|
2878
2957
|
if (type.isIntersection()) {
|
|
2879
2958
|
for (const member of type.types) {
|
|
2880
|
-
if (member.flags &
|
|
2959
|
+
if (member.flags & TS.TypeFlags.String)
|
|
2881
2960
|
return { type: "string" };
|
|
2882
|
-
if (member.flags &
|
|
2961
|
+
if (member.flags & TS.TypeFlags.Number)
|
|
2883
2962
|
return { type: "number" };
|
|
2884
|
-
if (member.flags &
|
|
2963
|
+
if (member.flags & TS.TypeFlags.Boolean)
|
|
2885
2964
|
return { type: "boolean" };
|
|
2886
2965
|
}
|
|
2887
|
-
return objectToSchema(type, checker);
|
|
2966
|
+
return objectToSchema(type, checker, options);
|
|
2888
2967
|
}
|
|
2889
2968
|
if (type.isUnion())
|
|
2890
|
-
return unionToSchema(type, checker);
|
|
2891
|
-
if (type.flags &
|
|
2969
|
+
return unionToSchema(type, checker, topLevel, options);
|
|
2970
|
+
if (type.flags & TS.TypeFlags.Any)
|
|
2892
2971
|
reject(type, checker, "declare the shape explicitly instead of any");
|
|
2893
|
-
if (type.flags &
|
|
2972
|
+
if (type.flags & TS.TypeFlags.Unknown)
|
|
2894
2973
|
reject(type, checker, "a contract root must declare its shape — unknown is only supported in value positions (e.g. Record<string, unknown>)");
|
|
2895
|
-
if (type.flags & (
|
|
2974
|
+
if (type.flags & (TS.TypeFlags.BigInt | TS.TypeFlags.BigIntLiteral))
|
|
2896
2975
|
reject(type, checker, "JSON has no bigint — use number or string");
|
|
2897
|
-
if (type.flags & (
|
|
2976
|
+
if (type.flags & (TS.TypeFlags.Null | TS.TypeFlags.Undefined | TS.TypeFlags.Void))
|
|
2898
2977
|
reject(type, checker, "a contract member cannot be null/undefined/void on its own");
|
|
2899
|
-
if (type.flags &
|
|
2978
|
+
if (type.flags & TS.TypeFlags.ESSymbol)
|
|
2900
2979
|
reject(type, checker, "symbols are not serializable");
|
|
2901
2980
|
if (type.getCallSignatures().length > 0)
|
|
2902
2981
|
reject(type, checker, "function types cannot be part of a contract");
|
|
2903
|
-
if (type.flags &
|
|
2904
|
-
return objectToSchema(type, checker);
|
|
2982
|
+
if (type.flags & TS.TypeFlags.Object)
|
|
2983
|
+
return objectToSchema(type, checker, options);
|
|
2905
2984
|
reject(type, checker);
|
|
2906
2985
|
}
|
|
2907
|
-
function unionToSchema(type, checker) {
|
|
2908
|
-
const parts = type.types.filter((t) => !(t.flags & (
|
|
2909
|
-
if (parts.length ===
|
|
2986
|
+
function unionToSchema(type, checker, topLevel, options) {
|
|
2987
|
+
const parts = type.types.filter((t) => !(t.flags & (TS.TypeFlags.Undefined | TS.TypeFlags.Null | TS.TypeFlags.Void)));
|
|
2988
|
+
if (parts.length === 0) {
|
|
2989
|
+
if (!topLevel && type.types.some((t) => t.flags & TS.TypeFlags.Null))
|
|
2990
|
+
return { type: "null" };
|
|
2991
|
+
reject(type, checker, "a contract member cannot be null/undefined/void on its own");
|
|
2992
|
+
}
|
|
2993
|
+
const schema = membersToSchema(parts, checker, options);
|
|
2994
|
+
return type.types.some((t) => t.flags & TS.TypeFlags.Null) ? withNull(schema) : schema;
|
|
2995
|
+
}
|
|
2996
|
+
function membersToSchema(parts, checker, options) {
|
|
2997
|
+
if (parts.length === 2 && parts.every((t) => t.flags & TS.TypeFlags.BooleanLiteral))
|
|
2910
2998
|
return { type: "boolean" };
|
|
2911
2999
|
if (parts.length === 1)
|
|
2912
|
-
return typeToSchema(parts[0], checker, false);
|
|
3000
|
+
return typeToSchema(parts[0], checker, false, options);
|
|
2913
3001
|
const values = parts.map(literalValue);
|
|
2914
3002
|
if (parts.length > 1 && values.every((v) => v !== undefined)) {
|
|
2915
3003
|
const vals = values;
|
|
@@ -2918,18 +3006,27 @@ function unionToSchema(type, checker) {
|
|
|
2918
3006
|
if (vals.every((v) => typeof v === "number"))
|
|
2919
3007
|
return { type: "number", enum: vals };
|
|
2920
3008
|
}
|
|
2921
|
-
return { anyOf: parts.map((t) => typeToSchema(t, checker, false)) };
|
|
3009
|
+
return { anyOf: parts.map((t) => typeToSchema(t, checker, false, options)) };
|
|
3010
|
+
}
|
|
3011
|
+
function withNull(schema) {
|
|
3012
|
+
return { anyOf: [...schema.anyOf ?? [schema], { type: "null" }] };
|
|
2922
3013
|
}
|
|
2923
|
-
function objectToSchema(type, checker) {
|
|
3014
|
+
function objectToSchema(type, checker, options) {
|
|
2924
3015
|
const properties = {};
|
|
2925
3016
|
const required = [];
|
|
2926
3017
|
for (const sym of checker.getPropertiesOfType(type)) {
|
|
2927
3018
|
const decl = sym.valueDeclaration ?? sym.declarations?.[0];
|
|
2928
3019
|
if (!decl)
|
|
2929
3020
|
throw new Error(`Property "${sym.name}" has no declaration`);
|
|
2930
|
-
const optional = !!(sym.flags &
|
|
3021
|
+
const optional = !!(sym.flags & TS.SymbolFlags.Optional);
|
|
2931
3022
|
const propType = checker.getTypeOfSymbolAtLocation(sym, decl);
|
|
2932
|
-
const propSchema =
|
|
3023
|
+
const propSchema = atPath(sym.name, () => {
|
|
3024
|
+
const schema2 = typeToSchema(optional ? stripUndefined(propType) : propType, checker, false, options);
|
|
3025
|
+
const format = jsDocFormat(sym, checker, options.allowDate);
|
|
3026
|
+
if (format !== undefined)
|
|
3027
|
+
applyFormat(schema2, format, options.allowDate);
|
|
3028
|
+
return schema2;
|
|
3029
|
+
});
|
|
2933
3030
|
const defaultValue = jsDocDefault(sym, checker);
|
|
2934
3031
|
if (defaultValue !== undefined)
|
|
2935
3032
|
propSchema.default = defaultValue;
|
|
@@ -2942,8 +3039,8 @@ function objectToSchema(type, checker) {
|
|
|
2942
3039
|
schema.properties = properties;
|
|
2943
3040
|
if (required.length > 0)
|
|
2944
3041
|
schema.required = required;
|
|
2945
|
-
const stringIndex = checker.getIndexInfoOfType(type,
|
|
2946
|
-
schema.additionalProperties = stringIndex ? typeToSchema(stringIndex.type, checker, false) : false;
|
|
3042
|
+
const stringIndex = checker.getIndexInfoOfType(type, TS.IndexKind.String);
|
|
3043
|
+
schema.additionalProperties = stringIndex ? atPath("*", () => typeToSchema(stringIndex.type, checker, false, options)) : false;
|
|
2947
3044
|
return schema;
|
|
2948
3045
|
}
|
|
2949
3046
|
function jsDocDefault(sym, checker) {
|
|
@@ -2959,46 +3056,104 @@ function jsDocDefault(sym, checker) {
|
|
|
2959
3056
|
return text;
|
|
2960
3057
|
}
|
|
2961
3058
|
}
|
|
3059
|
+
var FORMATS = ["date-time", "date", "time", "email", "uri", "uuid"];
|
|
3060
|
+
function jsDocFormat(sym, checker, lenient = false) {
|
|
3061
|
+
const tag = sym.getJsDocTags(checker).find((t) => t.name === "format");
|
|
3062
|
+
if (!tag)
|
|
3063
|
+
return;
|
|
3064
|
+
const text = (tag.text ?? []).map((p) => p.text).join("").trim();
|
|
3065
|
+
if (!FORMATS.includes(text)) {
|
|
3066
|
+
if (lenient)
|
|
3067
|
+
return;
|
|
3068
|
+
throw new ContractTypeError(`@format ${text}`, `supported formats are ${FORMATS.join(", ")}`, DIAGNOSTIC_CODES.UNSUPPORTED_FORMAT);
|
|
3069
|
+
}
|
|
3070
|
+
return text;
|
|
3071
|
+
}
|
|
3072
|
+
function applyFormat(schema, format, lenient = false) {
|
|
3073
|
+
const arms = (schema.anyOf ?? [schema]).filter((s) => s.type !== "null");
|
|
3074
|
+
if (lenient && arms.some((s) => s.format))
|
|
3075
|
+
return;
|
|
3076
|
+
if (arms.length === 0 || !arms.every((s) => s.type === "string" && s.const === undefined && s.enum === undefined)) {
|
|
3077
|
+
if (lenient)
|
|
3078
|
+
return;
|
|
3079
|
+
throw new ContractTypeError(`@format ${format}`, "a format applies to a string property", DIAGNOSTIC_CODES.UNSUPPORTED_FORMAT);
|
|
3080
|
+
}
|
|
3081
|
+
for (const s of arms)
|
|
3082
|
+
s.format = format;
|
|
3083
|
+
}
|
|
2962
3084
|
function stripUndefined(type) {
|
|
2963
3085
|
if (!type.isUnion())
|
|
2964
3086
|
return type;
|
|
2965
|
-
const parts = type.types.filter((t) => !(t.flags &
|
|
3087
|
+
const parts = type.types.filter((t) => !(t.flags & TS.TypeFlags.Undefined));
|
|
2966
3088
|
return parts.length === 1 ? parts[0] : type;
|
|
2967
3089
|
}
|
|
2968
3090
|
function literalValue(t) {
|
|
2969
|
-
if (t.flags & (
|
|
3091
|
+
if (t.flags & (TS.TypeFlags.StringLiteral | TS.TypeFlags.NumberLiteral | TS.TypeFlags.EnumLiteral)) {
|
|
2970
3092
|
return t.value;
|
|
2971
3093
|
}
|
|
2972
3094
|
return;
|
|
2973
3095
|
}
|
|
2974
3096
|
function isDate(type) {
|
|
2975
|
-
|
|
3097
|
+
const sym = type.getSymbol();
|
|
3098
|
+
return sym?.getName() === "Date" && type.getCallSignatures().length === 0 && !!sym.declarations?.some((d) => d.getSourceFile().hasNoDefaultLib);
|
|
2976
3099
|
}
|
|
2977
3100
|
function isTupleType(type) {
|
|
2978
3101
|
const target = type.target;
|
|
2979
|
-
return !!target && !!(target.objectFlags &
|
|
3102
|
+
return !!target && !!(target.objectFlags & TS.ObjectFlags.Tuple);
|
|
3103
|
+
}
|
|
3104
|
+
|
|
3105
|
+
class ContractTypeError extends Error {
|
|
3106
|
+
typeName;
|
|
3107
|
+
detail;
|
|
3108
|
+
code;
|
|
3109
|
+
path = [];
|
|
3110
|
+
constructor(typeName, detail, code = DIAGNOSTIC_CODES.UNSUPPORTED_TYPE) {
|
|
3111
|
+
super();
|
|
3112
|
+
this.typeName = typeName;
|
|
3113
|
+
this.detail = detail;
|
|
3114
|
+
this.code = code;
|
|
3115
|
+
this.message = this.describe();
|
|
3116
|
+
}
|
|
3117
|
+
under(segment) {
|
|
3118
|
+
this.path.unshift(segment);
|
|
3119
|
+
this.message = this.describe();
|
|
3120
|
+
}
|
|
3121
|
+
describe() {
|
|
3122
|
+
const at = this.path.length > 0 ? ` at ${this.path.join(".").replaceAll(".[]", "[]")}` : "";
|
|
3123
|
+
return `Unsupported type in function contract${at}: ${this.typeName}` + (this.detail ? ` — ${this.detail}` : "") + ". The contract format is a curated JSON Schema subset.";
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
function atPath(segment, derive) {
|
|
3127
|
+
try {
|
|
3128
|
+
return derive();
|
|
3129
|
+
} catch (err) {
|
|
3130
|
+
if (err instanceof ContractTypeError)
|
|
3131
|
+
err.under(segment);
|
|
3132
|
+
throw err;
|
|
3133
|
+
}
|
|
2980
3134
|
}
|
|
2981
3135
|
function reject(type, checker, detail) {
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
};
|
|
3136
|
+
throw new ContractTypeError(checker.typeToString(type), detail);
|
|
3137
|
+
}
|
|
3138
|
+
function consumerCompilerOptions() {
|
|
3139
|
+
return {
|
|
3140
|
+
target: TS.ScriptTarget.ES2020,
|
|
3141
|
+
module: TS.ModuleKind.ESNext,
|
|
3142
|
+
moduleResolution: TS.ModuleResolutionKind.Bundler,
|
|
3143
|
+
allowImportingTsExtensions: true,
|
|
3144
|
+
allowJs: true,
|
|
3145
|
+
strict: true,
|
|
3146
|
+
skipLibCheck: true,
|
|
3147
|
+
noEmit: true
|
|
3148
|
+
};
|
|
3149
|
+
}
|
|
2995
3150
|
function createProgram(fs7, rootNames, options) {
|
|
2996
3151
|
const selfContained = fs7.defaultLibFileName !== undefined;
|
|
2997
3152
|
const host = selfContained ? selfContainedHost(fs7) : diskBackedHost(fs7, options);
|
|
2998
3153
|
if (!selfContained)
|
|
2999
3154
|
assertDefaultLibReachable(host, options);
|
|
3000
|
-
const program2 =
|
|
3001
|
-
return { program: program2, checker: program2.getTypeChecker() };
|
|
3155
|
+
const program2 = TS.createProgram(rootNames, options, host);
|
|
3156
|
+
return { program: program2, checker: program2.getTypeChecker(), host };
|
|
3002
3157
|
}
|
|
3003
3158
|
function assertDefaultLibReachable(host, options) {
|
|
3004
3159
|
const libPath = host.getDefaultLibFileName(options);
|
|
@@ -3006,10 +3161,10 @@ function assertDefaultLibReachable(host, options) {
|
|
|
3006
3161
|
return;
|
|
3007
3162
|
throw new Error(`TypeScript lib not found at "${libPath}".
|
|
3008
3163
|
` + `Type derivation cannot run without it — Array/Record/Date/Promise would resolve to ` + `any and produce wrong schemas.
|
|
3009
|
-
|
|
3164
|
+
That path comes from the 'typescript' module's own location. If it names a directory from another machine, 'typescript' was bundled into the caller: build with '--external typescript' so it resolves from node_modules at runtime. If the project sets "noLib", remove it.`);
|
|
3010
3165
|
}
|
|
3011
3166
|
function diskBackedHost(fs7, options) {
|
|
3012
|
-
const host =
|
|
3167
|
+
const host = TS.createCompilerHost(options, true);
|
|
3013
3168
|
host.getCurrentDirectory = () => fs7.currentDirectory;
|
|
3014
3169
|
const baseGetSourceFile = host.getSourceFile.bind(host);
|
|
3015
3170
|
const baseReadFile = host.readFile.bind(host);
|
|
@@ -3017,7 +3172,7 @@ function diskBackedHost(fs7, options) {
|
|
|
3017
3172
|
const baseDirectoryExists = host.directoryExists?.bind(host);
|
|
3018
3173
|
host.getSourceFile = (name, langVersion, onError, shouldCreate) => {
|
|
3019
3174
|
const text = fs7.readFile(name);
|
|
3020
|
-
return text !== undefined ?
|
|
3175
|
+
return text !== undefined ? TS.createSourceFile(name, text, langVersion, true) : baseGetSourceFile(name, langVersion, onError, shouldCreate);
|
|
3021
3176
|
};
|
|
3022
3177
|
host.readFile = (name) => {
|
|
3023
3178
|
const text = fs7.readFile(name);
|
|
@@ -3031,7 +3186,7 @@ function selfContainedHost(fs7) {
|
|
|
3031
3186
|
return {
|
|
3032
3187
|
getSourceFile: (name, langVersion) => {
|
|
3033
3188
|
const text = fs7.readFile(name);
|
|
3034
|
-
return text !== undefined ?
|
|
3189
|
+
return text !== undefined ? TS.createSourceFile(name, text, langVersion, true) : undefined;
|
|
3035
3190
|
},
|
|
3036
3191
|
getDefaultLibFileName: () => fs7.defaultLibFileName,
|
|
3037
3192
|
getDefaultLibLocation: () => fs7.defaultLibLocation ?? "/",
|
|
@@ -3050,6 +3205,8 @@ function selfContainedHost(fs7) {
|
|
|
3050
3205
|
var DIAGNOSTIC_CODES = {
|
|
3051
3206
|
UNSUPPORTED_VALIDATOR: "unsupported-validator",
|
|
3052
3207
|
UNSUPPORTED_TYPE: "unsupported-type",
|
|
3208
|
+
UNSUPPORTED_DATE: "unsupported-date",
|
|
3209
|
+
UNSUPPORTED_FORMAT: "unsupported-format",
|
|
3053
3210
|
NON_STATIC_LITERAL: "non-static-literal",
|
|
3054
3211
|
UNREADABLE_PROPERTY: "unreadable-property",
|
|
3055
3212
|
MISSING_TYPE_ARGUMENT: "missing-type-argument",
|
|
@@ -3057,51 +3214,64 @@ var DIAGNOSTIC_CODES = {
|
|
|
3057
3214
|
MULTIPLE_FUNCTIONS_PER_FILE: "multiple-functions-per-file",
|
|
3058
3215
|
DEPRECATED_MARKER: "deprecated-marker",
|
|
3059
3216
|
NO_FUNCTION_DEFINITION: "no-function-definition",
|
|
3060
|
-
UNRESOLVED_SOURCE_FILE: "unresolved-source-file"
|
|
3217
|
+
UNRESOLVED_SOURCE_FILE: "unresolved-source-file",
|
|
3218
|
+
UNLINKED_DEFINITION: "unlinked-definition",
|
|
3219
|
+
UNLINKED_CONTRACT_TYPE: "unlinked-contract-type"
|
|
3061
3220
|
};
|
|
3062
|
-
function
|
|
3221
|
+
function walkDefinitions(sourceFile, checker, sdk, options) {
|
|
3063
3222
|
const bindings = sdkImportBindings(sourceFile);
|
|
3064
|
-
const
|
|
3065
|
-
const diagnostics = [];
|
|
3223
|
+
const defs = [];
|
|
3066
3224
|
const visit = (node) => {
|
|
3067
|
-
if (isDefineFunctionCall(node, bindings)) {
|
|
3225
|
+
if (isDefineFunctionCall(node, bindings, checker, sdk)) {
|
|
3068
3226
|
const arg = node.arguments[0];
|
|
3069
|
-
if (arg &&
|
|
3227
|
+
if (arg && TS.isObjectLiteralExpression(arg)) {
|
|
3070
3228
|
const fn = { ...readMetadata(arg) };
|
|
3229
|
+
const diagnostics = [];
|
|
3230
|
+
const markers = [];
|
|
3071
3231
|
for (const field of ["input", "output"]) {
|
|
3072
|
-
const { schema, diagnostic } = resolveField(arg, field, checker, bindings);
|
|
3232
|
+
const { schema, diagnostic, marker } = resolveField(arg, field, checker, bindings, sdk, options);
|
|
3073
3233
|
if (schema !== undefined)
|
|
3074
3234
|
fn[field] = schema;
|
|
3075
3235
|
if (diagnostic)
|
|
3076
3236
|
diagnostics.push({ ...diagnostic, functionName: fn.name, field });
|
|
3237
|
+
if (marker)
|
|
3238
|
+
markers.push(marker);
|
|
3239
|
+
}
|
|
3240
|
+
for (const p of arg.properties) {
|
|
3241
|
+
const name = TS.isPropertyAssignment(p) ? propertyName(p.name) : undefined;
|
|
3242
|
+
if ((name === "input" || name === "output") && p !== findProp(arg, name)) {
|
|
3243
|
+
markers.push(unwrap(p.initializer));
|
|
3244
|
+
}
|
|
3077
3245
|
}
|
|
3078
3246
|
const unreadable = isNestedInFunction(node) ? { fields: [], anyField: false } : unreadableProperties(arg);
|
|
3079
3247
|
if (unreadable.anyField) {
|
|
3080
3248
|
diagnostics.push({
|
|
3081
|
-
...diag(DIAGNOSTIC_CODES.UNREADABLE_PROPERTY, "the definition spreads another object or uses a computed key, so which
|
|
3249
|
+
...diag(DIAGNOSTIC_CODES.UNREADABLE_PROPERTY, "the definition spreads another object or uses a computed key, so which contract fields it carries is not statically known", "warning"),
|
|
3082
3250
|
functionName: fn.name
|
|
3083
3251
|
});
|
|
3084
3252
|
} else {
|
|
3085
3253
|
for (const field of unreadable.fields) {
|
|
3086
3254
|
diagnostics.push({
|
|
3087
|
-
...diag(DIAGNOSTIC_CODES.UNREADABLE_PROPERTY, METADATA_FIELDS.has(field) ? `${field} cannot be read statically: a shorthand property, a method, an
|
|
3255
|
+
...diag(DIAGNOSTIC_CODES.UNREADABLE_PROPERTY, METADATA_FIELDS.has(field) ? `${field} cannot be read statically: a shorthand property, a method, an accessor and a reference to a variable all read as absent. Write it at the defineFunction call as a string literal.` : `${field} is declared as a shorthand property, a method or an accessor, which reads as absent. Write it as \`${field}: <value>\`.`, "warning"),
|
|
3088
3256
|
functionName: fn.name,
|
|
3089
3257
|
...field === "input" || field === "output" ? { field } : {}
|
|
3090
3258
|
});
|
|
3091
3259
|
}
|
|
3092
3260
|
}
|
|
3093
|
-
|
|
3261
|
+
defs.push({ node, fn, diagnostics, markers });
|
|
3094
3262
|
}
|
|
3095
3263
|
}
|
|
3096
|
-
|
|
3264
|
+
TS.forEachChild(node, visit);
|
|
3097
3265
|
};
|
|
3098
3266
|
visit(sourceFile);
|
|
3099
|
-
return
|
|
3267
|
+
return defs;
|
|
3100
3268
|
}
|
|
3101
|
-
function extractFromFiles(files, checker, limits) {
|
|
3269
|
+
function extractFromFiles(files, checker, limits, exportName = "default", sdk, options) {
|
|
3102
3270
|
const functions = [];
|
|
3103
3271
|
const diagnostics = [];
|
|
3272
|
+
const allCalls = [];
|
|
3104
3273
|
const maxPerFile = limits?.maxDefineFunctionsPerFile;
|
|
3274
|
+
const scope = sdk ?? sdkExportsFromImports(files.map((f) => f.sourceFile), checker);
|
|
3105
3275
|
for (const { functionPath, sourceFile } of files) {
|
|
3106
3276
|
if (!sourceFile) {
|
|
3107
3277
|
diagnostics.push({
|
|
@@ -3112,12 +3282,38 @@ function extractFromFiles(files, checker, limits) {
|
|
|
3112
3282
|
});
|
|
3113
3283
|
continue;
|
|
3114
3284
|
}
|
|
3115
|
-
const
|
|
3116
|
-
for (const
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3285
|
+
const defs = walkDefinitions(sourceFile, checker, scope, options);
|
|
3286
|
+
for (const d of defs)
|
|
3287
|
+
allCalls.push({ ...d.fn, functionPath });
|
|
3288
|
+
const hasDefault = exportSymbol(sourceFile, checker, "default") !== undefined;
|
|
3289
|
+
const target = exportSymbol(sourceFile, checker, exportName);
|
|
3290
|
+
const hasTarget = target !== undefined;
|
|
3291
|
+
const served = target && !referencesItself(sourceFile, checker) && targetExpression(target, sourceFile, checker);
|
|
3292
|
+
const linked = defs.find((d) => d.node === served);
|
|
3293
|
+
if (linked) {
|
|
3294
|
+
functions.push({ ...linked.fn, functionPath });
|
|
3295
|
+
for (const d of linked.diagnostics)
|
|
3296
|
+
diagnostics.push({ ...d, file: functionPath });
|
|
3297
|
+
}
|
|
3298
|
+
const markers = hasTarget ? markerCalls(sourceFile, checker, scope) : [];
|
|
3299
|
+
const consumed = new Set(defs.flatMap((d) => d.markers));
|
|
3300
|
+
const unsafeMarker = linked ? markers.some((m) => !consumed.has(m)) : markers.length > 0;
|
|
3301
|
+
if (unsafeMarker) {
|
|
3302
|
+
diagnostics.push({
|
|
3303
|
+
code: DIAGNOSTIC_CODES.UNLINKED_CONTRACT_TYPE,
|
|
3304
|
+
severity: "error",
|
|
3305
|
+
message: `a defineSchema<T>() in this file cannot be derived: only one written directly as the input or output of the defineFunction(...) call the file serves can be.`,
|
|
3306
|
+
file: functionPath
|
|
3307
|
+
});
|
|
3308
|
+
} else if (hasTarget && !linked && defs.length > 0) {
|
|
3309
|
+
diagnostics.push({
|
|
3310
|
+
code: DIAGNOSTIC_CODES.UNLINKED_DEFINITION,
|
|
3311
|
+
severity: "warning",
|
|
3312
|
+
message: `the served export is not a defineFunction(...) call this file makes directly, so no entry point is produced statically; the CLI reads it by executing the module.`,
|
|
3313
|
+
file: functionPath
|
|
3314
|
+
});
|
|
3315
|
+
}
|
|
3316
|
+
if (limits?.requireFunctionPerFile && !hasDefault) {
|
|
3121
3317
|
diagnostics.push({
|
|
3122
3318
|
code: DIAGNOSTIC_CODES.NO_FUNCTION_DEFINITION,
|
|
3123
3319
|
severity: "error",
|
|
@@ -3125,11 +3321,11 @@ function extractFromFiles(files, checker, limits) {
|
|
|
3125
3321
|
file: functionPath
|
|
3126
3322
|
});
|
|
3127
3323
|
}
|
|
3128
|
-
if (maxPerFile !== undefined &&
|
|
3324
|
+
if (maxPerFile !== undefined && defs.length > maxPerFile) {
|
|
3129
3325
|
diagnostics.push({
|
|
3130
3326
|
code: DIAGNOSTIC_CODES.MULTIPLE_FUNCTIONS_PER_FILE,
|
|
3131
3327
|
severity: "error",
|
|
3132
|
-
message: `${
|
|
3328
|
+
message: `${defs.length} functions are defined in one file; at most ${maxPerFile} allowed. Move each defineFunction into its own file.`,
|
|
3133
3329
|
file: functionPath
|
|
3134
3330
|
});
|
|
3135
3331
|
}
|
|
@@ -3138,31 +3334,162 @@ function extractFromFiles(files, checker, limits) {
|
|
|
3138
3334
|
diagnostics.push({
|
|
3139
3335
|
code: DIAGNOSTIC_CODES.AMBIGUOUS_ROUTE,
|
|
3140
3336
|
severity: "warning",
|
|
3141
|
-
message: `route "${a.method} ${a.path}" (${a.functionPath}) overlaps "${b.method} ${b.path}"
|
|
3337
|
+
message: `route "${a.method} ${a.path}" (${a.functionPath}) overlaps "${b.method} ${b.path}" (${b.functionPath}): they match the same requests and are separated only by a ` + `deterministic tie-break — give them distinct paths to make routing unambiguous.`,
|
|
3142
3338
|
functionName: a.name,
|
|
3143
3339
|
file: a.functionPath
|
|
3144
3340
|
});
|
|
3145
3341
|
}
|
|
3146
|
-
return { functions, diagnostics };
|
|
3342
|
+
return { functions, diagnostics, allCalls };
|
|
3147
3343
|
}
|
|
3148
3344
|
var SDK_MODULE = "@uipath/coded-functions-js-sdk";
|
|
3149
|
-
function
|
|
3150
|
-
const
|
|
3151
|
-
if (!
|
|
3345
|
+
function isTypeOnlyImport(node) {
|
|
3346
|
+
const clause = node.importClause;
|
|
3347
|
+
if (!clause)
|
|
3152
3348
|
return false;
|
|
3153
|
-
|
|
3349
|
+
if (clause.isTypeOnly)
|
|
3350
|
+
return true;
|
|
3351
|
+
const named = clause.namedBindings;
|
|
3352
|
+
return !clause.name && named !== undefined && TS.isNamedImports(named) && named.elements.every((e) => e.isTypeOnly);
|
|
3353
|
+
}
|
|
3354
|
+
function isTypeOnlyExport(node) {
|
|
3355
|
+
if (node.isTypeOnly)
|
|
3356
|
+
return true;
|
|
3357
|
+
const clause = node.exportClause;
|
|
3358
|
+
return clause !== undefined && TS.isNamedExports(clause) && clause.elements.every((e) => e.isTypeOnly);
|
|
3359
|
+
}
|
|
3360
|
+
function referencesItself(sourceFile, checker) {
|
|
3361
|
+
const self = checker.getSymbolAtLocation(sourceFile);
|
|
3362
|
+
let found = false;
|
|
3363
|
+
const visit = (node) => {
|
|
3364
|
+
if (found)
|
|
3365
|
+
return;
|
|
3366
|
+
const typeOnly = TS.isImportDeclaration(node) ? isTypeOnlyImport(node) : TS.isExportDeclaration(node) && isTypeOnlyExport(node);
|
|
3367
|
+
const spec = typeOnly ? undefined : TS.isImportDeclaration(node) || TS.isExportDeclaration(node) ? node.moduleSpecifier : TS.isCallExpression(node) && node.expression.kind === TS.SyntaxKind.ImportKeyword ? node.arguments[0] : undefined;
|
|
3368
|
+
if (self && spec && checker.getSymbolAtLocation(spec) === self)
|
|
3369
|
+
found = true;
|
|
3370
|
+
if (TS.isCallExpression(node) && TS.isIdentifier(node.expression) && node.expression.text === "eval")
|
|
3371
|
+
found = true;
|
|
3372
|
+
TS.forEachChild(node, visit);
|
|
3373
|
+
};
|
|
3374
|
+
visit(sourceFile);
|
|
3375
|
+
return found;
|
|
3376
|
+
}
|
|
3377
|
+
function exportSymbol(sourceFile, checker, exportName) {
|
|
3378
|
+
const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
|
|
3379
|
+
return moduleSymbol && checker.getExportsOfModule(moduleSymbol).find((s) => s.escapedName === exportName);
|
|
3380
|
+
}
|
|
3381
|
+
function targetExpression(sym, sourceFile, checker) {
|
|
3382
|
+
const decl = sym.declarations?.length === 1 ? sym.declarations[0] : undefined;
|
|
3383
|
+
if (!decl || decl.getSourceFile() !== sourceFile)
|
|
3384
|
+
return;
|
|
3385
|
+
if (TS.isExportAssignment(decl) && !decl.isExportEquals) {
|
|
3386
|
+
const expr = unwrap(decl.expression);
|
|
3387
|
+
return TS.isIdentifier(expr) ? constInitializer(checker.getSymbolAtLocation(expr), decl, sourceFile, checker, decl) : expr;
|
|
3388
|
+
}
|
|
3389
|
+
if (TS.isExportSpecifier(decl) && !decl.parent.parent.moduleSpecifier) {
|
|
3390
|
+
return constInitializer(checker.getExportSpecifierLocalTargetSymbol(decl), decl, sourceFile, checker);
|
|
3391
|
+
}
|
|
3392
|
+
if (TS.isVariableDeclaration(decl))
|
|
3393
|
+
return constInitializer(sym, undefined, sourceFile, checker);
|
|
3394
|
+
return;
|
|
3395
|
+
}
|
|
3396
|
+
function constInitializer(sym, site, sourceFile, checker, evaluatedAt) {
|
|
3397
|
+
const decl = sym?.declarations?.length === 1 ? sym.declarations[0] : undefined;
|
|
3398
|
+
if (!decl || !TS.isVariableDeclaration(decl) || decl.getSourceFile() !== sourceFile || evaluatedAt !== undefined && decl.end > evaluatedAt.pos || !decl.initializer || !TS.isVariableDeclarationList(decl.parent) || !(decl.parent.flags & TS.NodeFlags.Const)) {
|
|
3399
|
+
return;
|
|
3400
|
+
}
|
|
3401
|
+
let references = 0;
|
|
3402
|
+
const count = (node) => {
|
|
3403
|
+
if (node === site || TS.isTypeNode(node))
|
|
3404
|
+
return;
|
|
3405
|
+
if (TS.isIdentifier(node) && node !== decl.name) {
|
|
3406
|
+
const target = TS.isShorthandPropertyAssignment(node.parent) && node.parent.name === node ? checker.getShorthandAssignmentValueSymbol(node.parent) : checker.getSymbolAtLocation(node);
|
|
3407
|
+
if (target === sym)
|
|
3408
|
+
references++;
|
|
3409
|
+
}
|
|
3410
|
+
TS.forEachChild(node, count);
|
|
3411
|
+
};
|
|
3412
|
+
count(sourceFile);
|
|
3413
|
+
return references === 0 ? unwrap(decl.initializer) : undefined;
|
|
3154
3414
|
}
|
|
3155
3415
|
var MARKER_EXPORTS = ["defineSchema", "type"];
|
|
3416
|
+
function sdkExports(program2, host, options) {
|
|
3417
|
+
const cache = TS.createModuleResolutionCache(program2.getCurrentDirectory(), (f) => f, options);
|
|
3418
|
+
const entries = new Set;
|
|
3419
|
+
for (const sf of program2.getSourceFiles()) {
|
|
3420
|
+
const specifiers = program2.isSourceFileFromExternalLibrary(sf) ? [] : [SDK_MODULE];
|
|
3421
|
+
for (const stmt of sf.statements) {
|
|
3422
|
+
const spec = TS.isImportDeclaration(stmt) || TS.isExportDeclaration(stmt) ? stmt.moduleSpecifier : undefined;
|
|
3423
|
+
if (spec && TS.isStringLiteral(spec))
|
|
3424
|
+
specifiers.push(spec.text);
|
|
3425
|
+
}
|
|
3426
|
+
for (const spec of specifiers) {
|
|
3427
|
+
const resolved = TS.resolveModuleName(spec, sf.fileName, options, host, cache).resolvedModule;
|
|
3428
|
+
const name = resolved?.packageId?.name;
|
|
3429
|
+
if (resolved && name === SDK_MODULE)
|
|
3430
|
+
entries.add(resolved.resolvedFileName);
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
const checker = program2.getTypeChecker();
|
|
3434
|
+
const exports = new Map;
|
|
3435
|
+
for (const file of entries) {
|
|
3436
|
+
const entry = program2.getSourceFile(file);
|
|
3437
|
+
const moduleSymbol = entry && checker.getSymbolAtLocation(entry);
|
|
3438
|
+
if (!moduleSymbol)
|
|
3439
|
+
continue;
|
|
3440
|
+
for (const s of checker.getExportsOfModule(moduleSymbol)) {
|
|
3441
|
+
exports.set(s.flags & TS.SymbolFlags.Alias ? checker.getAliasedSymbol(s) : s, s.name);
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
return exports;
|
|
3445
|
+
}
|
|
3446
|
+
function markerCalls(sourceFile, checker, sdk) {
|
|
3447
|
+
const bindings = sdkImportBindings(sourceFile);
|
|
3448
|
+
const found = [];
|
|
3449
|
+
const visit = (node) => {
|
|
3450
|
+
if (TS.isCallExpression(node)) {
|
|
3451
|
+
if (sdkCallee(node, MARKER_EXPORTS, bindings, checker, sdk))
|
|
3452
|
+
found.push(node);
|
|
3453
|
+
}
|
|
3454
|
+
TS.forEachChild(node, visit);
|
|
3455
|
+
};
|
|
3456
|
+
visit(sourceFile);
|
|
3457
|
+
return found;
|
|
3458
|
+
}
|
|
3459
|
+
function sdkCallee(call, names, bindings, checker, sdk) {
|
|
3460
|
+
const callee = call.expression;
|
|
3461
|
+
if (TS.isIdentifier(callee))
|
|
3462
|
+
return names.find((n) => matchesSdkExport(callee, n, bindings, checker, sdk));
|
|
3463
|
+
if (!TS.isPropertyAccessExpression(callee) || !TS.isIdentifier(callee.expression))
|
|
3464
|
+
return;
|
|
3465
|
+
const ns = callee.expression;
|
|
3466
|
+
if (sdk && sdk.size > 0) {
|
|
3467
|
+
const resolved = sdkExportName(callee.name, checker, sdk);
|
|
3468
|
+
return names.find((n) => n === resolved);
|
|
3469
|
+
}
|
|
3470
|
+
return isSdkNamespace(ns, checker) ? names.find((n) => n === callee.name.text) : undefined;
|
|
3471
|
+
}
|
|
3472
|
+
function isSdkNamespace(id, checker) {
|
|
3473
|
+
const decl = checker.getSymbolAtLocation(id)?.declarations?.[0];
|
|
3474
|
+
if (!decl || !TS.isNamespaceImport(decl))
|
|
3475
|
+
return false;
|
|
3476
|
+
const spec = decl.parent.parent.moduleSpecifier;
|
|
3477
|
+
return TS.isStringLiteral(spec) && spec.text === SDK_MODULE;
|
|
3478
|
+
}
|
|
3479
|
+
function isNamespaceImportBinding(id, checker) {
|
|
3480
|
+
const decl = checker.getSymbolAtLocation(id)?.declarations?.[0];
|
|
3481
|
+
return decl !== undefined && TS.isNamespaceImport(decl);
|
|
3482
|
+
}
|
|
3156
3483
|
function sdkImportBindings(sourceFile) {
|
|
3157
3484
|
const map = new Map;
|
|
3158
3485
|
for (const stmt of sourceFile.statements) {
|
|
3159
|
-
if (!
|
|
3486
|
+
if (!TS.isImportDeclaration(stmt))
|
|
3160
3487
|
continue;
|
|
3161
3488
|
const spec = stmt.moduleSpecifier;
|
|
3162
|
-
if (!
|
|
3489
|
+
if (!TS.isStringLiteral(spec) || spec.text !== SDK_MODULE)
|
|
3163
3490
|
continue;
|
|
3164
3491
|
const named = stmt.importClause?.namedBindings;
|
|
3165
|
-
if (named &&
|
|
3492
|
+
if (named && TS.isNamedImports(named)) {
|
|
3166
3493
|
for (const el of named.elements) {
|
|
3167
3494
|
map.set(el.name.text, (el.propertyName ?? el.name).text);
|
|
3168
3495
|
}
|
|
@@ -3170,36 +3497,91 @@ function sdkImportBindings(sourceFile) {
|
|
|
3170
3497
|
}
|
|
3171
3498
|
return map;
|
|
3172
3499
|
}
|
|
3173
|
-
function matchesSdkExport(
|
|
3174
|
-
|
|
3500
|
+
function matchesSdkExport(callee, exportName, bindings, checker, sdk) {
|
|
3501
|
+
if (sdk && sdk.size > 0)
|
|
3502
|
+
return sdkExportName(callee, checker, sdk) === exportName;
|
|
3503
|
+
if (hasImplementation(callee, checker))
|
|
3504
|
+
return false;
|
|
3505
|
+
return (bindings.size > 0 ? bindings.get(callee.text) : callee.text) === exportName;
|
|
3506
|
+
}
|
|
3507
|
+
function hasImplementation(id, checker) {
|
|
3508
|
+
let sym = checker.getSymbolAtLocation(id);
|
|
3509
|
+
if (sym && sym.flags & TS.SymbolFlags.Alias)
|
|
3510
|
+
sym = checker.getAliasedSymbol(sym);
|
|
3511
|
+
const decl = sym?.declarations?.[0];
|
|
3512
|
+
if (!decl || decl.getSourceFile().isDeclarationFile)
|
|
3513
|
+
return false;
|
|
3514
|
+
return !(TS.getCombinedModifierFlags(decl) & TS.ModifierFlags.Ambient);
|
|
3515
|
+
}
|
|
3516
|
+
function sdkExportsFromImports(sourceFiles, checker) {
|
|
3517
|
+
const exports = new Map;
|
|
3518
|
+
for (const sf of sourceFiles) {
|
|
3519
|
+
for (const stmt of sf?.statements ?? []) {
|
|
3520
|
+
const spec = TS.isImportDeclaration(stmt) || TS.isExportDeclaration(stmt) ? stmt.moduleSpecifier : undefined;
|
|
3521
|
+
if (!spec || !TS.isStringLiteral(spec) || spec.text !== SDK_MODULE)
|
|
3522
|
+
continue;
|
|
3523
|
+
const moduleSymbol = checker.getSymbolAtLocation(spec);
|
|
3524
|
+
for (const s of moduleSymbol ? checker.getExportsOfModule(moduleSymbol) : []) {
|
|
3525
|
+
exports.set(s.flags & TS.SymbolFlags.Alias ? checker.getAliasedSymbol(s) : s, s.name);
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3529
|
+
return exports.size > 0 ? exports : undefined;
|
|
3530
|
+
}
|
|
3531
|
+
function sdkExportName(id, checker, sdk, seen = new Set) {
|
|
3532
|
+
let sym = checker.getSymbolAtLocation(id);
|
|
3533
|
+
if (!sym)
|
|
3534
|
+
return;
|
|
3535
|
+
if (sym.flags & TS.SymbolFlags.Alias)
|
|
3536
|
+
sym = checker.getAliasedSymbol(sym);
|
|
3537
|
+
const name = sdk.get(sym);
|
|
3538
|
+
if (name !== undefined)
|
|
3539
|
+
return name;
|
|
3540
|
+
if (seen.has(sym))
|
|
3541
|
+
return null;
|
|
3542
|
+
seen.add(sym);
|
|
3543
|
+
const decl = sym.declarations?.[0];
|
|
3544
|
+
if (!decl)
|
|
3545
|
+
return;
|
|
3546
|
+
if (TS.isVariableDeclaration(decl) && decl.initializer && TS.isVariableDeclarationList(decl.parent) && decl.parent.flags & TS.NodeFlags.Const) {
|
|
3547
|
+
const init = unwrap(decl.initializer);
|
|
3548
|
+
if (TS.isIdentifier(init))
|
|
3549
|
+
return sdkExportName(init, checker, sdk, seen) ?? null;
|
|
3550
|
+
if (TS.isPropertyAccessExpression(init) && TS.isIdentifier(init.expression) && isNamespaceImportBinding(init.expression, checker)) {
|
|
3551
|
+
return sdkExportName(init.name, checker, sdk, seen) ?? null;
|
|
3552
|
+
}
|
|
3553
|
+
}
|
|
3554
|
+
return null;
|
|
3175
3555
|
}
|
|
3176
|
-
function isDefineFunctionCall(node, bindings) {
|
|
3177
|
-
return
|
|
3556
|
+
function isDefineFunctionCall(node, bindings, checker, sdk) {
|
|
3557
|
+
return TS.isCallExpression(node) && TS.isIdentifier(node.expression) && matchesSdkExport(node.expression, "defineFunction", bindings, checker, sdk);
|
|
3178
3558
|
}
|
|
3179
|
-
function resolveField(obj, field, checker, bindings) {
|
|
3559
|
+
function resolveField(obj, field, checker, bindings, sdk, options) {
|
|
3180
3560
|
const prop = findProp(obj, field);
|
|
3181
3561
|
if (!prop)
|
|
3182
3562
|
return {};
|
|
3183
3563
|
const value = unwrap(prop.initializer);
|
|
3184
|
-
const
|
|
3185
|
-
|
|
3564
|
+
const calleeId = TS.isCallExpression(value) && TS.isIdentifier(value.expression) ? value.expression : undefined;
|
|
3565
|
+
const marker = calleeId && MARKER_EXPORTS.find((name) => matchesSdkExport(calleeId, name, bindings, checker, sdk));
|
|
3566
|
+
if (TS.isCallExpression(value) && marker !== undefined) {
|
|
3186
3567
|
const typeArg = value.typeArguments?.[0];
|
|
3187
3568
|
if (!typeArg) {
|
|
3188
|
-
return { diagnostic: diag(DIAGNOSTIC_CODES.MISSING_TYPE_ARGUMENT, `${field}: defineSchema<T>() is missing its type argument`) };
|
|
3569
|
+
return { diagnostic: diag(DIAGNOSTIC_CODES.MISSING_TYPE_ARGUMENT, `${field}: defineSchema<T>() is missing its type argument`), marker: value };
|
|
3189
3570
|
}
|
|
3190
|
-
const viaDeprecatedName =
|
|
3571
|
+
const viaDeprecatedName = marker === "type";
|
|
3191
3572
|
const deprecation = viaDeprecatedName ? {
|
|
3192
3573
|
code: DIAGNOSTIC_CODES.DEPRECATED_MARKER,
|
|
3193
3574
|
severity: "warning",
|
|
3194
3575
|
message: `${field}: \`type\` is deprecated — use \`defineSchema\` instead`
|
|
3195
3576
|
} : undefined;
|
|
3196
3577
|
try {
|
|
3197
|
-
return { schema: typeToSchema(checker.getTypeFromTypeNode(typeArg), checker), diagnostic: deprecation };
|
|
3578
|
+
return { schema: typeToSchema(checker.getTypeFromTypeNode(typeArg), checker, true, options), diagnostic: deprecation, marker: value };
|
|
3198
3579
|
} catch (err) {
|
|
3199
|
-
|
|
3580
|
+
const code = err instanceof ContractTypeError ? err.code : DIAGNOSTIC_CODES.UNSUPPORTED_TYPE;
|
|
3581
|
+
return { diagnostic: diag(code, `${field}: ${err.message}`), marker: value };
|
|
3200
3582
|
}
|
|
3201
3583
|
}
|
|
3202
|
-
if (
|
|
3584
|
+
if (TS.isObjectLiteralExpression(value)) {
|
|
3203
3585
|
try {
|
|
3204
3586
|
return { schema: literalToSchema(value) };
|
|
3205
3587
|
} catch (err) {
|
|
@@ -3211,7 +3593,7 @@ function resolveField(obj, field, checker, bindings) {
|
|
|
3211
3593
|
};
|
|
3212
3594
|
}
|
|
3213
3595
|
function propertyName(name) {
|
|
3214
|
-
if (
|
|
3596
|
+
if (TS.isIdentifier(name) || TS.isStringLiteral(name) || TS.isNumericLiteral(name)) {
|
|
3215
3597
|
return name.text;
|
|
3216
3598
|
}
|
|
3217
3599
|
return;
|
|
@@ -3219,8 +3601,8 @@ function propertyName(name) {
|
|
|
3219
3601
|
var CONTRACT_FIELDS = new Set(["name", "method", "path", "description", "input", "output"]);
|
|
3220
3602
|
var METADATA_FIELDS = new Set(["name", "method", "path", "description"]);
|
|
3221
3603
|
function isNestedInFunction(node) {
|
|
3222
|
-
for (let current = node.parent;current && !
|
|
3223
|
-
if (
|
|
3604
|
+
for (let current = node.parent;current && !TS.isSourceFile(current); current = current.parent) {
|
|
3605
|
+
if (TS.isFunctionLike(current) || TS.isClassStaticBlockDeclaration(current))
|
|
3224
3606
|
return true;
|
|
3225
3607
|
}
|
|
3226
3608
|
return false;
|
|
@@ -3228,16 +3610,16 @@ function isNestedInFunction(node) {
|
|
|
3228
3610
|
function unreadableProperties(obj) {
|
|
3229
3611
|
const fields = new Set;
|
|
3230
3612
|
for (const property of obj.properties) {
|
|
3231
|
-
if (
|
|
3613
|
+
if (TS.isPropertyAssignment(property)) {
|
|
3232
3614
|
const name2 = propertyName(property.name);
|
|
3233
|
-
if (name2 === undefined)
|
|
3615
|
+
if (name2 === undefined || name2 === "__proto__")
|
|
3234
3616
|
return { fields: [], anyField: true };
|
|
3235
3617
|
if (METADATA_FIELDS.has(name2) && !isReadableMetadataValue(property.initializer)) {
|
|
3236
3618
|
fields.add(name2);
|
|
3237
3619
|
}
|
|
3238
3620
|
continue;
|
|
3239
3621
|
}
|
|
3240
|
-
if (
|
|
3622
|
+
if (TS.isSpreadAssignment(property) || TS.isGetAccessorDeclaration(property))
|
|
3241
3623
|
return { fields: [], anyField: true };
|
|
3242
3624
|
const name = property.name && propertyName(property.name);
|
|
3243
3625
|
if (name === undefined)
|
|
@@ -3248,10 +3630,15 @@ function unreadableProperties(obj) {
|
|
|
3248
3630
|
return { fields: [...fields], anyField: false };
|
|
3249
3631
|
}
|
|
3250
3632
|
function isReadableMetadataValue(value) {
|
|
3251
|
-
return
|
|
3633
|
+
return TS.isStringLiteralLike(unwrap(value));
|
|
3252
3634
|
}
|
|
3253
3635
|
function findProp(obj, field) {
|
|
3254
|
-
|
|
3636
|
+
for (let i = obj.properties.length - 1;i >= 0; i--) {
|
|
3637
|
+
const p = obj.properties[i];
|
|
3638
|
+
if (TS.isPropertyAssignment(p) && propertyName(p.name) === field)
|
|
3639
|
+
return p;
|
|
3640
|
+
}
|
|
3641
|
+
return;
|
|
3255
3642
|
}
|
|
3256
3643
|
function diag(code, message, severity = "error") {
|
|
3257
3644
|
return { code, severity, message };
|
|
@@ -3277,7 +3664,7 @@ function readMetadata(obj) {
|
|
|
3277
3664
|
}
|
|
3278
3665
|
function unwrap(value) {
|
|
3279
3666
|
let current = value;
|
|
3280
|
-
while (
|
|
3667
|
+
while (TS.isAsExpression(current) || TS.isParenthesizedExpression(current) || TS.isSatisfiesExpression(current)) {
|
|
3281
3668
|
current = current.expression;
|
|
3282
3669
|
}
|
|
3283
3670
|
return current;
|
|
@@ -3287,19 +3674,19 @@ function stringProp(obj, field) {
|
|
|
3287
3674
|
if (!prop)
|
|
3288
3675
|
return;
|
|
3289
3676
|
const value = unwrap(prop.initializer);
|
|
3290
|
-
return
|
|
3677
|
+
return TS.isStringLiteralLike(value) ? value.text : undefined;
|
|
3291
3678
|
}
|
|
3292
3679
|
function stringArrayProp(obj, field) {
|
|
3293
3680
|
const prop = findProp(obj, field);
|
|
3294
3681
|
if (!prop)
|
|
3295
3682
|
return;
|
|
3296
3683
|
const array = unwrap(prop.initializer);
|
|
3297
|
-
if (!
|
|
3684
|
+
if (!TS.isArrayLiteralExpression(array))
|
|
3298
3685
|
return;
|
|
3299
3686
|
const values = [];
|
|
3300
3687
|
for (const el of array.elements) {
|
|
3301
3688
|
const value = unwrap(el);
|
|
3302
|
-
if (!
|
|
3689
|
+
if (!TS.isStringLiteralLike(value))
|
|
3303
3690
|
return;
|
|
3304
3691
|
values.push(value.text);
|
|
3305
3692
|
}
|
|
@@ -3310,26 +3697,26 @@ function literalToSchema(node) {
|
|
|
3310
3697
|
}
|
|
3311
3698
|
function foldLiteral(expression) {
|
|
3312
3699
|
const node = unwrap(expression);
|
|
3313
|
-
if (
|
|
3700
|
+
if (TS.isStringLiteralLike(node))
|
|
3314
3701
|
return node.text;
|
|
3315
|
-
if (
|
|
3702
|
+
if (TS.isNumericLiteral(node))
|
|
3316
3703
|
return Number(node.text);
|
|
3317
|
-
if (node.kind ===
|
|
3704
|
+
if (node.kind === TS.SyntaxKind.TrueKeyword)
|
|
3318
3705
|
return true;
|
|
3319
|
-
if (node.kind ===
|
|
3706
|
+
if (node.kind === TS.SyntaxKind.FalseKeyword)
|
|
3320
3707
|
return false;
|
|
3321
|
-
if (node.kind ===
|
|
3708
|
+
if (node.kind === TS.SyntaxKind.NullKeyword)
|
|
3322
3709
|
return null;
|
|
3323
|
-
if (
|
|
3710
|
+
if (TS.isPrefixUnaryExpression(node) && node.operator === TS.SyntaxKind.MinusToken && TS.isNumericLiteral(node.operand)) {
|
|
3324
3711
|
return -Number(node.operand.text);
|
|
3325
3712
|
}
|
|
3326
|
-
if (
|
|
3713
|
+
if (TS.isArrayLiteralExpression(node)) {
|
|
3327
3714
|
return node.elements.map((el) => foldLiteral(el));
|
|
3328
3715
|
}
|
|
3329
|
-
if (
|
|
3716
|
+
if (TS.isObjectLiteralExpression(node)) {
|
|
3330
3717
|
const obj = {};
|
|
3331
3718
|
for (const p of node.properties) {
|
|
3332
|
-
if (!
|
|
3719
|
+
if (!TS.isPropertyAssignment(p)) {
|
|
3333
3720
|
throw new Error("object has a non-literal member (spread, shorthand, method, or getter)");
|
|
3334
3721
|
}
|
|
3335
3722
|
const key = propertyName(p.name);
|
|
@@ -3339,9 +3726,10 @@ function foldLiteral(expression) {
|
|
|
3339
3726
|
}
|
|
3340
3727
|
return obj;
|
|
3341
3728
|
}
|
|
3342
|
-
throw new Error(`not a static literal (${
|
|
3729
|
+
throw new Error(`not a static literal (${TS.SyntaxKind[node.kind]})`);
|
|
3343
3730
|
}
|
|
3344
|
-
function extractDisk(opts) {
|
|
3731
|
+
async function extractDisk(opts) {
|
|
3732
|
+
const TS2 = await loadTypeScript();
|
|
3345
3733
|
const { cwd, files } = opts;
|
|
3346
3734
|
const diskFs = {
|
|
3347
3735
|
readFile: () => {
|
|
@@ -3352,83 +3740,26 @@ function extractDisk(opts) {
|
|
|
3352
3740
|
currentDirectory: cwd
|
|
3353
3741
|
};
|
|
3354
3742
|
const rootNames = files.map((f) => resolve2(cwd, f));
|
|
3355
|
-
const
|
|
3356
|
-
const
|
|
3743
|
+
const options = readCompilerOptions(TS2, cwd);
|
|
3744
|
+
const { program: program2, checker, host } = createProgram(diskFs, rootNames, options);
|
|
3745
|
+
const useCase = TS2.sys.useCaseSensitiveFileNames;
|
|
3357
3746
|
const canonical = (p) => {
|
|
3358
3747
|
const s = p.replace(/\\/g, "/");
|
|
3359
3748
|
return useCase ? s : s.toLowerCase();
|
|
3360
3749
|
};
|
|
3361
3750
|
const byPath = new Map(program2.getSourceFiles().map((sf) => [canonical(sf.fileName), sf]));
|
|
3362
|
-
return extractFromFiles(files.map((file) => ({ functionPath: file, sourceFile: byPath.get(canonical(resolve2(cwd, file))) })), checker, opts.limits);
|
|
3751
|
+
return extractFromFiles(files.map((file) => ({ functionPath: file, sourceFile: byPath.get(canonical(resolve2(cwd, file))) })), checker, opts.limits, opts.exportName, sdkExports(program2, host, options), opts.derive);
|
|
3363
3752
|
}
|
|
3364
|
-
function readCompilerOptions(cwd) {
|
|
3365
|
-
const configPath =
|
|
3753
|
+
function readCompilerOptions(TS2, cwd) {
|
|
3754
|
+
const configPath = TS2.findConfigFile(cwd, TS2.sys.fileExists, "tsconfig.json");
|
|
3366
3755
|
if (!configPath)
|
|
3367
|
-
return
|
|
3368
|
-
const read =
|
|
3756
|
+
return consumerCompilerOptions();
|
|
3757
|
+
const read = TS2.readConfigFile(configPath, TS2.sys.readFile);
|
|
3369
3758
|
if (read.error || !read.config)
|
|
3370
|
-
return
|
|
3371
|
-
const parsed =
|
|
3759
|
+
return consumerCompilerOptions();
|
|
3760
|
+
const parsed = TS2.parseJsonConfigFileContent(read.config, TS2.sys, dirname(configPath));
|
|
3372
3761
|
return { ...parsed.options, noEmit: true, allowJs: true };
|
|
3373
3762
|
}
|
|
3374
|
-
function extractProject(functionsMap, cwd) {
|
|
3375
|
-
const files = [...new Set(Object.values(functionsMap).map((v) => v.split(":")[0]))];
|
|
3376
|
-
return extractDisk({
|
|
3377
|
-
cwd,
|
|
3378
|
-
files,
|
|
3379
|
-
limits: { requireFunctionPerFile: true }
|
|
3380
|
-
});
|
|
3381
|
-
}
|
|
3382
|
-
function toDerivedContracts(functions) {
|
|
3383
|
-
const derived = {};
|
|
3384
|
-
for (const fn of functions) {
|
|
3385
|
-
if (fn.functionPath && (fn.input !== undefined || fn.output !== undefined)) {
|
|
3386
|
-
derived[fn.functionPath] = fn;
|
|
3387
|
-
}
|
|
3388
|
-
}
|
|
3389
|
-
return derived;
|
|
3390
|
-
}
|
|
3391
|
-
function deriveRunContract(relFile, cwd) {
|
|
3392
|
-
const { functions } = extractDisk({ cwd, files: [relFile] });
|
|
3393
|
-
const fn = functions.find((f) => f.input !== undefined || f.output !== undefined);
|
|
3394
|
-
if (!fn)
|
|
3395
|
-
return null;
|
|
3396
|
-
const derived = {};
|
|
3397
|
-
if (fn.input !== undefined)
|
|
3398
|
-
derived.input = fn.input;
|
|
3399
|
-
if (fn.output !== undefined)
|
|
3400
|
-
derived.output = fn.output;
|
|
3401
|
-
return derived;
|
|
3402
|
-
}
|
|
3403
|
-
function readBakedContract(relFile, cwd) {
|
|
3404
|
-
const doc = readJsonIfExists(join6(cwd, "entry-points.json"));
|
|
3405
|
-
const entryPoints = doc?.entryPoints;
|
|
3406
|
-
if (!Array.isArray(entryPoints))
|
|
3407
|
-
return null;
|
|
3408
|
-
const target = stripContentPrefix(relFile);
|
|
3409
|
-
const ep = entryPoints.find((e) => e?.type === "function" && typeof e.filePath === "string" && stripContentPrefix(e.filePath) === target);
|
|
3410
|
-
if (!ep)
|
|
3411
|
-
return null;
|
|
3412
|
-
const derived = {};
|
|
3413
|
-
if (ep.input !== undefined)
|
|
3414
|
-
derived.input = ep.input;
|
|
3415
|
-
if (ep.output !== undefined)
|
|
3416
|
-
derived.output = ep.output;
|
|
3417
|
-
return derived.input !== undefined || derived.output !== undefined ? derived : null;
|
|
3418
|
-
}
|
|
3419
|
-
function stripContentPrefix(p) {
|
|
3420
|
-
const s = p.replace(/\\/g, "/");
|
|
3421
|
-
return s.startsWith("content/") ? s.slice("content/".length) : s;
|
|
3422
|
-
}
|
|
3423
|
-
function readJsonIfExists(path3) {
|
|
3424
|
-
if (!existsSync4(path3))
|
|
3425
|
-
return null;
|
|
3426
|
-
try {
|
|
3427
|
-
return JSON.parse(readFileSync3(path3, "utf-8"));
|
|
3428
|
-
} catch {
|
|
3429
|
-
return null;
|
|
3430
|
-
}
|
|
3431
|
-
}
|
|
3432
3763
|
var SDK_VERSION2 = "0.6.2";
|
|
3433
3764
|
var SDK_RANGE2 = `^${SDK_VERSION2}`;
|
|
3434
3765
|
var SDK_PACKAGE_NAME2 = "@uipath/coded-functions-js-sdk";
|
|
@@ -3568,19 +3899,11 @@ var SAMPLE_LOCK_PACKAGES2 = {
|
|
|
3568
3899
|
engines: { node: ">=14.17" }
|
|
3569
3900
|
}
|
|
3570
3901
|
};
|
|
3571
|
-
var CONSUMER_COMPILER_OPTIONS2 = {
|
|
3572
|
-
target: ts3.ScriptTarget.ES2020,
|
|
3573
|
-
module: ts3.ModuleKind.ESNext,
|
|
3574
|
-
moduleResolution: ts3.ModuleResolutionKind.Bundler,
|
|
3575
|
-
allowImportingTsExtensions: true,
|
|
3576
|
-
allowJs: true,
|
|
3577
|
-
strict: true,
|
|
3578
|
-
skipLibCheck: true,
|
|
3579
|
-
noEmit: true
|
|
3580
|
-
};
|
|
3581
3902
|
var DIAGNOSTIC_CODES2 = {
|
|
3582
3903
|
UNSUPPORTED_VALIDATOR: "unsupported-validator",
|
|
3583
3904
|
UNSUPPORTED_TYPE: "unsupported-type",
|
|
3905
|
+
UNSUPPORTED_DATE: "unsupported-date",
|
|
3906
|
+
UNSUPPORTED_FORMAT: "unsupported-format",
|
|
3584
3907
|
NON_STATIC_LITERAL: "non-static-literal",
|
|
3585
3908
|
UNREADABLE_PROPERTY: "unreadable-property",
|
|
3586
3909
|
MISSING_TYPE_ARGUMENT: "missing-type-argument",
|
|
@@ -3588,7 +3911,9 @@ var DIAGNOSTIC_CODES2 = {
|
|
|
3588
3911
|
MULTIPLE_FUNCTIONS_PER_FILE: "multiple-functions-per-file",
|
|
3589
3912
|
DEPRECATED_MARKER: "deprecated-marker",
|
|
3590
3913
|
NO_FUNCTION_DEFINITION: "no-function-definition",
|
|
3591
|
-
UNRESOLVED_SOURCE_FILE: "unresolved-source-file"
|
|
3914
|
+
UNRESOLVED_SOURCE_FILE: "unresolved-source-file",
|
|
3915
|
+
UNLINKED_DEFINITION: "unlinked-definition",
|
|
3916
|
+
UNLINKED_CONTRACT_TYPE: "unlinked-contract-type"
|
|
3592
3917
|
};
|
|
3593
3918
|
var CONTRACT_FIELDS2 = new Set(["name", "method", "path", "description", "input", "output"]);
|
|
3594
3919
|
var METADATA_FIELDS2 = new Set(["name", "method", "path", "description"]);
|
|
@@ -3706,6 +4031,9 @@ function transformAttachments(schema) {
|
|
|
3706
4031
|
function newId() {
|
|
3707
4032
|
return globalThis.crypto.randomUUID();
|
|
3708
4033
|
}
|
|
4034
|
+
function toDocumentSchema(schema) {
|
|
4035
|
+
return transformAttachments(schema ?? { type: "object" });
|
|
4036
|
+
}
|
|
3709
4037
|
function buildEntryPointsDoc(functions, existing, filePathPrefix = "content/") {
|
|
3710
4038
|
const functionIds = new Map;
|
|
3711
4039
|
const transactionRoots = new Set;
|
|
@@ -3726,8 +4054,8 @@ function buildEntryPointsDoc(functions, existing, filePathPrefix = "content/") {
|
|
|
3726
4054
|
filePath,
|
|
3727
4055
|
uniqueId: functionIds.get(filePath) ?? newId(),
|
|
3728
4056
|
type: "function",
|
|
3729
|
-
input:
|
|
3730
|
-
output:
|
|
4057
|
+
input: toDocumentSchema(fn.input),
|
|
4058
|
+
output: toDocumentSchema(fn.output),
|
|
3731
4059
|
...transactionRoots.has(filePath) ? { isTransactionRoot: true } : {}
|
|
3732
4060
|
};
|
|
3733
4061
|
});
|
|
@@ -3786,15 +4114,28 @@ function buildBindingsDoc(functions, entryPointIdByPath, existingBindings, fileP
|
|
|
3786
4114
|
}
|
|
3787
4115
|
var BLOCKING_CODES = new Set([
|
|
3788
4116
|
DIAGNOSTIC_CODES2.NO_FUNCTION_DEFINITION,
|
|
3789
|
-
DIAGNOSTIC_CODES2.UNRESOLVED_SOURCE_FILE
|
|
4117
|
+
DIAGNOSTIC_CODES2.UNRESOLVED_SOURCE_FILE,
|
|
4118
|
+
DIAGNOSTIC_CODES2.UNSUPPORTED_TYPE,
|
|
4119
|
+
DIAGNOSTIC_CODES2.UNSUPPORTED_DATE,
|
|
4120
|
+
DIAGNOSTIC_CODES2.UNSUPPORTED_FORMAT,
|
|
4121
|
+
DIAGNOSTIC_CODES2.MISSING_TYPE_ARGUMENT,
|
|
4122
|
+
DIAGNOSTIC_CODES2.UNLINKED_CONTRACT_TYPE
|
|
4123
|
+
]);
|
|
4124
|
+
var DESIGN_TIME_ONLY_CODES = new Set([DIAGNOSTIC_CODES2.UNLINKED_CONTRACT_TYPE]);
|
|
4125
|
+
var SILENT_CODES = new Set([
|
|
4126
|
+
DIAGNOSTIC_CODES2.UNSUPPORTED_VALIDATOR,
|
|
4127
|
+
DIAGNOSTIC_CODES2.UNLINKED_DEFINITION
|
|
3790
4128
|
]);
|
|
3791
|
-
var SILENT_CODES = new Set([DIAGNOSTIC_CODES2.UNSUPPORTED_VALIDATOR]);
|
|
3792
4129
|
function isSilentSchemaSignal(d) {
|
|
3793
4130
|
return d.code === DIAGNOSTIC_CODES2.UNREADABLE_PROPERTY && d.field !== undefined;
|
|
3794
4131
|
}
|
|
3795
4132
|
var REMEDIATION = {
|
|
3796
|
-
[DIAGNOSTIC_CODES2.NO_FUNCTION_DEFINITION]: (d) => `Every file in functions/ is served as a function. If this file is a helper, move it out
|
|
3797
|
-
[DIAGNOSTIC_CODES2.UNRESOLVED_SOURCE_FILE]: () => `Check the path exists and that tsconfig.json does not exclude it
|
|
4133
|
+
[DIAGNOSTIC_CODES2.NO_FUNCTION_DEFINITION]: (d) => `Every file in functions/ is served as a function. If this file is a helper, move it out of functions/ or rename it to ${underscored(d.file)} so discovery skips it.`,
|
|
4134
|
+
[DIAGNOSTIC_CODES2.UNRESOLVED_SOURCE_FILE]: () => `Check the path exists and that tsconfig.json does not exclude it.`,
|
|
4135
|
+
[DIAGNOSTIC_CODES2.UNSUPPORTED_TYPE]: () => `Declare this contract as a JSON Schema literal instead, or keep it on a validator like zod, which the CLI reads by executing the module.`,
|
|
4136
|
+
[DIAGNOSTIC_CODES2.UNSUPPORTED_DATE]: (d) => `Declare it as a \`string\` tagged \`/** @format date-time */\`, and ` + (d.field === "output" ? `return \`date.toISOString()\` from the handler.` : `call \`new Date(value)\` in the handler.`),
|
|
4137
|
+
[DIAGNOSTIC_CODES2.UNSUPPORTED_FORMAT]: () => `Tag a \`string\` property with one of the supported formats.`,
|
|
4138
|
+
[DIAGNOSTIC_CODES2.UNLINKED_CONTRACT_TYPE]: () => `Put it in the served call, \`export default defineFunction({ input: defineSchema<T>(), ... })\`, or declare the contract as a JSON Schema literal or a validator.`
|
|
3798
4139
|
};
|
|
3799
4140
|
function reportDiagnostics(diagnostics) {
|
|
3800
4141
|
const blocking = diagnostics.filter((d) => BLOCKING_CODES.has(d.code));
|
|
@@ -3813,6 +4154,11 @@ function reportDiagnosticsOrExit(diagnostics) {
|
|
|
3813
4154
|
${blocking} error(s) in the project's function files — nothing was written. ` + `Fix them and re-run.`);
|
|
3814
4155
|
process.exit(1);
|
|
3815
4156
|
}
|
|
4157
|
+
function describeBlockingDiagnostics(diagnostics) {
|
|
4158
|
+
const blocking = diagnostics.filter((d) => BLOCKING_CODES.has(d.code) && !DESIGN_TIME_ONLY_CODES.has(d.code));
|
|
4159
|
+
return blocking.length === 0 ? null : blocking.map(format).join(`
|
|
4160
|
+
`);
|
|
4161
|
+
}
|
|
3816
4162
|
function format(d) {
|
|
3817
4163
|
const where = [d.functionName, d.field].filter(Boolean).join(".");
|
|
3818
4164
|
const location = [d.file, where ? `(${where})` : ""].filter(Boolean).join(" ");
|
|
@@ -3826,24 +4172,207 @@ function underscored(file) {
|
|
|
3826
4172
|
const renamed = `_${basename2(file)}`;
|
|
3827
4173
|
return dir === "." ? renamed : `${dir}/${renamed}`;
|
|
3828
4174
|
}
|
|
3829
|
-
|
|
4175
|
+
var ALLOW_DATE_ENV = "UIPATH_FUNCTIONS_ALLOW_DATE";
|
|
4176
|
+
var DERIVE_ENV = "UIPATH_FUNCTIONS_DERIVE_CONTRACTS";
|
|
4177
|
+
var allowDateAnnounced = false;
|
|
4178
|
+
var deriveAnnounced = false;
|
|
4179
|
+
function executionDeriveOptions() {
|
|
4180
|
+
const allowDate = /^(1|true)$/i.test(process.env[ALLOW_DATE_ENV] ?? "");
|
|
4181
|
+
if (allowDate && !allowDateAnnounced) {
|
|
4182
|
+
allowDateAnnounced = true;
|
|
4183
|
+
console.warn(`${ALLOW_DATE_ENV} is set: a Date in a defineSchema<T>() contract derives as a date-time string, and the handler receives that string. A @format that would block is skipped.`);
|
|
4184
|
+
}
|
|
4185
|
+
return { allowDate };
|
|
4186
|
+
}
|
|
4187
|
+
function extractProject(functionsMap, cwd, derive) {
|
|
4188
|
+
const files = [...new Set(Object.values(functionsMap).map((v) => v.split(":")[0]))];
|
|
4189
|
+
return extractDisk({
|
|
4190
|
+
cwd,
|
|
4191
|
+
files,
|
|
4192
|
+
limits: { requireFunctionPerFile: true },
|
|
4193
|
+
derive
|
|
4194
|
+
});
|
|
4195
|
+
}
|
|
4196
|
+
function contractsFromExtraction(extraction) {
|
|
4197
|
+
const legacyFiles = new Set(extraction.diagnostics.filter((d) => d.code === DIAGNOSTIC_CODES2.UNLINKED_CONTRACT_TYPE).map((d) => d.file));
|
|
4198
|
+
const linked = new Set(extraction.functions.map((f) => f.functionPath));
|
|
4199
|
+
const legacy = (extraction.allCalls ?? []).filter((f) => legacyFiles.has(f.functionPath) && !linked.has(f.functionPath));
|
|
4200
|
+
const contracts = {};
|
|
4201
|
+
for (const fn of [...legacy, ...extraction.functions]) {
|
|
4202
|
+
if (fn.functionPath && (fn.input !== undefined || fn.output !== undefined)) {
|
|
4203
|
+
contracts[fn.functionPath] = { ...fn, ...toDocumentForm(fn) };
|
|
4204
|
+
}
|
|
4205
|
+
}
|
|
4206
|
+
return contracts;
|
|
4207
|
+
}
|
|
4208
|
+
async function extractContract(relFile, cwd, exportName = "default", derive, gate = false) {
|
|
4209
|
+
const { functions, diagnostics } = await extractDisk({ cwd, files: [relFile], exportName, derive });
|
|
4210
|
+
if (gate)
|
|
4211
|
+
reportDiagnosticsOrExit(diagnostics);
|
|
4212
|
+
else if (describeBlockingDiagnostics(diagnostics))
|
|
4213
|
+
console.error(describeBlockingDiagnostics(diagnostics));
|
|
4214
|
+
const fn = functions[0];
|
|
4215
|
+
if (!fn || fn.input === undefined && fn.output === undefined)
|
|
4216
|
+
return null;
|
|
4217
|
+
return toDocumentForm(fn);
|
|
4218
|
+
}
|
|
4219
|
+
function toDocumentForm(fn) {
|
|
4220
|
+
const out = {};
|
|
4221
|
+
if (fn.input !== undefined)
|
|
4222
|
+
out.input = toDocumentSchema(fn.input);
|
|
4223
|
+
if (fn.output !== undefined)
|
|
4224
|
+
out.output = toDocumentSchema(fn.output);
|
|
4225
|
+
return out;
|
|
4226
|
+
}
|
|
4227
|
+
function readDocument(cwd) {
|
|
4228
|
+
const doc = readJsonIfExists(join6(cwd, "entry-points.json"));
|
|
4229
|
+
if (!Array.isArray(doc?.entryPoints))
|
|
4230
|
+
return null;
|
|
4231
|
+
const byPath = new Map;
|
|
4232
|
+
for (const ep of doc.entryPoints) {
|
|
4233
|
+
if (ep?.type !== "function" || typeof ep.filePath !== "string")
|
|
4234
|
+
continue;
|
|
4235
|
+
if (ep.input === undefined || ep.output === undefined)
|
|
4236
|
+
continue;
|
|
4237
|
+
const entry = {};
|
|
4238
|
+
if (!isUndeclared(ep.input))
|
|
4239
|
+
entry.input = ep.input;
|
|
4240
|
+
if (!isUndeclared(ep.output))
|
|
4241
|
+
entry.output = ep.output;
|
|
4242
|
+
byPath.set(stripContentPrefix(ep.filePath), entry);
|
|
4243
|
+
}
|
|
4244
|
+
return byPath;
|
|
4245
|
+
}
|
|
4246
|
+
function contractFromDocument(relFile, cwd) {
|
|
4247
|
+
const entry = readDocument(cwd)?.get(stripContentPrefix(relFile));
|
|
4248
|
+
return entry && (entry.input !== undefined || entry.output !== undefined) ? entry : null;
|
|
4249
|
+
}
|
|
4250
|
+
async function resolveContracts(functionsMap, cwd, production, extract) {
|
|
4251
|
+
if (production && !derivesFromSource()) {
|
|
4252
|
+
const fromDocument = contractsFromDocument(functionsMap, cwd);
|
|
4253
|
+
if (fromDocument)
|
|
4254
|
+
return fromDocument;
|
|
4255
|
+
throw new IncompleteDocumentError(describeGap(functionsMap, cwd));
|
|
4256
|
+
}
|
|
4257
|
+
return contractsFromExtraction(await extract());
|
|
4258
|
+
}
|
|
4259
|
+
|
|
4260
|
+
class IncompleteDocumentError extends Error {
|
|
4261
|
+
}
|
|
4262
|
+
function derivesFromSource() {
|
|
4263
|
+
const derive = /^(1|true)$/i.test(process.env[DERIVE_ENV] ?? "");
|
|
4264
|
+
if (derive && !deriveAnnounced) {
|
|
4265
|
+
deriveAnnounced = true;
|
|
4266
|
+
console.warn(`${DERIVE_ENV} is set: contracts come from source instead of entry-points.json.`);
|
|
4267
|
+
}
|
|
4268
|
+
return derive;
|
|
4269
|
+
}
|
|
4270
|
+
function describeGap(functionsMap, cwd) {
|
|
4271
|
+
const byPath = readDocument(cwd);
|
|
4272
|
+
if (!byPath)
|
|
4273
|
+
return "entry-points.json is absent or unreadable; pack the project again.";
|
|
4274
|
+
const missing = declaredFiles(functionsMap).filter((file) => !byPath.has(stripContentPrefix(file)));
|
|
4275
|
+
return `entry-points.json has no entry for ${missing.join(", ")}; pack the project again.`;
|
|
4276
|
+
}
|
|
4277
|
+
function declaredFiles(functionsMap) {
|
|
4278
|
+
return [...new Set(Object.values(functionsMap).map((v) => v.split(":")[0]))];
|
|
4279
|
+
}
|
|
4280
|
+
function contractsFromDocument(functionsMap, cwd) {
|
|
4281
|
+
const byPath = readDocument(cwd);
|
|
4282
|
+
if (!byPath)
|
|
4283
|
+
return null;
|
|
4284
|
+
const contracts = {};
|
|
4285
|
+
for (const file of declaredFiles(functionsMap)) {
|
|
4286
|
+
const entry = byPath.get(stripContentPrefix(file));
|
|
4287
|
+
if (!entry)
|
|
4288
|
+
return null;
|
|
4289
|
+
if (entry.input !== undefined || entry.output !== undefined)
|
|
4290
|
+
contracts[file] = entry;
|
|
4291
|
+
}
|
|
4292
|
+
return contracts;
|
|
4293
|
+
}
|
|
4294
|
+
function isUndeclared(schema) {
|
|
4295
|
+
if (typeof schema !== "object" || schema === null || Array.isArray(schema))
|
|
4296
|
+
return true;
|
|
4297
|
+
const keys = Object.keys(schema);
|
|
4298
|
+
return keys.length === 1 && keys[0] === "type" && schema.type === "object";
|
|
4299
|
+
}
|
|
4300
|
+
function stripContentPrefix(p) {
|
|
4301
|
+
const s = p.replace(/\\/g, "/");
|
|
4302
|
+
return s.startsWith("content/") ? s.slice("content/".length) : s;
|
|
4303
|
+
}
|
|
4304
|
+
function readJsonIfExists(path3) {
|
|
4305
|
+
if (!existsSync4(path3))
|
|
4306
|
+
return null;
|
|
4307
|
+
try {
|
|
4308
|
+
return JSON.parse(readFileSync3(path3, "utf-8"));
|
|
4309
|
+
} catch {
|
|
4310
|
+
return null;
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4313
|
+
var INVALID_FUNCTION_DEFINITION = "JsCodedFunction.InvalidFunctionDefinition";
|
|
4314
|
+
var DEPLOYMENT = "Deployment";
|
|
4315
|
+
async function reportStartupFailure(title, detail) {
|
|
4316
|
+
const ipcEndpoint = process.env.JS_FUNCTION_API_IPC_ENDPOINT;
|
|
4317
|
+
if (!ipcEndpoint)
|
|
4318
|
+
return;
|
|
4319
|
+
|
|
4320
|
+
class IHttpFunctionServerApi {
|
|
4321
|
+
SignalStartupFailed(_error) {
|
|
4322
|
+
throw undefined;
|
|
4323
|
+
}
|
|
4324
|
+
}
|
|
4325
|
+
const error = {
|
|
4326
|
+
code: INVALID_FUNCTION_DEFINITION,
|
|
4327
|
+
title,
|
|
4328
|
+
detail,
|
|
4329
|
+
category: DEPLOYMENT
|
|
4330
|
+
};
|
|
4331
|
+
try {
|
|
4332
|
+
const { ipc } = await import("./index-q8r0mcyb.js").then((m)=>__toESM(m.default,1));
|
|
4333
|
+
const proxy = ipc.proxy.withAddress(ipc.namedPipe(ipcEndpoint)).withService(IHttpFunctionServerApi);
|
|
4334
|
+
await proxy.SignalStartupFailed(error);
|
|
4335
|
+
await ipc.disposeChannel(ipc.namedPipe(ipcEndpoint));
|
|
4336
|
+
} catch (err) {
|
|
4337
|
+
console.error("Failed to report startup failure to handler:", err);
|
|
4338
|
+
}
|
|
4339
|
+
}
|
|
4340
|
+
async function failStartup(detail) {
|
|
4341
|
+
if (detail === null)
|
|
4342
|
+
return;
|
|
4343
|
+
console.error(detail);
|
|
4344
|
+
await reportStartupFailure("The function package could not be loaded", detail);
|
|
4345
|
+
process.exit(1);
|
|
4346
|
+
}
|
|
4347
|
+
function installServerRunner(cwd, { production, serverRunnerTemplatePath = "", packageManager, hardLink = false }) {
|
|
3830
4348
|
const serverRunnerDir = join7(cwd, SERVER_RUNNER_DIR);
|
|
3831
4349
|
mkdirSync4(serverRunnerDir, { recursive: true });
|
|
3832
4350
|
if (serverRunnerTemplatePath !== "" && existsSync5(serverRunnerTemplatePath)) {
|
|
3833
4351
|
console.log("Copying server-runner ...");
|
|
3834
4352
|
for (const entry of readdirSync(serverRunnerTemplatePath)) {
|
|
3835
|
-
cpSync(join7(serverRunnerTemplatePath, entry), join7(serverRunnerDir, entry), { recursive: true });
|
|
4353
|
+
cpSync(join7(serverRunnerTemplatePath, entry), join7(serverRunnerDir, entry), { recursive: true, filter: hardLink ? copyUnlessHardLinked : undefined });
|
|
3836
4354
|
}
|
|
3837
4355
|
console.log("server-runner copied in " + serverRunnerDir + ".");
|
|
3838
4356
|
return;
|
|
3839
4357
|
}
|
|
3840
|
-
|
|
3841
|
-
pkgJson.dependencies = buildRunnerDependencies(cwd);
|
|
3842
|
-
writeFileSync6(join7(serverRunnerDir, "package.json"), JSON.stringify(pkgJson, null, 2), "utf-8");
|
|
4358
|
+
writeFileSync5(join7(serverRunnerDir, "package.json"), JSON.stringify(runnerManifest(), null, 2), "utf-8");
|
|
3843
4359
|
console.log("Installing runtime dependencies ...");
|
|
3844
|
-
resolvePackageManager(cwd, packageManager)
|
|
4360
|
+
const manager = production ? resolvePackageManager(cwd, packageManager) : resolveDesignTimePackageManager(cwd);
|
|
4361
|
+
manager.runInstall(serverRunnerDir);
|
|
3845
4362
|
console.log("Runtime dependencies installed.");
|
|
3846
4363
|
}
|
|
4364
|
+
function copyUnlessHardLinked(from, to) {
|
|
4365
|
+
try {
|
|
4366
|
+
linkSync(from, to);
|
|
4367
|
+
return false;
|
|
4368
|
+
} catch {
|
|
4369
|
+
return !isSameFile(from, to);
|
|
4370
|
+
}
|
|
4371
|
+
}
|
|
4372
|
+
function isSameFile(a, b) {
|
|
4373
|
+
const [first, second] = [lstatSync(a, { bigint: true }), lstatSync(b, { bigint: true, throwIfNoEntry: false })];
|
|
4374
|
+
return first.ino === second?.ino && first.dev === second?.dev;
|
|
4375
|
+
}
|
|
3847
4376
|
function declaresProductionDependency(cwd, packageName) {
|
|
3848
4377
|
let parsed;
|
|
3849
4378
|
try {
|
|
@@ -3863,7 +4392,7 @@ function declaresProductionDependency(cwd, packageName) {
|
|
|
3863
4392
|
function installProjectProductionDependencies(cwd, manager = resolvePackageManager(cwd)) {
|
|
3864
4393
|
const serverRunnerDir = join7(cwd, SERVER_RUNNER_DIR);
|
|
3865
4394
|
console.log("Installing dependencies in package working folder.");
|
|
3866
|
-
manager.runInstall(cwd, { production: true
|
|
4395
|
+
manager.runInstall(cwd, { production: true });
|
|
3867
4396
|
console.log("Preparing node_modules in package working folder.");
|
|
3868
4397
|
const packagesToCopy = ["@uipath/coded-functions-js-sdk"];
|
|
3869
4398
|
for (const packageName of packagesToCopy) {
|
|
@@ -3877,27 +4406,24 @@ function installProjectProductionDependencies(cwd, manager = resolvePackageManag
|
|
|
3877
4406
|
}
|
|
3878
4407
|
console.log("Package working folder dependencies installed.");
|
|
3879
4408
|
}
|
|
3880
|
-
function provisionPackage(cwd, serverRunnerTemplatePath = "", packageManager) {
|
|
3881
|
-
installServerRunner(cwd, serverRunnerTemplatePath, packageManager);
|
|
4409
|
+
function provisionPackage(cwd, serverRunnerTemplatePath = "", packageManager, hardLink = false) {
|
|
4410
|
+
installServerRunner(cwd, { production: true, serverRunnerTemplatePath, packageManager, hardLink });
|
|
3882
4411
|
if (!existsSync5(join7(cwd, "node_modules"))) {
|
|
3883
4412
|
installProjectProductionDependencies(cwd, resolvePackageManager(cwd, packageManager));
|
|
3884
4413
|
}
|
|
3885
4414
|
}
|
|
3886
|
-
function
|
|
3887
|
-
let runtimeVersion = RUNTIME_VERSION;
|
|
3888
|
-
let tsxVersion = TSX_VERSION;
|
|
3889
|
-
try {
|
|
3890
|
-
const pkgJson = JSON.parse(readFileSync4(join7(cwd, "package.json"), "utf-8"));
|
|
3891
|
-
const allDeps = { ...pkgJson.dependencies ?? {}, ...pkgJson.devDependencies ?? {} };
|
|
3892
|
-
runtimeVersion = allDeps["@uipath/coded-functions-js-runtime"] ?? RUNTIME_VERSION;
|
|
3893
|
-
tsxVersion = allDeps["tsx"] ?? TSX_VERSION;
|
|
3894
|
-
} catch {}
|
|
4415
|
+
function runnerManifest() {
|
|
3895
4416
|
return {
|
|
3896
|
-
"
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
4417
|
+
name: "runner",
|
|
4418
|
+
private: true,
|
|
4419
|
+
type: "module",
|
|
4420
|
+
dependencies: {
|
|
4421
|
+
"@uipath/coded-functions-js-runtime": RUNTIME_VERSION,
|
|
4422
|
+
"@uipath/coreipc": COREIPC_VERSION,
|
|
4423
|
+
tsx: TSX_VERSION,
|
|
4424
|
+
"@microsoft/signalr": SIGNALR_VERSION,
|
|
4425
|
+
"@jridgewell/trace-mapping": TRACE_MAPPING_VERSION
|
|
4426
|
+
}
|
|
3901
4427
|
};
|
|
3902
4428
|
}
|
|
3903
4429
|
function resolveTsx(cwd) {
|
|
@@ -3943,11 +4469,13 @@ function assert(check, cwd) {
|
|
|
3943
4469
|
}
|
|
3944
4470
|
}
|
|
3945
4471
|
function assertDependenciesInstalled(cwd) {
|
|
4472
|
+
assert(checkDesignTimeManager(cwd), cwd);
|
|
3946
4473
|
assert(checkDependenciesInstalled(cwd), cwd);
|
|
3947
4474
|
}
|
|
3948
4475
|
function assertReadyToPackage(cwd) {
|
|
3949
|
-
|
|
4476
|
+
assertDependenciesInstalled(cwd);
|
|
3950
4477
|
assert(checkLockCurrent(cwd), cwd);
|
|
4478
|
+
assert(checkNoGitDependencies(cwd), cwd);
|
|
3951
4479
|
}
|
|
3952
4480
|
function freePort(port) {
|
|
3953
4481
|
try {
|
|
@@ -3969,7 +4497,28 @@ function freePort(port) {
|
|
|
3969
4497
|
}
|
|
3970
4498
|
} catch {}
|
|
3971
4499
|
}
|
|
4500
|
+
var SIGNAL_READY_IPC = ` const ipcEndpoint = (typeof Deno !== "undefined" ? Deno.env.get("JS_FUNCTION_API_IPC_ENDPOINT") : process.env.JS_FUNCTION_API_IPC_ENDPOINT);
|
|
4501
|
+
if (ipcEndpoint) {
|
|
4502
|
+
console.log("Signaling ready to handler via CoreIPC on endpoint: " + ipcEndpoint);
|
|
4503
|
+
try {
|
|
4504
|
+
const { ipc } = await import("@uipath/coreipc");
|
|
4505
|
+
class IHttpFunctionServerApi {
|
|
4506
|
+
SignalReady() { throw void 0; }
|
|
4507
|
+
}
|
|
4508
|
+
const proxy = ipc.proxy
|
|
4509
|
+
.withAddress(ipc.namedPipe(ipcEndpoint))
|
|
4510
|
+
.withService(IHttpFunctionServerApi);
|
|
4511
|
+
await proxy.SignalReady();
|
|
4512
|
+
await ipc.disposeChannel(ipc.namedPipe(ipcEndpoint));
|
|
4513
|
+
console.log("Sent ready signal to handler via CoreIPC");
|
|
4514
|
+
} catch (e) {
|
|
4515
|
+
console.error("Failed to send ready signal via CoreIPC:", e);
|
|
4516
|
+
}
|
|
4517
|
+
return;
|
|
4518
|
+
}
|
|
4519
|
+
`;
|
|
3972
4520
|
var SIGNAL_READY_NODE = `async function signalReady() {
|
|
4521
|
+
${SIGNAL_READY_IPC}
|
|
3973
4522
|
const socketPath = (typeof Deno !== "undefined" ? Deno.env.get("JS_FUNCTION_API_SOCKET") : process.env.JS_FUNCTION_API_SOCKET);
|
|
3974
4523
|
if (!socketPath) {
|
|
3975
4524
|
return;
|
|
@@ -3999,26 +4548,7 @@ var SIGNAL_READY_NODE = `async function signalReady() {
|
|
|
3999
4548
|
});
|
|
4000
4549
|
}`;
|
|
4001
4550
|
var SIGNAL_READY_DENO = `async function signalReady() {
|
|
4002
|
-
|
|
4003
|
-
if (ipcEndpoint) {
|
|
4004
|
-
console.log("Signaling ready to handler via CoreIPC on endpoint: " + ipcEndpoint);
|
|
4005
|
-
try {
|
|
4006
|
-
const { ipc } = await import("@uipath/coreipc");
|
|
4007
|
-
class IJsFunctionApi {
|
|
4008
|
-
SignalReady() { throw void 0; }
|
|
4009
|
-
}
|
|
4010
|
-
const proxy = ipc.proxy
|
|
4011
|
-
.withAddress(ipc.namedPipe(ipcEndpoint))
|
|
4012
|
-
.withService(IJsFunctionApi);
|
|
4013
|
-
await proxy.SignalReady();
|
|
4014
|
-
await ipc.disposeChannel(ipc.namedPipe(ipcEndpoint));
|
|
4015
|
-
console.log("Sent ready signal to handler via CoreIPC");
|
|
4016
|
-
} catch (e) {
|
|
4017
|
-
console.error("Failed to send ready signal via CoreIPC:", e);
|
|
4018
|
-
}
|
|
4019
|
-
return;
|
|
4020
|
-
}
|
|
4021
|
-
|
|
4551
|
+
${SIGNAL_READY_IPC}
|
|
4022
4552
|
const socketPath = (typeof Deno !== "undefined" ? Deno.env.get("JS_FUNCTION_API_SOCKET") : process.env.JS_FUNCTION_API_SOCKET);
|
|
4023
4553
|
if (!socketPath) {
|
|
4024
4554
|
return;
|
|
@@ -4061,7 +4591,7 @@ function syncFunctionsMap(cwd) {
|
|
|
4061
4591
|
if (mapsEqual(existing, discovered))
|
|
4062
4592
|
return false;
|
|
4063
4593
|
uipathJson.functions = Object.fromEntries(Object.keys(discovered).sort().map((k) => [k, discovered[k]]));
|
|
4064
|
-
|
|
4594
|
+
writeFileSync6(uipathJsonPath, JSON.stringify(uipathJson, null, 2) + `
|
|
4065
4595
|
`, "utf-8");
|
|
4066
4596
|
return true;
|
|
4067
4597
|
}
|
|
@@ -4087,6 +4617,16 @@ function mapsEqual(a, b) {
|
|
|
4087
4617
|
return ak.length === Object.keys(b).length && ak.every((k) => a[k] === b[k]);
|
|
4088
4618
|
}
|
|
4089
4619
|
var DEFAULT_PORT = 7070;
|
|
4620
|
+
var LOAD_AGGREGATOR = (aggregatorFile) => `let app;
|
|
4621
|
+
try {
|
|
4622
|
+
({ default: app } = await import("./${aggregatorFile}"));
|
|
4623
|
+
} catch (err) {
|
|
4624
|
+
try {
|
|
4625
|
+
const runtime = await import("@uipath/coded-functions-js-runtime");
|
|
4626
|
+
await runtime.reportModuleLoadFailure?.(err);
|
|
4627
|
+
} catch {}
|
|
4628
|
+
throw err;
|
|
4629
|
+
}`;
|
|
4090
4630
|
function registerServeCommand(program2) {
|
|
4091
4631
|
program2.command("serve").description("Start local function server with hot reload.").option("--runtime <runtime>", "Runtime: node (default) or deno", "node").option("--port <port>", "Port to listen on", String(DEFAULT_PORT)).option("--production", "Run under production context and skip .uipath/server-runner install if already exists; also skip freePort check.").action(async (opts) => {
|
|
4092
4632
|
const cwd = resolve3(".");
|
|
@@ -4112,20 +4652,29 @@ function registerServeCommand(program2) {
|
|
|
4112
4652
|
process.exit(1);
|
|
4113
4653
|
}
|
|
4114
4654
|
}
|
|
4115
|
-
const
|
|
4116
|
-
|
|
4117
|
-
|
|
4655
|
+
const contracts = await resolveContracts(uipathJson.functions, cwd, opts.production === true, async () => {
|
|
4656
|
+
const extraction = await extractProject(uipathJson.functions, cwd, executionDeriveOptions());
|
|
4657
|
+
if (opts.production !== true) {
|
|
4658
|
+
reportDiagnosticsOrExit(extraction.diagnostics);
|
|
4659
|
+
} else {
|
|
4660
|
+
await failStartup(describeBlockingDiagnostics(extraction.diagnostics));
|
|
4661
|
+
}
|
|
4662
|
+
return extraction;
|
|
4663
|
+
}).catch(async (err) => {
|
|
4664
|
+
if (err instanceof IncompleteDocumentError)
|
|
4665
|
+
await failStartup(err.message);
|
|
4666
|
+
throw err;
|
|
4667
|
+
});
|
|
4118
4668
|
const skipInstall = opts.production === true && existsSync7(join9(cwd, SERVER_RUNNER_DIR));
|
|
4119
4669
|
if (!skipInstall) {
|
|
4120
4670
|
try {
|
|
4121
|
-
installServerRunner(cwd);
|
|
4671
|
+
installServerRunner(cwd, { production: opts.production === true });
|
|
4122
4672
|
} catch (err) {
|
|
4123
4673
|
console.error(err instanceof Error ? err.message : String(err));
|
|
4124
4674
|
process.exit(1);
|
|
4125
4675
|
}
|
|
4126
4676
|
}
|
|
4127
|
-
const
|
|
4128
|
-
const aggregatorPath = generateAggregator(uipathJson.functions, cwd, "serve", derived);
|
|
4677
|
+
const aggregatorPath = generateAggregator(uipathJson.functions, cwd, "serve", contracts);
|
|
4129
4678
|
if (opts.production !== true) {
|
|
4130
4679
|
freePort(port);
|
|
4131
4680
|
}
|
|
@@ -4160,19 +4709,23 @@ function denoServeArgs(entryPath, opts) {
|
|
|
4160
4709
|
entryPath
|
|
4161
4710
|
];
|
|
4162
4711
|
}
|
|
4163
|
-
function
|
|
4712
|
+
function writeNodeServeEntry(cwd, port, aggregatorPath) {
|
|
4164
4713
|
const nodeEntryPath = join9(cwd, SERVER_RUNNER_DIR, "serve-node.ts");
|
|
4165
4714
|
const aggregatorFile = basename3(aggregatorPath);
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4715
|
+
writeFileSync7(nodeEntryPath, `import { serveNode } from "@uipath/coded-functions-js-runtime/node";
|
|
4716
|
+
${LOAD_AGGREGATOR(aggregatorFile)}
|
|
4717
|
+
const port = Number(process.env.HTTP_SERVER_LISTEN_PORT ?? ${port});
|
|
4718
|
+
console.log("http://localhost:" + port);
|
|
4719
|
+
${SIGNAL_READY_NODE}
|
|
4720
|
+
serveNode(app, port, (port) => {
|
|
4172
4721
|
console.log(\`JS function node server listening on http://127.0.0.1:\${port}\`);
|
|
4173
4722
|
signalReady();
|
|
4174
4723
|
});
|
|
4175
4724
|
`, "utf-8");
|
|
4725
|
+
return nodeEntryPath;
|
|
4726
|
+
}
|
|
4727
|
+
function serveNode(cwd, port, aggregatorPath, production) {
|
|
4728
|
+
const nodeEntryPath = writeNodeServeEntry(cwd, port, aggregatorPath);
|
|
4176
4729
|
const envFile = join9(cwd, ".env");
|
|
4177
4730
|
let bin;
|
|
4178
4731
|
let tsxPrefix;
|
|
@@ -4203,11 +4756,11 @@ function serveNode(cwd, port, aggregatorPath, production) {
|
|
|
4203
4756
|
function writeDenoServeEntry(cwd, port, aggregatorPath) {
|
|
4204
4757
|
const denoEntryPath = join9(cwd, SERVER_RUNNER_DIR, "serve-deno.ts");
|
|
4205
4758
|
const aggregatorFile = basename3(aggregatorPath);
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4759
|
+
writeFileSync7(denoEntryPath, `${LOAD_AGGREGATOR(aggregatorFile)}
|
|
4760
|
+
const port = Number(Deno.env.get("HTTP_SERVER_LISTEN_PORT") ?? ${port});
|
|
4761
|
+
console.log("http://localhost:" + port);
|
|
4762
|
+
${SIGNAL_READY_DENO}
|
|
4763
|
+
Deno.serve(
|
|
4211
4764
|
{
|
|
4212
4765
|
port,
|
|
4213
4766
|
onListen: () => {
|
|
@@ -4959,7 +5512,7 @@ function strToU8(str, latin1) {
|
|
|
4959
5512
|
else if (c < 2048)
|
|
4960
5513
|
w(192 | c >> 6), w(128 | c & 63);
|
|
4961
5514
|
else if (c > 55295 && c < 57344)
|
|
4962
|
-
c = 65536 + (c &
|
|
5515
|
+
c = 65536 + (c & 1047552) | str.charCodeAt(++i2) & 1023, w(240 | c >> 18), w(128 | c >> 12 & 63), w(128 | c >> 6 & 63), w(128 | c & 63);
|
|
4963
5516
|
else
|
|
4964
5517
|
w(224 | c >> 12), w(128 | c >> 6 & 63), w(128 | c & 63);
|
|
4965
5518
|
}
|
|
@@ -5832,7 +6385,7 @@ async function extractAndWriteEntryPointsAndBindings(aggregatorPath, projectPath
|
|
|
5832
6385
|
} catch (err2) {
|
|
5833
6386
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
5834
6387
|
if (msg.includes("Cannot find") || msg.includes("ERR_MODULE_NOT_FOUND")) {
|
|
5835
|
-
throw new Error(`Failed to load function modules. Run '${describeInstallCommand(
|
|
6388
|
+
throw new Error(`Failed to load function modules. Run '${describeInstallCommand()}' first, then retry.`);
|
|
5836
6389
|
}
|
|
5837
6390
|
throw new Error(`Manifest extraction failed.
|
|
5838
6391
|
${msg}`);
|
|
@@ -5844,10 +6397,10 @@ ${msg}`);
|
|
|
5844
6397
|
if (manifest.endpoints.length === 0) {
|
|
5845
6398
|
throw new Error("No functions found. Add at least one defineFunction() in your functions/ directory.");
|
|
5846
6399
|
}
|
|
5847
|
-
writeEntryPointsAndBindings(toExtractedFunctions(manifest.endpoints), projectPath);
|
|
6400
|
+
await writeEntryPointsAndBindings(toExtractedFunctions(manifest.endpoints), projectPath, false);
|
|
5848
6401
|
return manifest;
|
|
5849
6402
|
}
|
|
5850
|
-
function writeEntryPointsAndBindings(functions, projectPath) {
|
|
6403
|
+
async function writeEntryPointsAndBindings(functions, projectPath, compile) {
|
|
5851
6404
|
const epPath = join11(projectPath, "entry-points.json");
|
|
5852
6405
|
let existingEntryPointsDoc = null;
|
|
5853
6406
|
if (existsSync9(epPath)) {
|
|
@@ -5856,7 +6409,9 @@ function writeEntryPointsAndBindings(functions, projectPath) {
|
|
|
5856
6409
|
} catch {}
|
|
5857
6410
|
}
|
|
5858
6411
|
const entryPointsDoc = buildEntryPointsDoc(functions, existingEntryPointsDoc);
|
|
5859
|
-
|
|
6412
|
+
if (compile)
|
|
6413
|
+
await compileContracts(functions, entryPointsDoc.entryPoints, projectPath);
|
|
6414
|
+
writeFileSync8(join11(projectPath, "entry-points.json"), JSON.stringify(entryPointsDoc, null, 2));
|
|
5860
6415
|
const entryPointIdByPath = new Map;
|
|
5861
6416
|
for (const ep of entryPointsDoc.entryPoints) {
|
|
5862
6417
|
if (ep.type === "function" && !entryPointIdByPath.has(ep.filePath)) {
|
|
@@ -5871,7 +6426,7 @@ function writeEntryPointsAndBindings(functions, projectPath) {
|
|
|
5871
6426
|
} catch {}
|
|
5872
6427
|
}
|
|
5873
6428
|
const bindingsDoc = buildBindingsDoc(functions, entryPointIdByPath, existingBindingsDoc);
|
|
5874
|
-
|
|
6429
|
+
writeFileSync8(join11(projectPath, "bindings_v2.json"), JSON.stringify(bindingsDoc, null, 2));
|
|
5875
6430
|
}
|
|
5876
6431
|
function manifestNeedsExecution(extraction, functionsMap) {
|
|
5877
6432
|
const forcesExecution = new Set([
|
|
@@ -5888,6 +6443,7 @@ function manifestNeedsExecution(extraction, functionsMap) {
|
|
|
5888
6443
|
return Object.values(functionsMap).some((v) => !covered.has(v.split(":")[0]));
|
|
5889
6444
|
}
|
|
5890
6445
|
async function writeManifest(extraction, aggregatorPath, projectPath, functionsMap) {
|
|
6446
|
+
installServerRunner(projectPath, { production: false });
|
|
5891
6447
|
if (manifestNeedsExecution(extraction, functionsMap)) {
|
|
5892
6448
|
const manifest = await extractAndWriteEntryPointsAndBindings(aggregatorPath, projectPath);
|
|
5893
6449
|
return { count: manifest.endpoints.length, static: false };
|
|
@@ -5896,9 +6452,26 @@ async function writeManifest(extraction, aggregatorPath, projectPath, functionsM
|
|
|
5896
6452
|
if (functions.length === 0) {
|
|
5897
6453
|
throw new Error("No functions found. Add at least one defineFunction() in your functions/ directory.");
|
|
5898
6454
|
}
|
|
5899
|
-
writeEntryPointsAndBindings(functions, projectPath);
|
|
6455
|
+
await writeEntryPointsAndBindings(functions, projectPath, true);
|
|
5900
6456
|
return { count: functions.length, static: true };
|
|
5901
6457
|
}
|
|
6458
|
+
async function compileContracts(functions, entryPoints, projectPath) {
|
|
6459
|
+
const shim = join11(projectPath, SERVER_RUNNER_DIR, "compile-contracts.mjs");
|
|
6460
|
+
writeFileSync8(shim, `export { createApp } from "@uipath/coded-functions-js-runtime";
|
|
6461
|
+
`);
|
|
6462
|
+
const { createApp } = await import(pathToFileURL2(shim).href);
|
|
6463
|
+
const byPath = new Map(entryPoints.filter((ep) => ep.type === "function").map((ep) => [ep.filePath, ep]));
|
|
6464
|
+
for (const fn of functions) {
|
|
6465
|
+
const ep = byPath.get("content/" + (fn.functionPath ?? ""));
|
|
6466
|
+
try {
|
|
6467
|
+
createApp([{ functionPath: fn.functionPath, functionDef: { ...fn, input: ep?.input, output: ep?.output, contractVersion: "v1", handler: () => {
|
|
6468
|
+
return;
|
|
6469
|
+
} } }]);
|
|
6470
|
+
} catch (err2) {
|
|
6471
|
+
throw new Error(`${fn.name ?? fn.functionPath}: the runtime rejects this contract. ${err2.message}`);
|
|
6472
|
+
}
|
|
6473
|
+
}
|
|
6474
|
+
}
|
|
5902
6475
|
async function generateManifests(projectPath) {
|
|
5903
6476
|
const uipathJsonPath = join12(projectPath, "uipath.json");
|
|
5904
6477
|
if (!existsSync10(uipathJsonPath)) {
|
|
@@ -5915,17 +6488,13 @@ async function generateManifests(projectPath) {
|
|
|
5915
6488
|
const previousDesignTime = process.env[DESIGN_TIME_ENV];
|
|
5916
6489
|
process.env[DESIGN_TIME_ENV] = "1";
|
|
5917
6490
|
try {
|
|
5918
|
-
const extraction = extractProject(uipathJson.functions, projectPath);
|
|
6491
|
+
const extraction = await extractProject(uipathJson.functions, projectPath);
|
|
5919
6492
|
const blocking = reportDiagnostics(extraction.diagnostics);
|
|
5920
6493
|
if (blocking > 0) {
|
|
5921
6494
|
throw new Error(`${blocking} error(s) in the project's function files — nothing was written. ` + `Fix them and re-run.`);
|
|
5922
6495
|
}
|
|
5923
6496
|
console.log("Generating aggregator...");
|
|
5924
|
-
const aggregatorPath = generateAggregator(uipathJson.functions, projectPath, "serve",
|
|
5925
|
-
const needsExecution = manifestNeedsExecution(extraction, uipathJson.functions);
|
|
5926
|
-
if (needsExecution) {
|
|
5927
|
-
installServerRunner(projectPath);
|
|
5928
|
-
}
|
|
6497
|
+
const aggregatorPath = generateAggregator(uipathJson.functions, projectPath, "serve", contractsFromExtraction(extraction));
|
|
5929
6498
|
console.log("Extracting function manifest...");
|
|
5930
6499
|
return await writeManifest(extraction, aggregatorPath, projectPath, uipathJson.functions);
|
|
5931
6500
|
} finally {
|
|
@@ -5956,7 +6525,7 @@ function registerPackCommand(program2) {
|
|
|
5956
6525
|
const version = packageJson.version ?? "1.0.0";
|
|
5957
6526
|
if (!uipathJson.projectId) {
|
|
5958
6527
|
uipathJson.projectId = randomUUID();
|
|
5959
|
-
|
|
6528
|
+
writeFileSync9(uipathJsonPath, JSON.stringify(uipathJson, null, 2), "utf-8");
|
|
5960
6529
|
}
|
|
5961
6530
|
console.log("Assembling package...");
|
|
5962
6531
|
const outputDir = join13(cwd, ".uipath", "package-build");
|
|
@@ -6002,7 +6571,7 @@ function zipToNupkg(buildDir, cwd, packageId, version) {
|
|
|
6002
6571
|
const zipped = zipSync(files);
|
|
6003
6572
|
mkdirSync5(join13(cwd, ".uipath"), { recursive: true });
|
|
6004
6573
|
const nupkgPath = join13(cwd, ".uipath", `${packageId}.${version}.nupkg`);
|
|
6005
|
-
|
|
6574
|
+
writeFileSync9(nupkgPath, zipped);
|
|
6006
6575
|
return nupkgPath;
|
|
6007
6576
|
}
|
|
6008
6577
|
var GUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -6225,7 +6794,7 @@ function readLocalStudioMetadata(projectDir) {
|
|
|
6225
6794
|
function writeStudioMetadata(projectDir, metadata) {
|
|
6226
6795
|
const path3 = join15(projectDir, STUDIO_METADATA_PATH);
|
|
6227
6796
|
mkdirSync6(dirname4(path3), { recursive: true });
|
|
6228
|
-
|
|
6797
|
+
writeFileSync10(path3, JSON.stringify(metadata, null, 2) + `
|
|
6229
6798
|
`, "utf-8");
|
|
6230
6799
|
return path3;
|
|
6231
6800
|
}
|
|
@@ -6333,8 +6902,11 @@ function collectLocalFiles(projectDir) {
|
|
|
6333
6902
|
walk(projectDir);
|
|
6334
6903
|
return results;
|
|
6335
6904
|
}
|
|
6905
|
+
function studioApiBase(cfg) {
|
|
6906
|
+
return `${cfg.baseUrl}/${cfg.orgId}/studio_/backend/api`;
|
|
6907
|
+
}
|
|
6336
6908
|
function projectBase(cfg) {
|
|
6337
|
-
return `${cfg
|
|
6909
|
+
return `${studioApiBase(cfg)}/Project/${cfg.projectId}`;
|
|
6338
6910
|
}
|
|
6339
6911
|
function authHeaders(cfg, lockKey) {
|
|
6340
6912
|
const h = {
|
|
@@ -6345,7 +6917,50 @@ function authHeaders(cfg, lockKey) {
|
|
|
6345
6917
|
h["x-uipath-sw-lockkey"] = lockKey;
|
|
6346
6918
|
return h;
|
|
6347
6919
|
}
|
|
6920
|
+
async function getJson(cfg, url) {
|
|
6921
|
+
const res = await fetch(url, { headers: authHeaders(cfg) }).catch(() => null);
|
|
6922
|
+
if (!res?.ok || res.status === 204)
|
|
6923
|
+
return null;
|
|
6924
|
+
return await res.json().catch(() => null);
|
|
6925
|
+
}
|
|
6926
|
+
async function serverDrivesLocking(cfg) {
|
|
6927
|
+
const config = await getJson(cfg, `${studioApiBase(cfg)}/Locks/Configuration`);
|
|
6928
|
+
return config?.serverDrivesLockingStrategies === true;
|
|
6929
|
+
}
|
|
6930
|
+
function serverLocksUrl(cfg, query, lockKey) {
|
|
6931
|
+
const keySegment = lockKey ? `/${encodeURIComponent(lockKey)}` : "";
|
|
6932
|
+
return `${studioApiBase(cfg)}/Locks${keySegment}?${new URLSearchParams(query)}`;
|
|
6933
|
+
}
|
|
6348
6934
|
async function acquireLock(cfg) {
|
|
6935
|
+
return await serverDrivesLocking(cfg) ? acquireServerDrivenLock(cfg) : acquireClientDrivenLock(cfg);
|
|
6936
|
+
}
|
|
6937
|
+
async function acquireServerDrivenLock(cfg) {
|
|
6938
|
+
const project = await getJson(cfg, projectBase(cfg));
|
|
6939
|
+
const solutionId = project?.solutionId;
|
|
6940
|
+
const projectScope = solutionId ? { sId: solutionId, pId: cfg.projectId } : { pId: cfg.projectId };
|
|
6941
|
+
const existing = await getJson(cfg, serverLocksUrl(cfg, projectScope));
|
|
6942
|
+
const lockKey = existing?.lockKey ?? crypto.randomUUID();
|
|
6943
|
+
const sharedOnly = existing?.lockKey ? existing.isShared ?? false : true;
|
|
6944
|
+
const putRes = await fetch(serverLocksUrl(cfg, projectScope, lockKey), {
|
|
6945
|
+
method: "PUT",
|
|
6946
|
+
headers: { ...authHeaders(cfg), "Content-Type": "application/json" },
|
|
6947
|
+
body: JSON.stringify({ sharedOnly })
|
|
6948
|
+
});
|
|
6949
|
+
if (putRes.status === 409 || putRes.status === 423)
|
|
6950
|
+
throw lockedError();
|
|
6951
|
+
if (!putRes.ok) {
|
|
6952
|
+
const text = await putRes.text().catch(() => "");
|
|
6953
|
+
throw new Error(`Failed to acquire project lock: ${putRes.status}
|
|
6954
|
+
${text}`);
|
|
6955
|
+
}
|
|
6956
|
+
const releaseScope = solutionId ? { sId: solutionId } : { pId: cfg.projectId };
|
|
6957
|
+
return {
|
|
6958
|
+
key: lockKey,
|
|
6959
|
+
owned: !existing?.lockKey,
|
|
6960
|
+
serverReleaseQuery: { ...releaseScope, sharedOnly: String(sharedOnly) }
|
|
6961
|
+
};
|
|
6962
|
+
}
|
|
6963
|
+
async function acquireClientDrivenLock(cfg) {
|
|
6349
6964
|
const getRes = await fetch(`${projectBase(cfg)}/Lock?api-version=2`, {
|
|
6350
6965
|
headers: authHeaders(cfg)
|
|
6351
6966
|
});
|
|
@@ -6370,10 +6985,11 @@ ${text}`);
|
|
|
6370
6985
|
}
|
|
6371
6986
|
return { key: lockKey, owned: true };
|
|
6372
6987
|
}
|
|
6373
|
-
async function releaseLock(cfg,
|
|
6374
|
-
|
|
6988
|
+
async function releaseLock(cfg, lock) {
|
|
6989
|
+
const url = lock.serverReleaseQuery ? serverLocksUrl(cfg, lock.serverReleaseQuery, lock.key) : `${projectBase(cfg)}/Lock/${lock.key}?api-version=2`;
|
|
6990
|
+
await fetch(url, {
|
|
6375
6991
|
method: "DELETE",
|
|
6376
|
-
headers: authHeaders(cfg,
|
|
6992
|
+
headers: authHeaders(cfg, lock.key)
|
|
6377
6993
|
}).catch(() => {});
|
|
6378
6994
|
}
|
|
6379
6995
|
async function fetchStructure(cfg) {
|
|
@@ -6450,7 +7066,8 @@ async function downloadFile(cfg, fileId) {
|
|
|
6450
7066
|
function isProtectedRemotePath(path3) {
|
|
6451
7067
|
return path3 === "project.uiproj" || path3 === ".project" || path3.startsWith(".project/") || path3 === ".uipath" || path3.startsWith(".uipath/") || path3 === ".settings" || path3.startsWith(".settings/");
|
|
6452
7068
|
}
|
|
6453
|
-
|
|
7069
|
+
var EVALS_DIR = "evals";
|
|
7070
|
+
async function computePlan(cfg, localFiles, structure, keepRemoteEvals) {
|
|
6454
7071
|
const remoteFileMap = new Map(structure.files.map((f) => [f.path, f]));
|
|
6455
7072
|
const plan = {
|
|
6456
7073
|
filesToUpload: [],
|
|
@@ -6459,9 +7076,11 @@ async function computePlan(cfg, localFiles, structure) {
|
|
|
6459
7076
|
};
|
|
6460
7077
|
const localPaths = new Set(localFiles.map((f) => f.remotePath));
|
|
6461
7078
|
for (const rf of structure.files) {
|
|
6462
|
-
if (
|
|
6463
|
-
|
|
6464
|
-
}
|
|
7079
|
+
if (localPaths.has(rf.path) || isProtectedRemotePath(rf.path))
|
|
7080
|
+
continue;
|
|
7081
|
+
if (keepRemoteEvals && rf.path.startsWith(`${EVALS_DIR}/`))
|
|
7082
|
+
continue;
|
|
7083
|
+
plan.filesToDelete.push(rf);
|
|
6465
7084
|
}
|
|
6466
7085
|
const comparisons = localFiles.map(async (lf) => {
|
|
6467
7086
|
const remote = remoteFileMap.get(lf.remotePath);
|
|
@@ -6520,7 +7139,9 @@ async function pushToStudio(cfg, projectDir, localFiles, onProgress) {
|
|
|
6520
7139
|
log("Fetching remote structure...");
|
|
6521
7140
|
const structure = await fetchStructure(cfg);
|
|
6522
7141
|
log("Computing diff...");
|
|
6523
|
-
const
|
|
7142
|
+
const evalsDir = statSync3(join16(projectDir, EVALS_DIR), { throwIfNoEntry: false });
|
|
7143
|
+
const keepRemoteEvals = !evalsDir?.isDirectory();
|
|
7144
|
+
const plan = await computePlan(cfg, localFiles, structure, keepRemoteEvals);
|
|
6524
7145
|
const total = plan.filesToUpload.length + plan.filesToUpdate.length + plan.filesToDelete.length;
|
|
6525
7146
|
const remoteMetadata = structure.files.find((f) => f.path === STUDIO_METADATA_PATH);
|
|
6526
7147
|
if (total === 0 && remoteMetadata) {
|
|
@@ -6533,7 +7154,7 @@ async function pushToStudio(cfg, projectDir, localFiles, onProgress) {
|
|
|
6533
7154
|
await cleanupEmptyFolders(cfg, lock.key);
|
|
6534
7155
|
} finally {
|
|
6535
7156
|
if (lock?.owned) {
|
|
6536
|
-
await releaseLock(cfg, lock
|
|
7157
|
+
await releaseLock(cfg, lock);
|
|
6537
7158
|
}
|
|
6538
7159
|
}
|
|
6539
7160
|
}
|
|
@@ -6593,16 +7214,13 @@ Create the project in Studio Web first to get UIPATH_PROJECT_ID.`);
|
|
|
6593
7214
|
}
|
|
6594
7215
|
if (!uipathJson.projectId) {
|
|
6595
7216
|
uipathJson.projectId = creds.projectId;
|
|
6596
|
-
|
|
7217
|
+
writeFileSync11(uipathJsonPath, JSON.stringify(uipathJson, null, 2) + `
|
|
6597
7218
|
`, "utf-8");
|
|
6598
7219
|
}
|
|
6599
7220
|
console.log("Generating entry-points.json...");
|
|
6600
|
-
const extraction = extractProject(uipathJson.functions, cwd);
|
|
7221
|
+
const extraction = await extractProject(uipathJson.functions, cwd);
|
|
6601
7222
|
reportDiagnosticsOrExit(extraction.diagnostics);
|
|
6602
|
-
const aggregatorPath = generateAggregator(uipathJson.functions, cwd, "serve",
|
|
6603
|
-
if (manifestNeedsExecution(extraction, uipathJson.functions)) {
|
|
6604
|
-
installServerRunner(cwd);
|
|
6605
|
-
}
|
|
7223
|
+
const aggregatorPath = generateAggregator(uipathJson.functions, cwd, "serve", contractsFromExtraction(extraction));
|
|
6606
7224
|
try {
|
|
6607
7225
|
const result = await writeManifest(extraction, aggregatorPath, cwd, uipathJson.functions);
|
|
6608
7226
|
console.log(` ${result.count} function(s) exported — ${result.static ? "extracted statically" : "executed to extract"}.`);
|
|
@@ -6627,8 +7245,12 @@ Push complete.`);
|
|
|
6627
7245
|
}
|
|
6628
7246
|
});
|
|
6629
7247
|
}
|
|
6630
|
-
|
|
6631
|
-
|
|
7248
|
+
function contractFilePath(cwd) {
|
|
7249
|
+
const jobDir = process.env.JOB_WORKING_DIRECTORY;
|
|
7250
|
+
const fileName = jobDir ? `contract.${basename5(jobDir)}.json` : "contract.json";
|
|
7251
|
+
return join18(cwd, ".uipath", "run", fileName);
|
|
7252
|
+
}
|
|
7253
|
+
function resolveTargetEntry(cwd, opts) {
|
|
6632
7254
|
let entry = opts.entrypoint;
|
|
6633
7255
|
if (!entry && opts.function) {
|
|
6634
7256
|
const mapped = readFunctionsMap(cwd)[opts.function];
|
|
@@ -6640,19 +7262,25 @@ function resolveTargetFile(cwd, opts) {
|
|
|
6640
7262
|
const match = entry.match(/^(.*?):([A-Za-z_$][\w$]*)$/);
|
|
6641
7263
|
const filePart = match ? match[1] : entry;
|
|
6642
7264
|
const abs = isAbsolute3(filePart) ? filePart : resolve8(cwd, filePart);
|
|
6643
|
-
return relative3(cwd, abs);
|
|
7265
|
+
return { file: relative3(cwd, abs), exportName: match ? match[2] : "default" };
|
|
6644
7266
|
}
|
|
6645
|
-
function
|
|
7267
|
+
async function writeContractFile(cwd, opts) {
|
|
6646
7268
|
try {
|
|
6647
|
-
const
|
|
6648
|
-
if (!
|
|
7269
|
+
const target = resolveTargetEntry(cwd, opts);
|
|
7270
|
+
if (!target)
|
|
6649
7271
|
return "";
|
|
6650
|
-
const
|
|
6651
|
-
|
|
7272
|
+
const fromDocument = opts.production === true && !derivesFromSource();
|
|
7273
|
+
const contract = fromDocument && target.exportName === "default" ? contractFromDocument(target.file, cwd) : await extractContract(target.file, cwd, target.exportName, executionDeriveOptions(), !fromDocument);
|
|
7274
|
+
if (!contract)
|
|
6652
7275
|
return "";
|
|
6653
|
-
const outPath =
|
|
6654
|
-
mkdirSync7(
|
|
6655
|
-
|
|
7276
|
+
const outPath = contractFilePath(cwd);
|
|
7277
|
+
mkdirSync7(dirname5(outPath), { recursive: true });
|
|
7278
|
+
writeFileSync12(outPath, JSON.stringify(contract), "utf-8");
|
|
7279
|
+
process.once("exit", () => {
|
|
7280
|
+
try {
|
|
7281
|
+
rmSync2(outPath, { force: true });
|
|
7282
|
+
} catch {}
|
|
7283
|
+
});
|
|
6656
7284
|
return outPath;
|
|
6657
7285
|
} catch (err2) {
|
|
6658
7286
|
console.error("contract preparation skipped: " + (err2 instanceof Error ? err2.message : String(err2)));
|
|
@@ -6726,13 +7354,16 @@ function registerRunCommand(program2) {
|
|
|
6726
7354
|
const skipInstall = opts.production === true && existsSync16(join19(cwd, SERVER_RUNNER_DIR));
|
|
6727
7355
|
if (!skipInstall) {
|
|
6728
7356
|
try {
|
|
6729
|
-
installServerRunner(cwd);
|
|
7357
|
+
installServerRunner(cwd, { production: opts.production === true });
|
|
6730
7358
|
} catch (err2) {
|
|
6731
7359
|
console.error(err2 instanceof Error ? err2.message : String(err2));
|
|
6732
7360
|
process.exit(1);
|
|
6733
7361
|
}
|
|
6734
7362
|
}
|
|
6735
|
-
|
|
7363
|
+
if (syncFunctionsMap(cwd)) {
|
|
7364
|
+
console.log("Updated functions map in uipath.json.");
|
|
7365
|
+
}
|
|
7366
|
+
const derivedFile = await writeContractFile(cwd, opts);
|
|
6736
7367
|
const runOpts = { ...opts, derivedFile };
|
|
6737
7368
|
if (opts.runtime === "deno") {
|
|
6738
7369
|
runDeno(cwd, runOpts);
|
|
@@ -6780,7 +7411,7 @@ function readIfPresent(path3) {
|
|
|
6780
7411
|
}
|
|
6781
7412
|
function removeQuietly(path3) {
|
|
6782
7413
|
try {
|
|
6783
|
-
|
|
7414
|
+
rmSync3(path3, { force: true });
|
|
6784
7415
|
return true;
|
|
6785
7416
|
} catch {
|
|
6786
7417
|
return false;
|
|
@@ -6795,7 +7426,7 @@ function writeRunEntry(cwd, fileName, content) {
|
|
|
6795
7426
|
}
|
|
6796
7427
|
const tmp = `${entryPath}.${process.pid}.tmp`;
|
|
6797
7428
|
try {
|
|
6798
|
-
|
|
7429
|
+
writeFileSync13(tmp, content, "utf-8");
|
|
6799
7430
|
renameSync(tmp, entryPath);
|
|
6800
7431
|
} catch (err2) {
|
|
6801
7432
|
removeQuietly(tmp);
|
|
@@ -6915,22 +7546,10 @@ function registerPrepareRuntimeCommand(program2) {
|
|
|
6915
7546
|
process.exit(1);
|
|
6916
7547
|
}
|
|
6917
7548
|
mkdirSync9(runnerDir, { recursive: true });
|
|
6918
|
-
const pkg =
|
|
6919
|
-
name: "runner",
|
|
6920
|
-
private: true,
|
|
6921
|
-
type: "module",
|
|
6922
|
-
dependencies: {
|
|
6923
|
-
"@uipath/coded-functions-js-runtime": RUNTIME_VERSION,
|
|
6924
|
-
"@uipath/coreipc": COREIPC_VERSION,
|
|
6925
|
-
tsx: TSX_VERSION,
|
|
6926
|
-
"@microsoft/signalr": SIGNALR_VERSION,
|
|
6927
|
-
"@jridgewell/trace-mapping": TRACE_MAPPING_VERSION
|
|
6928
|
-
}
|
|
6929
|
-
};
|
|
7549
|
+
const pkg = runnerManifest();
|
|
6930
7550
|
const pkgPath = join20(runnerDir, "package.json");
|
|
6931
|
-
|
|
7551
|
+
writeFileSync14(pkgPath, JSON.stringify(pkg, null, 2), "utf-8");
|
|
6932
7552
|
console.log(`Wrote ${pkgPath}`);
|
|
6933
|
-
writeRunnerRegistryConfig(runnerDir);
|
|
6934
7553
|
console.log("Installing dependencies...");
|
|
6935
7554
|
try {
|
|
6936
7555
|
manager.runInstall(runnerDir, { production: true });
|
|
@@ -6942,10 +7561,10 @@ function registerPrepareRuntimeCommand(program2) {
|
|
|
6942
7561
|
});
|
|
6943
7562
|
}
|
|
6944
7563
|
function registerInstallServerCommand(program2) {
|
|
6945
|
-
program2.command("install-server").description("Provision a packed project: install the server-runner and, when node_modules is missing, its production dependencies.").option("--template <path>", "Path to the server-runner template folder").addOption(new Option("--package-manager <name-or-path>", "Install with this package manager instead of the project's own").hideHelp()).action((opts) => {
|
|
7564
|
+
program2.command("install-server").description("Provision a packed project: install the server-runner and, when node_modules is missing, its production dependencies.").option("--template <path>", "Path to the server-runner template folder").option("--hard-link", "Hard-link the template's files instead of copying them").addOption(new Option("--package-manager <name-or-path>", "Install with this package manager instead of the project's own").hideHelp()).action((opts) => {
|
|
6946
7565
|
const cwd = resolve11(".");
|
|
6947
7566
|
try {
|
|
6948
|
-
provisionPackage(cwd, opts.template, opts.packageManager);
|
|
7567
|
+
provisionPackage(cwd, opts.template, opts.packageManager, opts.hardLink);
|
|
6949
7568
|
} catch (err2) {
|
|
6950
7569
|
console.error(err2 instanceof Error ? err2.message : String(err2));
|
|
6951
7570
|
process.exit(1);
|
|
@@ -6957,8 +7576,31 @@ var DEFAULT_HUB = "http://127.0.0.1:5099/signalr/robotdebug";
|
|
|
6957
7576
|
var DEFAULT_INSPECT = "127.0.0.1:9231";
|
|
6958
7577
|
var BRIDGE_FILE = "debug-bridge.ts";
|
|
6959
7578
|
var WORKER_FILE = "debug-job-worker.ts";
|
|
7579
|
+
function parseDebugRuntime(value) {
|
|
7580
|
+
return value === "node" || value === "deno" ? value : undefined;
|
|
7581
|
+
}
|
|
7582
|
+
var MAX_ATTACH_TIMEOUT_SECONDS = 86400;
|
|
7583
|
+
function parseAttach(attach, runAsJob) {
|
|
7584
|
+
if (attach === true && !runAsJob) {
|
|
7585
|
+
throw new Error("--attach requires --run-as-job.");
|
|
7586
|
+
}
|
|
7587
|
+
return attach === true;
|
|
7588
|
+
}
|
|
7589
|
+
function parseAttachTimeout(value, attach) {
|
|
7590
|
+
if (value === undefined) {
|
|
7591
|
+
return;
|
|
7592
|
+
}
|
|
7593
|
+
const seconds = Number(value);
|
|
7594
|
+
if (!Number.isInteger(seconds) || seconds < 1 || seconds > MAX_ATTACH_TIMEOUT_SECONDS) {
|
|
7595
|
+
throw new Error(`--attach-timeout must be a whole number of seconds from 1 to ${MAX_ATTACH_TIMEOUT_SECONDS}.`);
|
|
7596
|
+
}
|
|
7597
|
+
if (!attach) {
|
|
7598
|
+
throw new Error("--attach-timeout requires --attach.");
|
|
7599
|
+
}
|
|
7600
|
+
return seconds;
|
|
7601
|
+
}
|
|
6960
7602
|
function resolveDebugAssetsDir(moduleUrl) {
|
|
6961
|
-
const moduleDir =
|
|
7603
|
+
const moduleDir = dirname6(fileURLToPath2(moduleUrl));
|
|
6962
7604
|
const candidates = [
|
|
6963
7605
|
join21(moduleDir, "deno-runtime", "debug"),
|
|
6964
7606
|
join21(moduleDir, "..", "deno-runtime", "debug"),
|
|
@@ -6976,11 +7618,11 @@ function stageDebugAssets(cwd) {
|
|
|
6976
7618
|
mkdirSync10(stagedDir, { recursive: true });
|
|
6977
7619
|
const assetsDir = resolveDebugAssetsDir(import.meta.url);
|
|
6978
7620
|
for (const entry of readdirSync6(assetsDir)) {
|
|
6979
|
-
|
|
7621
|
+
writeFileSync15(join21(stagedDir, entry), readFileSync16(join21(assetsDir, entry), "utf-8"), "utf-8");
|
|
6980
7622
|
}
|
|
6981
7623
|
return { bridge: join21(stagedDir, BRIDGE_FILE), worker: join21(stagedDir, WORKER_FILE) };
|
|
6982
7624
|
}
|
|
6983
|
-
function buildBridgeSpawn(bridgePath, workerEntry, opts) {
|
|
7625
|
+
function buildBridgeSpawn(bridgePath, workerEntry, opts, nodeLoader = []) {
|
|
6984
7626
|
const modeEnv = opts.runAsJob ? {
|
|
6985
7627
|
DEBUG_RUN_AS_JOB: "1",
|
|
6986
7628
|
FN_ENTRYPOINT: opts.entrypoint,
|
|
@@ -6988,27 +7630,33 @@ function buildBridgeSpawn(bridgePath, workerEntry, opts) {
|
|
|
6988
7630
|
FN_INPUT_FILE: opts.inputFile,
|
|
6989
7631
|
FN_CONTEXT: opts.context,
|
|
6990
7632
|
FN_CONTEXT_FILE: opts.contextFile,
|
|
6991
|
-
FN_DERIVED_FILE: opts.derivedFile
|
|
7633
|
+
FN_DERIVED_FILE: opts.derivedFile,
|
|
7634
|
+
...opts.attach ? { DEBUG_ATTACH: "1" } : {},
|
|
7635
|
+
...opts.attachTimeoutSeconds ? { DEBUG_ATTACH_TIMEOUT_MS: String(opts.attachTimeoutSeconds * 1000) } : {}
|
|
6992
7636
|
} : {
|
|
6993
7637
|
DEBUG_RUN_AS_JOB: "0",
|
|
6994
7638
|
FN_NAME: opts.functionName,
|
|
6995
7639
|
FN_FILE: opts.functionFile,
|
|
6996
7640
|
FN_PORT: String(opts.port ?? DEFAULT_PORT2)
|
|
6997
7641
|
};
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7642
|
+
const envFileArg = opts.envFile ? [`--env-file=${opts.envFile}`] : [];
|
|
7643
|
+
const args = opts.runtime === "deno" ? [
|
|
7644
|
+
"run",
|
|
7645
|
+
"--node-modules-dir=manual",
|
|
7646
|
+
...opts.production ? denoPermissionFlags(process.cwd(), true) : [
|
|
7002
7647
|
"--allow-env",
|
|
7003
7648
|
"--allow-net",
|
|
7004
7649
|
"--allow-read",
|
|
7005
7650
|
"--allow-write",
|
|
7006
7651
|
"--allow-run",
|
|
7007
|
-
...opts.runAsJob ? ["--allow-sys"] : []
|
|
7008
|
-
...opts.envFile ? [`--env-file=${opts.envFile}`] : [],
|
|
7009
|
-
`--inspect=${opts.inspect}`,
|
|
7010
|
-
bridgePath
|
|
7652
|
+
...opts.runAsJob ? ["--allow-sys"] : []
|
|
7011
7653
|
],
|
|
7654
|
+
...envFileArg,
|
|
7655
|
+
`--inspect=${opts.inspect}`,
|
|
7656
|
+
bridgePath
|
|
7657
|
+
] : [`--inspect=${opts.inspect}`, ...nodeLoader, ...envFileArg, bridgePath];
|
|
7658
|
+
return {
|
|
7659
|
+
args,
|
|
7012
7660
|
env: {
|
|
7013
7661
|
DEBUG_SESSION_ID: opts.session,
|
|
7014
7662
|
HUB_URL: opts.hub,
|
|
@@ -7021,9 +7669,23 @@ function buildBridgeSpawn(bridgePath, workerEntry, opts) {
|
|
|
7021
7669
|
};
|
|
7022
7670
|
}
|
|
7023
7671
|
function registerDebugCommand(program2) {
|
|
7024
|
-
program2.command("debug").description("Debug a coded function: bridges StudioWeb's SignalR DebugHub to the
|
|
7672
|
+
program2.command("debug").description("Debug a coded function: bridges StudioWeb's SignalR DebugHub to the V8 inspector of a Node (default) or Deno debuggee for line breakpoints.").option("--runtime <runtime>", "Runtime hosting the bridge and its debuggee: node (default) or deno", "node").option("--session <id>", "Debug session id / jobKey (must match the FE debug hub group)").option("--hub <url>", "SignalR DebugHub relay URL", DEFAULT_HUB).option("--run-as-job", "Debug a one-shot coded function job without an HTTP server").option("--entrypoint <path>", "Path to the function file (run-as-job mode)").option("--function <name>", "Which function from uipath.json to debug (default: the first)").option("--port <port>", "Port the debug server listens on", String(DEFAULT_PORT2)).option("--input <json>", "JSON input passed to the function's main method", "{}").option("--input-file <path>", "Path to a JSON input file (takes priority over --input)").option("--context <json>", "JSON runtime-context payload (used when --context-file is absent)").option("--context-file <path>", "Path to the runtime-context JSON file (takes priority over --context)").option("--production", "Use the preinstalled server-runner dependencies when available, and give the debuggee run --production's permissions").option("--inspect <endpoint>", "V8 inspector endpoint for the spawned runner", DEFAULT_INSPECT).option("--token <jwt>", "Bearer token for a remote SignalR hub. Falls back to env HUB_ACCESS_TOKEN when omitted; leave both unset for an unauthenticated local hub.", "").option("--attach", "Run-as-job mode: a debugger attaches to this job instead of launching it. The job runs its own input and function once, keeps running when the debugger leaves, and reports its result as `run` does").option("--attach-timeout <seconds>", `With --attach: run the job without a debugger when none attaches within this many seconds (1-${MAX_ATTACH_TIMEOUT_SECONDS})`).action(async (opts) => {
|
|
7025
7673
|
const cwd = resolve12(".");
|
|
7026
7674
|
const runAsJob = opts.runAsJob === true;
|
|
7675
|
+
let attach = false;
|
|
7676
|
+
let attachTimeoutSeconds;
|
|
7677
|
+
try {
|
|
7678
|
+
attach = parseAttach(opts.attach, runAsJob);
|
|
7679
|
+
attachTimeoutSeconds = parseAttachTimeout(opts.attachTimeout, attach);
|
|
7680
|
+
} catch (err2) {
|
|
7681
|
+
console.error(err2 instanceof Error ? err2.message : String(err2));
|
|
7682
|
+
process.exit(1);
|
|
7683
|
+
}
|
|
7684
|
+
const runtime = parseDebugRuntime(opts.runtime);
|
|
7685
|
+
if (!runtime) {
|
|
7686
|
+
console.error(`Unknown runtime: ${opts.runtime}. Use node or deno.`);
|
|
7687
|
+
process.exit(1);
|
|
7688
|
+
}
|
|
7027
7689
|
if (opts.entrypoint && !runAsJob) {
|
|
7028
7690
|
console.error("--entrypoint requires --run-as-job.");
|
|
7029
7691
|
process.exit(1);
|
|
@@ -7036,6 +7698,10 @@ function registerDebugCommand(program2) {
|
|
|
7036
7698
|
console.error("Provide only one of --entrypoint or --function.");
|
|
7037
7699
|
process.exit(1);
|
|
7038
7700
|
}
|
|
7701
|
+
if (runtime === "deno" && !denoAvailable()) {
|
|
7702
|
+
console.error("Deno not found. Install it with 'uipath-functions setup --runtime deno', or pass --runtime node.");
|
|
7703
|
+
process.exit(1);
|
|
7704
|
+
}
|
|
7039
7705
|
const uipathJsonPath = join21(cwd, "uipath.json");
|
|
7040
7706
|
if (!existsSync17(uipathJsonPath) && (!runAsJob || !opts.entrypoint)) {
|
|
7041
7707
|
console.error("No uipath.json found. Run 'uipath-functions init' first.");
|
|
@@ -7094,44 +7760,44 @@ function registerDebugCommand(program2) {
|
|
|
7094
7760
|
const skipInstall = opts.production === true && existsSync17(join21(cwd, SERVER_RUNNER_DIR));
|
|
7095
7761
|
if (!skipInstall) {
|
|
7096
7762
|
try {
|
|
7097
|
-
installServerRunner(cwd);
|
|
7763
|
+
installServerRunner(cwd, { production: opts.production === true });
|
|
7098
7764
|
} catch (err2) {
|
|
7099
7765
|
console.error(err2 instanceof Error ? err2.message : String(err2));
|
|
7100
7766
|
process.exit(1);
|
|
7101
7767
|
}
|
|
7102
7768
|
}
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
|
|
7769
|
+
let nodeLoader = [];
|
|
7770
|
+
if (runtime === "node") {
|
|
7771
|
+
const loader = resolveTsxLoader(cwd);
|
|
7772
|
+
if (!loader) {
|
|
7773
|
+
console.error(`tsx not found in ${SERVER_RUNNER_DIR}. Run 'uipath-functions install-server' and retry.`);
|
|
7106
7774
|
process.exit(1);
|
|
7107
7775
|
}
|
|
7108
|
-
|
|
7109
|
-
const selector = { entrypoint: opts.entrypoint, function: fnName || undefined, production: opts.production };
|
|
7110
|
-
runNode(cwd, {
|
|
7111
|
-
...selector,
|
|
7112
|
-
input: inputJson,
|
|
7113
|
-
inputFile: opts.inputFile,
|
|
7114
|
-
context: opts.context,
|
|
7115
|
-
contextFile: opts.contextFile,
|
|
7116
|
-
derivedFile: writeDerivedContract(cwd, selector)
|
|
7117
|
-
});
|
|
7118
|
-
return;
|
|
7776
|
+
nodeLoader = loader;
|
|
7119
7777
|
}
|
|
7120
7778
|
const staged = stageDebugAssets(cwd);
|
|
7121
7779
|
let workerEntry;
|
|
7122
7780
|
let derivedFile = "";
|
|
7123
7781
|
if (runAsJob) {
|
|
7124
|
-
derivedFile =
|
|
7782
|
+
derivedFile = await writeContractFile(cwd, { entrypoint: opts.entrypoint, function: opts.function, production: opts.production });
|
|
7125
7783
|
workerEntry = staged.worker;
|
|
7126
7784
|
} else {
|
|
7127
|
-
const
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7785
|
+
const contracts = await resolveContracts(functions, cwd, opts.production === true, async () => {
|
|
7786
|
+
const extraction = await extractProject(functions, cwd, executionDeriveOptions());
|
|
7787
|
+
reportDiagnosticsOrExit(extraction.diagnostics);
|
|
7788
|
+
return extraction;
|
|
7789
|
+
}).catch((err2) => {
|
|
7790
|
+
if (!(err2 instanceof IncompleteDocumentError))
|
|
7791
|
+
throw err2;
|
|
7792
|
+
console.error(err2.message);
|
|
7793
|
+
process.exit(1);
|
|
7794
|
+
});
|
|
7795
|
+
const aggregatorPath = generateAggregator(functions, cwd, "serve", contracts);
|
|
7796
|
+
workerEntry = runtime === "deno" ? writeDenoServeEntry(cwd, port, aggregatorPath) : writeNodeServeEntry(cwd, port, aggregatorPath);
|
|
7132
7797
|
freePort(port);
|
|
7133
7798
|
}
|
|
7134
7799
|
const resolved = {
|
|
7800
|
+
runtime,
|
|
7135
7801
|
session: opts.session && opts.session.length > 0 ? opts.session : randomUUID2(),
|
|
7136
7802
|
hub: opts.hub,
|
|
7137
7803
|
inspect: opts.inspect,
|
|
@@ -7139,27 +7805,30 @@ function registerDebugCommand(program2) {
|
|
|
7139
7805
|
runAsJob,
|
|
7140
7806
|
entrypoint: opts.entrypoint ?? "",
|
|
7141
7807
|
functionName: fnName,
|
|
7142
|
-
functionFile: fnName ?
|
|
7808
|
+
functionFile: fnName ? resolveTargetEntry(cwd, { function: fnName })?.file ?? "" : "",
|
|
7143
7809
|
input: inputJson,
|
|
7144
7810
|
inputFile: opts.inputFile ?? "",
|
|
7145
7811
|
context: opts.context ?? "",
|
|
7146
7812
|
contextFile: opts.contextFile ?? "",
|
|
7147
7813
|
token: opts.token && opts.token.length > 0 ? opts.token : process.env.HUB_ACCESS_TOKEN ?? "",
|
|
7148
7814
|
envFile: existsSync17(join21(cwd, ".env")) ? ".env" : "",
|
|
7149
|
-
derivedFile
|
|
7815
|
+
derivedFile,
|
|
7816
|
+
production: opts.production === true,
|
|
7817
|
+
...attach ? { attach } : {},
|
|
7818
|
+
...attachTimeoutSeconds ? { attachTimeoutSeconds } : {}
|
|
7150
7819
|
};
|
|
7151
|
-
const { args, env } = buildBridgeSpawn(staged.bridge, workerEntry, resolved);
|
|
7820
|
+
const { args, env } = buildBridgeSpawn(staged.bridge, workerEntry, resolved, nodeLoader);
|
|
7152
7821
|
const target = resolved.entrypoint || resolved.functionName;
|
|
7153
|
-
console.log(runAsJob ? `Debug bridge: session=${resolved.session} hub=${resolved.hub} job=${target} inspector=${resolved.inspect}` : `Debug bridge: session=${resolved.session} hub=${resolved.hub} function=${fnName} port=${port} inspector=${resolved.inspect}`);
|
|
7154
|
-
const
|
|
7155
|
-
const proc = spawn3(
|
|
7822
|
+
console.log(runAsJob ? `Debug bridge: runtime=${runtime} session=${resolved.session} hub=${resolved.hub} job=${target} inspector=${resolved.inspect}` : `Debug bridge: runtime=${runtime} session=${resolved.session} hub=${resolved.hub} function=${fnName} port=${port} inspector=${resolved.inspect}`);
|
|
7823
|
+
const bin = runtime === "deno" ? resolveDeno() : "node";
|
|
7824
|
+
const proc = spawn3(bin, args, {
|
|
7156
7825
|
cwd,
|
|
7157
7826
|
env: { ...process.env, ...env },
|
|
7158
7827
|
stdio: "inherit"
|
|
7159
7828
|
});
|
|
7160
7829
|
proc.on("error", (err2) => {
|
|
7161
7830
|
if (err2.code === "ENOENT") {
|
|
7162
|
-
console.error("Deno not found. Run 'uipath-functions setup --runtime deno'.");
|
|
7831
|
+
console.error(runtime === "deno" ? "Deno not found. Run 'uipath-functions setup --runtime deno'." : "node not found. Run 'uipath-functions setup'.");
|
|
7163
7832
|
} else {
|
|
7164
7833
|
console.error(err2);
|
|
7165
7834
|
}
|
|
@@ -7168,7 +7837,7 @@ function registerDebugCommand(program2) {
|
|
|
7168
7837
|
proc.on("exit", (code) => process.exit(code ?? 0));
|
|
7169
7838
|
});
|
|
7170
7839
|
}
|
|
7171
|
-
var __dirname3 =
|
|
7840
|
+
var __dirname3 = dirname7(fileURLToPath3(import.meta.url));
|
|
7172
7841
|
var pkg = JSON.parse(readFileSync17(join22(__dirname3, "..", "package.json"), "utf-8"));
|
|
7173
7842
|
function buildProgram() {
|
|
7174
7843
|
const program2 = new Command;
|
|
@@ -7195,4 +7864,4 @@ export {
|
|
|
7195
7864
|
generateManifests
|
|
7196
7865
|
};
|
|
7197
7866
|
|
|
7198
|
-
//# debugId=
|
|
7867
|
+
//# debugId=D0840AE987D2809064756E2164756E21
|