@uipath/function-tool 1.205.0-preview.268 → 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.
@@ -1,42 +1,42 @@
1
- import"./packager-tool-1de529jm.js";
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 dirname6, join as join22 } from "node:path";
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 writeFileSync4 } from "node:fs";
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, writeFileSync as writeFileSync3 } from "node:fs";
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 writeFileSync8 } from "node:fs";
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 writeFileSync5, mkdirSync as mkdirSync3 } from "node:fs";
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 ts3 from "typescript";
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 writeFileSync7 } from "node:fs";
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 writeFileSync10 } from "node:fs";
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 writeFileSync9 } from "node:fs";
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 writeFileSync12 } from "node:fs";
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 writeFileSync11 } from "node:fs";
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 rmSync2, writeFileSync as writeFileSync14 } from "node:fs";
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 writeFileSync13 } from "node:fs";
97
- import { isAbsolute as isAbsolute3, join as join18, relative as relative3, resolve as resolve8 } from "node:path";
98
- import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync15 } from "node:fs";
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 writeFileSync16 } from "node:fs";
102
- import { dirname as dirname5, join as join21, resolve as resolve12 } from "node:path";
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 __toESM = (mod, isNodeMode, target) => {
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 __require = /* @__PURE__ */ createRequire(import.meta.url);
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 = __require("node:events").EventEmitter;
707
- var childProcess4 = __require("node:child_process");
708
- var path3 = __require("node:path");
709
- var fs7 = __require("node:fs");
710
- var process22 = __require("node:process");
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__ = __toESM(require_commander(), 1);
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, preferOffline }) => [
2468
+ args: ({ production }) => [
2466
2469
  "install",
2467
- ...production === true ? ["--omit=dev"] : [],
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, preferOffline }) => [
2482
+ args: ({ production }) => [
2483
+ "install",
2484
+ ...production === true ? BUN_PRODUCTION_FLAGS : []
2485
+ ],
2486
+ strictArgs: ({ production }) => [
2476
2487
  "install",
2477
- ...production === true ? ["--production"] : [],
2478
- ...preferOffline === true ? ["--prefer-offline"] : []
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
- const argv = args(options);
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(cwd)
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 detection = detectPackageManager(presentLockFiles(cwd));
2630
- if (detection.kind !== "found") {
2631
- const { problem, remedyCommand } = describeDependencyProblem(detection);
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 { lockFile, installHint } = detection.manager;
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: installHint
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(cwd) {
2652
- const name = detectProjectManager(cwd) ?? FALLBACK_ORDER[0];
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
- writeFileSync4(join4(projectDir, sampleFile), lang === "ts" ? HELLO_TS : HELLO_JS, "utf-8");
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
- resolvePackageManager(projectDir).runInstall(projectDir);
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.9.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, derivedByPath = {}) {
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 relevantDerived = {};
2815
+ const relevantContracts = {};
2748
2816
  for (const file of files) {
2749
- const d = derivedByPath[file];
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
- relevantDerived[file] = entry;
2826
+ relevantContracts[file] = entry;
2759
2827
  }
2760
- const hasDerived = Object.keys(relevantDerived).length > 0;
2828
+ const hasContracts = Object.keys(relevantContracts).length > 0;
2761
2829
  const entries = files.map((file, i) => {
2762
- const def = hasDerived ? `__lower(f${i}, "${file}")` : `f${i}`;
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 = hasDerived ? `const __derived = ${JSON.stringify(relevantDerived, null, 2)};
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 = __derived[path];
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
- writeFileSync5(outputFile, content, "utf-8");
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
- function typeToSchema(type, checker, topLevel = true) {
2850
- if (!topLevel && type.flags & ts.TypeFlags.Unknown)
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 & ts.TypeFlags.Boolean)
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 & ts.TypeFlags.BooleanLiteral)
2930
+ if (type.flags & TS.TypeFlags.BooleanLiteral)
2855
2931
  return { type: "boolean" };
2856
- if (type.flags & ts.TypeFlags.String)
2932
+ if (type.flags & TS.TypeFlags.String)
2857
2933
  return { type: "string" };
2858
- if (type.flags & ts.TypeFlags.Number)
2934
+ if (type.flags & TS.TypeFlags.Number)
2859
2935
  return { type: "number" };
2860
- if (type.flags & ts.TypeFlags.StringLiteral)
2936
+ if (type.flags & TS.TypeFlags.StringLiteral)
2861
2937
  return { type: "string", const: type.value };
2862
- if (type.flags & ts.TypeFlags.NumberLiteral)
2938
+ if (type.flags & TS.TypeFlags.NumberLiteral)
2863
2939
  return { type: "number", const: type.value };
2864
- if (type.flags & ts.TypeFlags.EnumLiteral && !type.isUnion()) {
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
- return { type: "string", format: "date-time" };
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 & ts.TypeFlags.String)
2959
+ if (member.flags & TS.TypeFlags.String)
2881
2960
  return { type: "string" };
2882
- if (member.flags & ts.TypeFlags.Number)
2961
+ if (member.flags & TS.TypeFlags.Number)
2883
2962
  return { type: "number" };
2884
- if (member.flags & ts.TypeFlags.Boolean)
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 & ts.TypeFlags.Any)
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 & ts.TypeFlags.Unknown)
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 & (ts.TypeFlags.BigInt | ts.TypeFlags.BigIntLiteral))
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 & (ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.Void))
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 & ts.TypeFlags.ESSymbol)
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 & ts.TypeFlags.Object)
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 & (ts.TypeFlags.Undefined | ts.TypeFlags.Null | ts.TypeFlags.Void)));
2909
- if (parts.length === 2 && parts.every((t) => t.flags & ts.TypeFlags.BooleanLiteral))
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 & ts.SymbolFlags.Optional);
3021
+ const optional = !!(sym.flags & TS.SymbolFlags.Optional);
2931
3022
  const propType = checker.getTypeOfSymbolAtLocation(sym, decl);
2932
- const propSchema = typeToSchema(optional ? stripUndefined(propType) : propType, checker, false);
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, ts.IndexKind.String);
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 & ts.TypeFlags.Undefined));
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 & (ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral | ts.TypeFlags.EnumLiteral)) {
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
- return type.getSymbol()?.getName() === "Date" && type.getCallSignatures().length === 0;
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 & ts.ObjectFlags.Tuple);
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
- const name = checker.typeToString(type);
2983
- throw new Error(`Unsupported type in function contract: ${name}` + (detail ? ` — ${detail}` : "") + ". The contract format is a curated JSON Schema subset.");
2984
- }
2985
- var CONSUMER_COMPILER_OPTIONS = {
2986
- target: ts.ScriptTarget.ES2020,
2987
- module: ts.ModuleKind.ESNext,
2988
- moduleResolution: ts.ModuleResolutionKind.Bundler,
2989
- allowImportingTsExtensions: true,
2990
- allowJs: true,
2991
- strict: true,
2992
- skipLibCheck: true,
2993
- noEmit: true
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 = ts.createProgram(rootNames, options, host);
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
- ` + `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.`);
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 = ts.createCompilerHost(options, true);
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 ? ts.createSourceFile(name, text, langVersion, true) : baseGetSourceFile(name, langVersion, onError, shouldCreate);
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 ? ts.createSourceFile(name, text, langVersion, true) : 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 extractFunctionContracts(sourceFile, checker) {
3221
+ function walkDefinitions(sourceFile, checker, sdk, options) {
3063
3222
  const bindings = sdkImportBindings(sourceFile);
3064
- const functions = [];
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 && ts.isObjectLiteralExpression(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 " + "contract fields it carries is not statically known", "warning"),
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 ` + `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"),
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
- functions.push(fn);
3261
+ defs.push({ node, fn, diagnostics, markers });
3094
3262
  }
3095
3263
  }
3096
- ts.forEachChild(node, visit);
3264
+ TS.forEachChild(node, visit);
3097
3265
  };
3098
3266
  visit(sourceFile);
3099
- return { functions, diagnostics };
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 result = extractFunctionContracts(sourceFile, checker);
3116
- for (const fn of result.functions)
3117
- functions.push({ ...fn, functionPath });
3118
- for (const d of result.diagnostics)
3119
- diagnostics.push({ ...d, file: functionPath });
3120
- if (limits?.requireFunctionPerFile && result.functions.length === 0 && !hasDefaultExport(sourceFile, checker)) {
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 && result.functions.length > maxPerFile) {
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: `${result.functions.length} functions are defined in one file; at most ${maxPerFile} ` + `allowed. Move each defineFunction into its own file.`,
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}" ` + `(${b.functionPath}): they match the same requests and are separated only by a ` + `deterministic tie-break — give them distinct paths to make routing unambiguous.`,
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 hasDefaultExport(sourceFile, checker) {
3150
- const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
3151
- if (!moduleSymbol)
3345
+ function isTypeOnlyImport(node) {
3346
+ const clause = node.importClause;
3347
+ if (!clause)
3152
3348
  return false;
3153
- return checker.getExportsOfModule(moduleSymbol).some((s) => s.escapedName === "default");
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 (!ts.isImportDeclaration(stmt))
3486
+ if (!TS.isImportDeclaration(stmt))
3160
3487
  continue;
3161
3488
  const spec = stmt.moduleSpecifier;
3162
- if (!ts.isStringLiteral(spec) || spec.text !== SDK_MODULE)
3489
+ if (!TS.isStringLiteral(spec) || spec.text !== SDK_MODULE)
3163
3490
  continue;
3164
3491
  const named = stmt.importClause?.namedBindings;
3165
- if (named && ts.isNamedImports(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(local, exportName, bindings) {
3174
- return bindings.size > 0 ? bindings.get(local) === exportName : local === exportName;
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 ts.isCallExpression(node) && ts.isIdentifier(node.expression) && matchesSdkExport(node.expression.text, "defineFunction", bindings);
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 callee = ts.isCallExpression(value) && ts.isIdentifier(value.expression) ? value.expression.text : undefined;
3185
- if (ts.isCallExpression(value) && callee !== undefined && MARKER_EXPORTS.some((name) => matchesSdkExport(callee, name, bindings))) {
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 = (bindings.size > 0 ? bindings.get(callee) : callee) === "type";
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
- return { diagnostic: diag(DIAGNOSTIC_CODES.UNSUPPORTED_TYPE, `${field}: ${err.message}`) };
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 (ts.isObjectLiteralExpression(value)) {
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 (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) {
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 && !ts.isSourceFile(current); current = current.parent) {
3223
- if (ts.isFunctionLike(current) || ts.isClassStaticBlockDeclaration(current))
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 (ts.isPropertyAssignment(property)) {
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 (ts.isSpreadAssignment(property))
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 ts.isStringLiteralLike(unwrap(value));
3633
+ return TS.isStringLiteralLike(unwrap(value));
3252
3634
  }
3253
3635
  function findProp(obj, field) {
3254
- return obj.properties.find((p) => ts.isPropertyAssignment(p) && propertyName(p.name) === field);
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 (ts.isAsExpression(current) || ts.isParenthesizedExpression(current) || ts.isSatisfiesExpression(current)) {
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 ts.isStringLiteralLike(value) ? value.text : undefined;
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 (!ts.isArrayLiteralExpression(array))
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 (!ts.isStringLiteralLike(value))
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 (ts.isStringLiteralLike(node))
3700
+ if (TS.isStringLiteralLike(node))
3314
3701
  return node.text;
3315
- if (ts.isNumericLiteral(node))
3702
+ if (TS.isNumericLiteral(node))
3316
3703
  return Number(node.text);
3317
- if (node.kind === ts.SyntaxKind.TrueKeyword)
3704
+ if (node.kind === TS.SyntaxKind.TrueKeyword)
3318
3705
  return true;
3319
- if (node.kind === ts.SyntaxKind.FalseKeyword)
3706
+ if (node.kind === TS.SyntaxKind.FalseKeyword)
3320
3707
  return false;
3321
- if (node.kind === ts.SyntaxKind.NullKeyword)
3708
+ if (node.kind === TS.SyntaxKind.NullKeyword)
3322
3709
  return null;
3323
- if (ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.MinusToken && ts.isNumericLiteral(node.operand)) {
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 (ts.isArrayLiteralExpression(node)) {
3713
+ if (TS.isArrayLiteralExpression(node)) {
3327
3714
  return node.elements.map((el) => foldLiteral(el));
3328
3715
  }
3329
- if (ts.isObjectLiteralExpression(node)) {
3716
+ if (TS.isObjectLiteralExpression(node)) {
3330
3717
  const obj = {};
3331
3718
  for (const p of node.properties) {
3332
- if (!ts.isPropertyAssignment(p)) {
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 (${ts.SyntaxKind[node.kind]})`);
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 { program: program2, checker } = createProgram(diskFs, rootNames, readCompilerOptions(cwd));
3356
- const useCase = ts2.sys.useCaseSensitiveFileNames;
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 = ts2.findConfigFile(cwd, ts2.sys.fileExists, "tsconfig.json");
3753
+ function readCompilerOptions(TS2, cwd) {
3754
+ const configPath = TS2.findConfigFile(cwd, TS2.sys.fileExists, "tsconfig.json");
3366
3755
  if (!configPath)
3367
- return CONSUMER_COMPILER_OPTIONS;
3368
- const read = ts2.readConfigFile(configPath, ts2.sys.readFile);
3756
+ return consumerCompilerOptions();
3757
+ const read = TS2.readConfigFile(configPath, TS2.sys.readFile);
3369
3758
  if (read.error || !read.config)
3370
- return CONSUMER_COMPILER_OPTIONS;
3371
- const parsed = ts2.parseJsonConfigFileContent(read.config, ts2.sys, dirname(configPath));
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: transformAttachments(fn.input ?? { type: "object" }),
3730
- output: transformAttachments(fn.output ?? { type: "object" }),
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 ` + `of functions/ or rename it to ${underscored(d.file)} so discovery skips it.`,
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
- function installServerRunner(cwd, serverRunnerTemplatePath = "", packageManager) {
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
- const pkgJson = JSON.parse(readFileSync4(join7(cwd, "package.json"), "utf-8"));
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).runInstall(serverRunnerDir, { preferOffline: true });
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, preferOffline: 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 buildRunnerDependencies(cwd) {
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
- "@uipath/coded-functions-js-runtime": runtimeVersion,
3897
- "@uipath/coreipc": COREIPC_VERSION,
3898
- tsx: tsxVersion,
3899
- "@microsoft/signalr": SIGNALR_VERSION,
3900
- "@jridgewell/trace-mapping": TRACE_MAPPING_VERSION
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
- assert(checkDependenciesInstalled(cwd), cwd);
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
- const ipcEndpoint = (typeof Deno !== "undefined" ? Deno.env.get("JS_FUNCTION_API_IPC_ENDPOINT") : process.env.JS_FUNCTION_API_IPC_ENDPOINT);
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
- writeFileSync7(uipathJsonPath, JSON.stringify(uipathJson, null, 2) + `
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 extraction = extractProject(uipathJson.functions, cwd);
4116
- if (opts.production !== true)
4117
- reportDiagnosticsOrExit(extraction.diagnostics);
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 derived = toDerivedContracts(extraction.functions);
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 serveNode(cwd, port, aggregatorPath, production) {
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
- writeFileSync8(nodeEntryPath, `import { serveNode } from "@uipath/coded-functions-js-runtime/node";
4167
- ` + `import app from "./${aggregatorFile}";
4168
- ` + `const port = Number(process.env.HTTP_SERVER_LISTEN_PORT ?? ${port});
4169
- ` + `console.log("http://localhost:" + port);
4170
- ` + `${SIGNAL_READY_NODE}
4171
- ` + `serveNode(app, port, (port) => {
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
- writeFileSync8(denoEntryPath, `import app from "./${aggregatorFile}";
4207
- ` + `const port = Number(Deno.env.get("HTTP_SERVER_LISTEN_PORT") ?? ${port});
4208
- ` + `console.log("http://localhost:" + port);
4209
- ` + `${SIGNAL_READY_DENO}
4210
- ` + `Deno.serve(
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 & 1023 << 10) | str.charCodeAt(++i2) & 1023, w(240 | c >> 18), w(128 | c >> 12 & 63), w(128 | c >> 6 & 63), w(128 | c & 63);
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(projectPath)}' first, then retry.`);
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
- writeFileSync9(join11(projectPath, "entry-points.json"), JSON.stringify(entryPointsDoc, null, 2));
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
- writeFileSync9(join11(projectPath, "bindings_v2.json"), JSON.stringify(bindingsDoc, null, 2));
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", toDerivedContracts(extraction.functions));
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
- writeFileSync10(uipathJsonPath, JSON.stringify(uipathJson, null, 2), "utf-8");
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
- writeFileSync10(nupkgPath, zipped);
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
- writeFileSync11(path3, JSON.stringify(metadata, null, 2) + `
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.baseUrl}/${cfg.orgId}/studio_/backend/api/Project/${cfg.projectId}`;
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, lockKey) {
6374
- await fetch(`${projectBase(cfg)}/Lock/${lockKey}?api-version=2`, {
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, lockKey)
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
- async function computePlan(cfg, localFiles, structure) {
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 (!localPaths.has(rf.path) && !isProtectedRemotePath(rf.path)) {
6463
- plan.filesToDelete.push(rf);
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 plan = await computePlan(cfg, localFiles, structure);
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.key);
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
- writeFileSync12(uipathJsonPath, JSON.stringify(uipathJson, null, 2) + `
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", toDerivedContracts(extraction.functions));
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
- var DERIVED_CONTRACT_FILE = ".uipath/run/derived-contracts.json";
6631
- function resolveTargetFile(cwd, opts) {
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 writeDerivedContract(cwd, opts) {
7267
+ async function writeContractFile(cwd, opts) {
6646
7268
  try {
6647
- const relFile = resolveTargetFile(cwd, opts);
6648
- if (!relFile)
7269
+ const target = resolveTargetEntry(cwd, opts);
7270
+ if (!target)
6649
7271
  return "";
6650
- const derived = opts.production ? readBakedContract(relFile, cwd) : deriveRunContract(relFile, cwd);
6651
- if (!derived)
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 = join18(cwd, DERIVED_CONTRACT_FILE);
6654
- mkdirSync7(join18(cwd, ".uipath/run"), { recursive: true });
6655
- writeFileSync13(outPath, JSON.stringify(derived), "utf-8");
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
- const derivedFile = writeDerivedContract(cwd, opts);
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
- rmSync2(path3, { force: true });
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
- writeFileSync14(tmp, content, "utf-8");
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
- writeFileSync15(pkgPath, JSON.stringify(pkg, null, 2), "utf-8");
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 = dirname5(fileURLToPath2(moduleUrl));
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
- writeFileSync16(join21(stagedDir, entry), readFileSync16(join21(assetsDir, entry), "utf-8"), "utf-8");
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
- return {
6999
- args: [
7000
- "run",
7001
- "--node-modules-dir=manual",
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 Deno V8 inspector for line breakpoints. Without Deno, --run-as-job falls back to a plain Node run of the same job.").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").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.", "").action(async (opts) => {
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
- if (!denoAvailable()) {
7104
- if (!runAsJob) {
7105
- console.error("Deno not found, and the HTTP debug bridge needs it. Install it with 'uipath-functions setup --runtime deno', or debug a single invocation with --run-as-job.");
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
- console.error("Deno not found: running the job under Node instead, without breakpoints or the debug hub bridge. Install Deno with 'uipath-functions setup --runtime deno' for a full debug session.");
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 = writeDerivedContract(cwd, { entrypoint: opts.entrypoint, function: opts.function, production: opts.production });
7782
+ derivedFile = await writeContractFile(cwd, { entrypoint: opts.entrypoint, function: opts.function, production: opts.production });
7125
7783
  workerEntry = staged.worker;
7126
7784
  } else {
7127
- const extraction = extractProject(functions, cwd);
7128
- reportDiagnosticsOrExit(extraction.diagnostics);
7129
- const derived = toDerivedContracts(extraction.functions);
7130
- const aggregatorPath = generateAggregator(functions, cwd, "serve", derived);
7131
- workerEntry = writeDenoServeEntry(cwd, port, aggregatorPath);
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 ? resolveTargetFile(cwd, { function: 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 deno = resolveDeno();
7155
- const proc = spawn3(deno, args, {
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 = dirname6(fileURLToPath3(import.meta.url));
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=94EBF991AB3525F364756E2164756E21
7867
+ //# debugId=D0840AE987D2809064756E2164756E21