@reliverse/rempts 1.7.49 → 1.7.51

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.
@@ -16,23 +16,13 @@ import readline__default from 'node:readline';
16
16
  import { ReadStream, WriteStream } from 'node:tty';
17
17
  import readline$1 from 'node:readline/promises';
18
18
  import { repeat, digit, buildRegExp, startOfString, endOfString } from 'ts-regex-builder';
19
- import path, { resolve, dirname } from '@reliverse/pathkit';
20
- import fs from '@reliverse/relifso';
21
- import { loadConfig } from 'c12';
22
- import termkit from 'terminal-kit';
19
+ import { realpathSync } from 'fs';
20
+ import { readFile, writeFile } from 'fs/promises';
21
+ import path from 'path';
22
+ import readline$2 from 'readline';
23
23
  import { homedir } from 'node:os';
24
- import { createJiti } from 'jiti';
25
- import { reliArgParser } from '@reliverse/reliarg';
24
+ import { readdir, stat } from 'node:fs/promises';
26
25
  import { readPackageJSON } from 'pkg-types';
27
- import { inspect } from 'node:util';
28
- import * as trpcServer11 from '@trpc/server';
29
- export { trpcServer11 as trpcServer };
30
- import { Command, Option, Argument, InvalidArgumentError } from 'commander';
31
- import * as zod4 from 'zod/v4/core';
32
- import zodToJsonSchema from 'zod-to-json-schema';
33
- import * as zod from 'zod';
34
- export { zod };
35
- export { z } from 'zod/v4';
36
26
 
37
27
  const colorMap = {
38
28
  // @reliverse/relico
@@ -1374,7 +1364,275 @@ async function datePrompt(opts) {
1374
1364
  }
1375
1365
  }
1376
1366
 
1377
- const { terminal: term } = termkit;
1367
+ class TerminalInterface {
1368
+ rl;
1369
+ _width;
1370
+ _height;
1371
+ keyListeners = [];
1372
+ resizeListeners = [];
1373
+ constructor() {
1374
+ this.rl = readline$2.createInterface({
1375
+ input: process.stdin,
1376
+ output: process.stdout,
1377
+ terminal: true
1378
+ });
1379
+ this._width = process.stdout.columns || 80;
1380
+ this._height = process.stdout.rows || 24;
1381
+ process.stdout.on("resize", () => {
1382
+ this._width = process.stdout.columns || 80;
1383
+ this._height = process.stdout.rows || 24;
1384
+ this.resizeListeners.forEach((listener) => listener(this._width, this._height));
1385
+ });
1386
+ process.stdin.setRawMode(true);
1387
+ process.stdin.resume();
1388
+ process.stdin.setEncoding("utf8");
1389
+ process.stdin.on("data", (data) => {
1390
+ const key = this.parseKey(data);
1391
+ if (key) {
1392
+ this.keyListeners.forEach(
1393
+ (listener) => listener(key, [], {
1394
+ isCharacter: this.isCharacter(key),
1395
+ code: data,
1396
+ codepoint: data.toString().charCodeAt(0)
1397
+ })
1398
+ );
1399
+ }
1400
+ });
1401
+ }
1402
+ parseKey(data) {
1403
+ const str = data.toString();
1404
+ if (str === "") return "CTRL_C";
1405
+ if (str === "") return "CTRL_A";
1406
+ if (str === "") return "CTRL_O";
1407
+ if (str === "") return "CTRL_S";
1408
+ if (str === "") return "CTRL_X";
1409
+ if (str === "") return "CTRL_F";
1410
+ if (str === "\v") return "CTRL_K";
1411
+ if (str === "") return "CTRL_U";
1412
+ if (str === "") return "CTRL_T";
1413
+ if (str === " ") return "TAB";
1414
+ if (str === "\r" || str === "\n") return "ENTER";
1415
+ if (str === "\x7F" || str === "\b") return "BACKSPACE";
1416
+ if (str === "\x1B[3~") return "DELETE";
1417
+ if (str === "\x1B[A") return "UP";
1418
+ if (str === "\x1B[B") return "DOWN";
1419
+ if (str === "\x1B[C") return "RIGHT";
1420
+ if (str === "\x1B[D") return "LEFT";
1421
+ if (str === "\x1B[5~") return "PAGE_UP";
1422
+ if (str === "\x1B[6~") return "PAGE_DOWN";
1423
+ if (str === "\x1B[H") return "HOME";
1424
+ if (str === "\x1B[F") return "END";
1425
+ if (str === "\x1B[1;5H") return "CTRL_HOME";
1426
+ if (str === "\x1B[1;5F") return "CTRL_END";
1427
+ if (str === "\x1B[1;3C") return "ALT_C";
1428
+ if (str === "\x1B[2;2~") return "SHIFT_INSERT";
1429
+ if (str === "\x1B[2;5~") return "CTRL_INSERT";
1430
+ return str.length === 1 ? str : "";
1431
+ }
1432
+ isCharacter(key) {
1433
+ return key.length === 1 && !key.startsWith("\x1B") && ![
1434
+ "CTRL_C",
1435
+ "CTRL_A",
1436
+ "CTRL_O",
1437
+ "CTRL_S",
1438
+ "CTRL_X",
1439
+ "CTRL_F",
1440
+ "CTRL_K",
1441
+ "CTRL_U",
1442
+ "CTRL_T",
1443
+ "TAB",
1444
+ "ENTER",
1445
+ "BACKSPACE",
1446
+ "DELETE",
1447
+ "UP",
1448
+ "DOWN",
1449
+ "RIGHT",
1450
+ "LEFT",
1451
+ "PAGE_UP",
1452
+ "PAGE_DOWN",
1453
+ "HOME",
1454
+ "END",
1455
+ "CTRL_HOME",
1456
+ "CTRL_END",
1457
+ "ALT_C",
1458
+ "SHIFT_INSERT",
1459
+ "CTRL_INSERT"
1460
+ ].includes(key);
1461
+ }
1462
+ get width() {
1463
+ return this._width;
1464
+ }
1465
+ get height() {
1466
+ return this._height;
1467
+ }
1468
+ fullscreen(enabled) {
1469
+ if (enabled) {
1470
+ process.stdout.write("\x1B[?1049h");
1471
+ } else {
1472
+ process.stdout.write("\x1B[?1049l");
1473
+ }
1474
+ }
1475
+ grabInput(enabled) {
1476
+ if (enabled) {
1477
+ process.stdin.setRawMode(true);
1478
+ } else {
1479
+ process.stdin.setRawMode(false);
1480
+ }
1481
+ }
1482
+ on(event, listener) {
1483
+ if (event === "key") {
1484
+ this.keyListeners.push(listener);
1485
+ } else if (event === "resize") {
1486
+ this.resizeListeners.push(listener);
1487
+ }
1488
+ }
1489
+ off(event, listener) {
1490
+ if (event === "key") {
1491
+ const index = this.keyListeners.indexOf(listener);
1492
+ if (index > -1) this.keyListeners.splice(index, 1);
1493
+ } else if (event === "resize") {
1494
+ const index = this.resizeListeners.indexOf(listener);
1495
+ if (index > -1) this.resizeListeners.splice(index, 1);
1496
+ }
1497
+ }
1498
+ moveTo(x, y) {
1499
+ process.stdout.write(ansiEscapes.cursorTo(x, y));
1500
+ }
1501
+ clear() {
1502
+ process.stdout.write(ansiEscapes.clearScreen);
1503
+ }
1504
+ eraseLine() {
1505
+ process.stdout.write(ansiEscapes.eraseLine);
1506
+ }
1507
+ eraseLineAfter() {
1508
+ process.stdout.write(ansiEscapes.eraseLine);
1509
+ }
1510
+ hideCursor() {
1511
+ process.stdout.write(cursor.hide);
1512
+ }
1513
+ restoreCursor() {
1514
+ process.stdout.write(cursor.show);
1515
+ }
1516
+ styleReset() {
1517
+ process.stdout.write(ansiEscapes.cursorShow + "\x1B[0m");
1518
+ }
1519
+ bgColor(color) {
1520
+ const colorMap = {
1521
+ black: "\x1B[40m",
1522
+ white: "\x1B[47m",
1523
+ red: "\x1B[41m",
1524
+ green: "\x1B[42m",
1525
+ yellow: "\x1B[43m",
1526
+ blue: "\x1B[44m",
1527
+ magenta: "\x1B[45m",
1528
+ cyan: "\x1B[46m",
1529
+ brown: "\x1B[43m"
1530
+ };
1531
+ process.stdout.write(colorMap[color] || "");
1532
+ return this;
1533
+ }
1534
+ color(color) {
1535
+ const colorMap = {
1536
+ black: "\x1B[30m",
1537
+ white: "\x1B[37m",
1538
+ red: "\x1B[31m",
1539
+ green: "\x1B[32m",
1540
+ yellow: "\x1B[33m",
1541
+ blue: "\x1B[34m",
1542
+ magenta: "\x1B[35m",
1543
+ cyan: "\x1B[36m",
1544
+ gray: "\x1B[90m"
1545
+ };
1546
+ process.stdout.write(colorMap[color] || "");
1547
+ return this;
1548
+ }
1549
+ inputField(options) {
1550
+ return {
1551
+ promise: new Promise((resolve) => {
1552
+ const prompt = "> ";
1553
+ process.stdout.write(prompt);
1554
+ let input = "";
1555
+ const onData = (data) => {
1556
+ const char = data.toString();
1557
+ if (char === "\n" || char === "\r") {
1558
+ process.stdout.write("\n");
1559
+ process.stdin.removeListener("data", onData);
1560
+ resolve(input);
1561
+ return;
1562
+ }
1563
+ if (char === "") {
1564
+ process.stdout.write("\n");
1565
+ process.stdin.removeListener("data", onData);
1566
+ resolve("");
1567
+ return;
1568
+ }
1569
+ if (char === "\x7F" || char === "\b") {
1570
+ if (input.length > 0) {
1571
+ input = input.slice(0, -1);
1572
+ process.stdout.write("\b \b");
1573
+ }
1574
+ } else if (options.echo) {
1575
+ input += char;
1576
+ process.stdout.write(char);
1577
+ } else {
1578
+ input += char;
1579
+ process.stdout.write("*");
1580
+ }
1581
+ };
1582
+ process.stdin.on("data", onData);
1583
+ })
1584
+ };
1585
+ }
1586
+ yesOrNo(options) {
1587
+ return {
1588
+ promise: new Promise((resolve) => {
1589
+ const prompt = "(y/N) ";
1590
+ process.stdout.write(prompt);
1591
+ const onData = (data) => {
1592
+ const char = data.toString().toLowerCase();
1593
+ if (char === "\n" || char === "\r") {
1594
+ process.stdout.write("\n");
1595
+ process.stdin.removeListener("data", onData);
1596
+ resolve(false);
1597
+ return;
1598
+ }
1599
+ if (char === "") {
1600
+ process.stdout.write("\n");
1601
+ process.stdin.removeListener("data", onData);
1602
+ resolve(null);
1603
+ return;
1604
+ }
1605
+ if (options.yes.includes(char)) {
1606
+ process.stdout.write(char + "\n");
1607
+ process.stdin.removeListener("data", onData);
1608
+ resolve(true);
1609
+ return;
1610
+ }
1611
+ if (options.no.includes(char)) {
1612
+ process.stdout.write(char + "\n");
1613
+ process.stdin.removeListener("data", onData);
1614
+ resolve(false);
1615
+ return;
1616
+ }
1617
+ };
1618
+ process.stdin.on("data", onData);
1619
+ })
1620
+ };
1621
+ }
1622
+ // Callable interface for writing text
1623
+ write(text) {
1624
+ process.stdout.write(text);
1625
+ }
1626
+ red(text) {
1627
+ process.stdout.write("\x1B[31m" + text + "\x1B[0m");
1628
+ }
1629
+ destroy() {
1630
+ this.rl.close();
1631
+ process.stdin.setRawMode(false);
1632
+ process.stdin.pause();
1633
+ }
1634
+ }
1635
+ const term = new TerminalInterface();
1378
1636
  let state = {
1379
1637
  lines: [""],
1380
1638
  // Document content as an array of strings
@@ -1424,24 +1682,6 @@ let state = {
1424
1682
  exitResolver: null,
1425
1683
  exitRejecter: null
1426
1684
  };
1427
- async function loadEditorConfig(cwd = process.cwd(), overrides = {}) {
1428
- const { config } = await loadConfig({
1429
- name: "minedit",
1430
- cwd,
1431
- defaults: {
1432
- // Low priority defaults
1433
- syntaxHighlighting: false,
1434
- theme: "auto",
1435
- defaultAllowSaveAs: true,
1436
- defaultAllowOpen: true,
1437
- defaultAutoCloseOnSave: false,
1438
- defaultReturnContentOnSave: false
1439
- },
1440
- // user provided overrides during programmatic call have higher priority
1441
- overrides
1442
- });
1443
- return config || {};
1444
- }
1445
1685
  function setupTheme(configTheme) {
1446
1686
  let mode = configTheme;
1447
1687
  if (mode === "auto") {
@@ -1500,13 +1740,13 @@ function renderStatusBar() {
1500
1740
  const middlePart = hints + " ".repeat(hintPadding);
1501
1741
  const statusBar = leftPart + middlePart + rightPart;
1502
1742
  term.moveTo(1, term.height - 1);
1503
- term(state.theme.statusBarBg(state.theme.statusBarText(statusBar.padEnd(width))));
1743
+ term.write(state.theme.statusBarBg(state.theme.statusBarText(statusBar.padEnd(width))));
1504
1744
  }
1505
1745
  function renderMessageBar() {
1506
1746
  term.moveTo(1, term.height);
1507
1747
  term.eraseLine();
1508
1748
  if (state.statusMessage) {
1509
- term(state.theme.highlight(state.statusMessage.slice(0, term.width)));
1749
+ term.write(state.theme.highlight(state.statusMessage.slice(0, term.width)));
1510
1750
  setTimeout(() => {
1511
1751
  if (state.isRunning) {
1512
1752
  state.statusMessage = "";
@@ -1549,11 +1789,11 @@ function renderEditor() {
1549
1789
  term.moveTo(1, y + 1);
1550
1790
  if (fileLineIndex < state.lines.length) {
1551
1791
  const lineNum = String(fileLineIndex + 1).padStart(3);
1552
- term(state.theme.lineNumber(`${lineNum} `));
1792
+ term.write(state.theme.lineNumber(`${lineNum} `));
1553
1793
  const line = state.lines[fileLineIndex];
1554
1794
  const displayLine = line?.substring(state.leftCol, state.leftCol + displayWidth);
1555
1795
  const highlightedDisplayLine = applySyntaxHighlighting(displayLine ?? "");
1556
- term(highlightedDisplayLine);
1796
+ term.write(highlightedDisplayLine);
1557
1797
  term.eraseLineAfter();
1558
1798
  } else {
1559
1799
  term.eraseLine();
@@ -1693,13 +1933,15 @@ async function promptForFilename(promptMessage = "File path: ") {
1693
1933
  renderMessageBar();
1694
1934
  term.moveTo(1, term.height);
1695
1935
  term.eraseLine();
1696
- term(promptMessage);
1936
+ term.write(promptMessage);
1697
1937
  try {
1698
1938
  const input = await term.inputField({ echo: true }).promise;
1699
- term.moveTo(1, term.height).eraseLine();
1939
+ term.moveTo(1, term.height);
1940
+ term.eraseLine();
1700
1941
  return input ? input.trim() : null;
1701
1942
  } catch (_error) {
1702
- term.moveTo(1, term.height).eraseLine();
1943
+ term.moveTo(1, term.height);
1944
+ term.eraseLine();
1703
1945
  state.statusMessage = "Cancelled";
1704
1946
  render();
1705
1947
  return null;
@@ -1710,16 +1952,18 @@ async function confirmAction(promptMessage = "Are you sure? (y/N)") {
1710
1952
  renderMessageBar();
1711
1953
  term.moveTo(1, term.height);
1712
1954
  term.eraseLine();
1713
- term(`${promptMessage} `);
1955
+ term.write(`${promptMessage} `);
1714
1956
  try {
1715
1957
  const confirm = await term.yesOrNo({
1716
1958
  yes: ["y", "Y"],
1717
1959
  no: ["n", "N", "ENTER"]
1718
1960
  }).promise;
1719
- term.moveTo(1, term.height).eraseLine();
1961
+ term.moveTo(1, term.height);
1962
+ term.eraseLine();
1720
1963
  return confirm ?? false;
1721
1964
  } catch (_error) {
1722
- term.moveTo(1, term.height).eraseLine();
1965
+ term.moveTo(1, term.height);
1966
+ term.eraseLine();
1723
1967
  state.statusMessage = "Cancelled";
1724
1968
  render();
1725
1969
  return false;
@@ -1766,7 +2010,7 @@ async function saveFile() {
1766
2010
  return true;
1767
2011
  }
1768
2012
  try {
1769
- await fs.writeFile(state.filename, contentToSave);
2013
+ await writeFile(state.filename, contentToSave);
1770
2014
  state.originalContent = contentToSave;
1771
2015
  state.modified = false;
1772
2016
  state.statusMessage = `Saved to ${state.filename}`;
@@ -1832,7 +2076,7 @@ async function loadFile(filePath) {
1832
2076
  const absolutePath = path.resolve(cwd, filePath);
1833
2077
  let content = "";
1834
2078
  try {
1835
- content = await fs.readFile(absolutePath, "utf-8");
2079
+ content = await readFile(absolutePath, "utf-8");
1836
2080
  state.statusMessage = `Opened ${absolutePath}`;
1837
2081
  } catch (error) {
1838
2082
  if (error && error.code === "ENOENT") {
@@ -2056,7 +2300,7 @@ async function cleanupAndExit(saved = false, content = null) {
2056
2300
  }
2057
2301
  term.off("key", handleInputWrapper);
2058
2302
  term.off("resize", handleResize);
2059
- term.hideCursor(false);
2303
+ term.hideCursor();
2060
2304
  term.grabInput(false);
2061
2305
  term.fullscreen(false);
2062
2306
  term.styleReset();
@@ -2141,8 +2385,15 @@ async function initializeEditorState(options) {
2141
2385
  // Reset toggle state
2142
2386
  };
2143
2387
  try {
2144
- const loadedConfig = await loadEditorConfig(state.options.cwd, options.configOverrides);
2145
- state.editorConfig = loadedConfig;
2388
+ state.editorConfig = {
2389
+ defaultAllowSaveAs: true,
2390
+ defaultAllowOpen: true,
2391
+ defaultAutoCloseOnSave: false,
2392
+ defaultReturnContentOnSave: false,
2393
+ syntaxHighlighting: false,
2394
+ theme: "light",
2395
+ ...options.configOverrides
2396
+ };
2146
2397
  state.options.allowSaveAs = options.allowSaveAs ?? state.editorConfig.defaultAllowSaveAs ?? true;
2147
2398
  state.options.allowOpen = options.allowOpen ?? state.editorConfig.defaultAllowOpen ?? true;
2148
2399
  state.options.autoCloseOnSave = options.autoCloseOnSave ?? state.editorConfig.defaultAutoCloseOnSave ?? false;
@@ -2216,8 +2467,8 @@ async function startEditor(options = {}) {
2216
2467
  }
2217
2468
  const isDirectRun = (() => {
2218
2469
  try {
2219
- const scriptPath = fs.realpathSync(process.argv[1] || "");
2220
- const modulePath = fs.realpathSync(import.meta.filename);
2470
+ const scriptPath = realpathSync(process.argv[1] || "");
2471
+ const modulePath = realpathSync(import.meta.filename);
2221
2472
  return scriptPath === modulePath;
2222
2473
  } catch (_e) {
2223
2474
  return false;
@@ -3112,2208 +3363,513 @@ async function introPrompt(optionsOrTitle) {
3112
3363
  const startPrompt = introPrompt;
3113
3364
  const intro = introPrompt;
3114
3365
 
3115
- const jiti = createJiti(import.meta.url, {
3116
- debug: process$1.env.NODE_ENV === "development",
3117
- fsCache: true,
3118
- sourceMaps: true
3119
- });
3120
- const COMMAND_EXTENSIONS = [".ts", ".js"];
3121
- const COMMAND_FILENAMES = ["cmd.ts", "cmd.js"];
3122
- const getCallerDirectory = async () => {
3123
- const stack = new Error().stack?.split("\n") ?? [];
3124
- const cwd = process$1.cwd();
3125
- if (process$1.env.NODE_ENV === "development") {
3126
- relinka("log", "Stack trace for getCallerDirectory:");
3127
- stack.forEach((line, index) => {
3128
- relinka("log", ` [${index}]: ${line.trim()}`);
3129
- });
3130
- }
3131
- for (const line of stack) {
3132
- const match = /\((.*):(\d+):(\d+)\)/.exec(line) || /at (.*):(\d+):(\d+)/.exec(line);
3133
- if (match?.[1]) {
3134
- const filePath = match[1];
3135
- if (process$1.env.NODE_ENV === "development") {
3136
- relinka("log", `Checking file path: ${filePath}`);
3137
- }
3138
- if (!filePath.includes("node_modules") && !filePath.includes("command-runner") && !filePath.includes("command-typed") && !filePath.includes("launcher-mod") && !filePath.includes("launcher-types") && !filePath.endsWith("mod.mjs") && // Skip compiled output
3139
- !filePath.endsWith("mod.js") && // Skip compiled output
3140
- !filePath.endsWith("mod.ts")) {
3141
- try {
3142
- const fileDir = dirname(filePath);
3143
- let currentDir2 = fileDir;
3144
- let packageRoot = null;
3145
- while (currentDir2 !== dirname(currentDir2)) {
3146
- try {
3147
- const packageJsonPath = resolve(currentDir2, "package.json");
3148
- if (await fs.pathExists(packageJsonPath)) {
3149
- packageRoot = currentDir2;
3150
- if (process$1.env.NODE_ENV === "development") {
3151
- relinka("log", `Found package.json at: ${packageRoot}`);
3152
- }
3153
- const cwdPackageJsonPath = resolve(cwd, "package.json");
3154
- if (await fs.pathExists(cwdPackageJsonPath)) {
3155
- try {
3156
- const callerPackage = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
3157
- const cwdPackage = JSON.parse(await fs.readFile(cwdPackageJsonPath, "utf-8"));
3158
- if (callerPackage.name !== cwdPackage.name || callerPackage.version !== cwdPackage.version) {
3159
- if (process$1.env.NODE_ENV === "development") {
3160
- relinka("log", `Using caller package root: ${packageRoot} (${callerPackage.name}@${callerPackage.version})`);
3161
- }
3162
- return packageRoot;
3163
- }
3164
- } catch {
3165
- if (resolve(packageRoot) !== resolve(cwd)) {
3166
- if (process$1.env.NODE_ENV === "development") {
3167
- relinka("log", `Using caller package root (different path): ${packageRoot}`);
3168
- }
3169
- return packageRoot;
3170
- }
3171
- }
3172
- } else {
3173
- if (process$1.env.NODE_ENV === "development") {
3174
- relinka("log", `Using caller package root (no CWD package.json): ${packageRoot}`);
3175
- }
3176
- return packageRoot;
3177
- }
3178
- break;
3179
- }
3180
- } catch {
3181
- }
3182
- currentDir2 = dirname(currentDir2);
3183
- }
3184
- const resolvedFileDir = resolve(fileDir);
3185
- const resolvedCwd = resolve(cwd);
3186
- if (resolvedFileDir !== resolvedCwd && !resolvedFileDir.startsWith(resolvedCwd)) {
3187
- if (process$1.env.NODE_ENV === "development") {
3188
- relinka("log", `Using caller directory (different from CWD): ${fileDir}`);
3189
- }
3190
- return packageRoot || fileDir;
3191
- }
3192
- } catch {
3193
- continue;
3194
- }
3195
- }
3366
+ const NEGATIVE_NUMBER_REGEX = /^[0-9]+(\.[0-9]+)?$/;
3367
+ function isAsciiLetter(ch) {
3368
+ const code = ch.charCodeAt(0);
3369
+ return code >= 65 && code <= 90 || code >= 97 && code <= 122;
3370
+ }
3371
+ function reliArgParser(argv, opts = {}) {
3372
+ const context = createParserContext(opts);
3373
+ prePopulateDefaults(context);
3374
+ let i = 0;
3375
+ const argvLength = argv.length;
3376
+ while (i < argvLength) {
3377
+ const arg = argv[i];
3378
+ if (!arg) {
3379
+ i++;
3380
+ continue;
3196
3381
  }
3197
- }
3198
- for (const line of stack) {
3199
- const match = /\((.*):(\d+):(\d+)\)/.exec(line) || /at (.*):(\d+):(\d+)/.exec(line);
3200
- if (match?.[1]) {
3201
- const filePath = match[1];
3202
- if (filePath.includes("node_modules")) {
3203
- try {
3204
- const nodeModulesMatch = filePath.match(/(.+\/node_modules\/[^\/]+)/);
3205
- if (nodeModulesMatch?.[1]) {
3206
- const packageDir = nodeModulesMatch[1];
3207
- const packageJsonPath = resolve(packageDir, "package.json");
3208
- if (await fs.pathExists(packageJsonPath)) {
3209
- if (process$1.env.NODE_ENV === "development") {
3210
- relinka("log", `Found command package in node_modules: ${packageDir}`);
3211
- }
3212
- return packageDir;
3213
- }
3214
- }
3215
- } catch {
3216
- continue;
3217
- }
3218
- }
3382
+ if (arg === "--") {
3383
+ context.result._.push(...argv.slice(i + 1));
3384
+ break;
3219
3385
  }
3220
- }
3221
- let currentDir = cwd;
3222
- while (currentDir !== dirname(currentDir)) {
3223
- try {
3224
- const packageJsonPath = resolve(currentDir, "package.json");
3225
- if (await fs.pathExists(packageJsonPath)) {
3226
- if (process$1.env.NODE_ENV === "development") {
3227
- relinka("log", `Found package.json at: ${currentDir}`);
3228
- }
3229
- return currentDir;
3386
+ if (context.allowNegativeNumbers && isNegativeNumber(arg)) {
3387
+ if (context.stopEarly) {
3388
+ context.result._.push(...argv.slice(i));
3389
+ break;
3390
+ } else {
3391
+ context.result._.push(arg);
3392
+ i++;
3393
+ continue;
3230
3394
  }
3231
- } catch {
3232
3395
  }
3233
- currentDir = dirname(currentDir);
3234
- }
3235
- if (process$1.env.NODE_ENV === "development") {
3236
- relinka("log", `No suitable caller found, using cwd: ${cwd}`);
3237
- }
3238
- return process$1.cwd();
3239
- };
3240
- const getNodeModulesPackageDirsFromStack = async () => {
3241
- const stack = new Error().stack?.split("\n") ?? [];
3242
- const packageDirs = /* @__PURE__ */ new Set();
3243
- for (const line of stack) {
3244
- const match = /\((.*):(\d+):(\d+)\)/.exec(line) || /at (.*):(\d+):(\d+)/.exec(line);
3245
- if (!match?.[1]) continue;
3246
- const filePath = match[1];
3247
- if (!filePath.includes("node_modules")) continue;
3248
- try {
3249
- const nodeModulesMatch = filePath.match(/(.+\\node_modules\\(?:@[^\\/]+\\)?[^\\/]+)|(.+\/node_modules\/(?:@[^\/]+\/)?[^\/]+)/);
3250
- const packageDir = (nodeModulesMatch?.[1] || nodeModulesMatch?.[2])?.trim();
3251
- if (!packageDir) continue;
3252
- const packageJsonPath = resolve(packageDir, "package.json");
3253
- if (await fs.pathExists(packageJsonPath)) {
3254
- packageDirs.add(packageDir);
3255
- }
3256
- } catch {
3396
+ if (shouldHandleNegatedBoolean(arg, context)) {
3397
+ handleNegatedBooleanFlag(arg, context);
3398
+ i++;
3399
+ continue;
3257
3400
  }
3258
- }
3259
- return Array.from(packageDirs);
3260
- };
3261
- const tryLoadCommand = async (path) => {
3262
- if (!await fs.pathExists(path)) return null;
3263
- try {
3264
- const cmd = await jiti.import(path, { default: true });
3265
- return cmd;
3266
- } catch {
3267
- relinka("log", `Failed to load ${path} as a command file`);
3268
- return null;
3269
- }
3270
- };
3271
- const generateCandidatePaths = async (resolvedPath) => {
3272
- if (!await fs.pathExists(resolvedPath)) {
3273
- return COMMAND_EXTENSIONS.map((ext) => `${resolvedPath}${ext}`);
3274
- }
3275
- if (await fs.isDirectory(resolvedPath)) {
3276
- return COMMAND_FILENAMES.map((filename) => resolve(resolvedPath, filename));
3277
- }
3278
- return [resolvedPath];
3279
- };
3280
- const generateAlternativePaths = async (cmdPath, callerDir) => {
3281
- const normalizedCmdPath = cmdPath.replace(/^\.\//, "");
3282
- const paths = [];
3283
- const commonCommandLocations = [
3284
- // Direct command file
3285
- resolve(callerDir, `${normalizedCmdPath}.ts`),
3286
- resolve(callerDir, `${normalizedCmdPath}.js`),
3287
- // Command in cmd subdirectory
3288
- resolve(callerDir, normalizedCmdPath, "cmd.ts"),
3289
- resolve(callerDir, normalizedCmdPath, "cmd.js"),
3290
- // Command in app subdirectory
3291
- resolve(callerDir, "app", normalizedCmdPath, "cmd.ts"),
3292
- resolve(callerDir, "app", normalizedCmdPath, "cmd.js"),
3293
- // Command in src subdirectory
3294
- resolve(callerDir, "src", normalizedCmdPath, "cmd.ts"),
3295
- resolve(callerDir, "src", normalizedCmdPath, "cmd.js"),
3296
- // Command in src/app subdirectory
3297
- resolve(callerDir, "src", "app", normalizedCmdPath, "cmd.ts"),
3298
- resolve(callerDir, "src", "app", normalizedCmdPath, "cmd.js"),
3299
- // Command in src-ts subdirectory
3300
- resolve(callerDir, "src-ts", normalizedCmdPath, "cmd.ts"),
3301
- resolve(callerDir, "src-ts", normalizedCmdPath, "cmd.js"),
3302
- // Command in src-ts/app subdirectory (for dler-like structures)
3303
- resolve(callerDir, "src-ts", "app", normalizedCmdPath, "cmd.ts"),
3304
- resolve(callerDir, "src-ts", "app", normalizedCmdPath, "cmd.js"),
3305
- // Command in lib subdirectory
3306
- resolve(callerDir, "lib", normalizedCmdPath, "cmd.ts"),
3307
- resolve(callerDir, "lib", normalizedCmdPath, "cmd.js"),
3308
- // Command in lib/app subdirectory
3309
- resolve(callerDir, "lib", "app", normalizedCmdPath, "cmd.ts"),
3310
- resolve(callerDir, "lib", "app", normalizedCmdPath, "cmd.js"),
3311
- // Command in dist subdirectory (compiled)
3312
- resolve(callerDir, "dist", normalizedCmdPath, "cmd.js"),
3313
- resolve(callerDir, "dist", "app", normalizedCmdPath, "cmd.js"),
3314
- // Command in bin subdirectory
3315
- resolve(callerDir, "bin", normalizedCmdPath, "cmd.ts"),
3316
- resolve(callerDir, "bin", normalizedCmdPath, "cmd.js"),
3317
- // Command in bin/app subdirectory (common for CLI tools)
3318
- resolve(callerDir, "bin", "app", normalizedCmdPath, "cmd.ts"),
3319
- resolve(callerDir, "bin", "app", normalizedCmdPath, "cmd.js"),
3320
- // Command in commands subdirectory
3321
- resolve(callerDir, "commands", normalizedCmdPath, "cmd.ts"),
3322
- resolve(callerDir, "commands", normalizedCmdPath, "cmd.js"),
3323
- // Command in cli subdirectory
3324
- resolve(callerDir, "cli", normalizedCmdPath, "cmd.ts"),
3325
- resolve(callerDir, "cli", normalizedCmdPath, "cmd.js"),
3326
- // Command in cli/commands subdirectory
3327
- resolve(callerDir, "cli", "commands", normalizedCmdPath, "cmd.ts"),
3328
- resolve(callerDir, "cli", "commands", normalizedCmdPath, "cmd.js"),
3329
- // Command in tools subdirectory
3330
- resolve(callerDir, "tools", normalizedCmdPath, "cmd.ts"),
3331
- resolve(callerDir, "tools", normalizedCmdPath, "cmd.js"),
3332
- // Command in scripts subdirectory
3333
- resolve(callerDir, "scripts", normalizedCmdPath, "cmd.ts"),
3334
- resolve(callerDir, "scripts", normalizedCmdPath, "cmd.js")
3335
- ];
3336
- for (const path of commonCommandLocations) {
3337
- if (await fs.pathExists(path)) {
3338
- paths.push(path);
3401
+ if (arg.length > 2 && arg[0] === "-" && arg[1] === "-") {
3402
+ i = handleLongFlag(argv, i, context);
3403
+ continue;
3404
+ }
3405
+ if (arg.length > 1 && arg[0] === "-" && arg[1] !== "-") {
3406
+ i = handleShortFlags(argv, i, context);
3407
+ continue;
3408
+ }
3409
+ if (context.stopEarly) {
3410
+ context.result._.push(...argv.slice(i));
3411
+ break;
3339
3412
  }
3413
+ context.result._.push(arg);
3414
+ i++;
3340
3415
  }
3341
- return paths;
3342
- };
3343
- const createCommandNotFoundError = (cmdPath, searchedPaths) => new Error(
3344
- `No command file found for "${cmdPath}". Expected to find either:
3345
- - A valid command file at the specified path
3346
- - A directory containing cmd.ts or cmd.js
3347
- - A file path that can be resolved with .ts or .js extension
3348
-
3349
- Searched paths: ${searchedPaths.join(", ")}
3350
- Please ensure one of these exists and exports a default command.`
3351
- );
3352
- const createLoadError = (cmdPath, originalError) => new Error(
3353
- `Failed to load command from "${cmdPath}"
3354
-
3355
- For developers: Ensure the command file:
3356
- - Exists and is accessible
3357
- - Exports a default command (e.g., export default defineCommand({...}))
3358
- - Is a valid TypeScript/JavaScript module
3359
-
3360
- Original error: ${originalError instanceof Error ? originalError.message : String(originalError)}`
3361
- );
3362
- async function loadCommand(cmdPath) {
3363
- try {
3364
- const callerDir = await getCallerDirectory();
3365
- const normalizedPath = cmdPath.replace(/^\.\//, "");
3366
- const resolvedPath = resolve(callerDir, normalizedPath);
3367
- if (process$1.env.NODE_ENV === "development") {
3368
- relinka("log", `Loading command: ${cmdPath}`);
3369
- relinka("log", `Caller directory: ${callerDir}`);
3370
- relinka("log", `Normalized path: ${normalizedPath}`);
3371
- relinka("log", `Resolved path: ${resolvedPath}`);
3372
- }
3373
- const searchedPaths = [];
3374
- const baseDirs = [callerDir];
3375
- const stackPackageDirs = await getNodeModulesPackageDirsFromStack();
3376
- for (const dir of stackPackageDirs) {
3377
- if (!baseDirs.includes(dir)) baseDirs.push(dir);
3378
- }
3379
- for (const baseDir of baseDirs) {
3380
- const alternativePaths = await generateAlternativePaths(cmdPath, baseDir);
3381
- if (process$1.env.NODE_ENV === "development") {
3382
- relinka("log", `Trying alternative paths in base ${baseDir}: ${alternativePaths.join(", ")}`);
3383
- }
3384
- searchedPaths.push(...alternativePaths);
3385
- for (const path of alternativePaths) {
3386
- const command = await tryLoadCommand(path);
3387
- if (command) {
3388
- if (process$1.env.NODE_ENV === "development") {
3389
- relinka("log", `Successfully loaded command from alternative path: ${path}`);
3390
- }
3391
- return command;
3416
+ return context.result;
3417
+ }
3418
+ function createParserContext(opts) {
3419
+ const booleanFlags = new Set(opts.boolean || []);
3420
+ const arrayFlags = new Set(opts.array || []);
3421
+ const stringFlags = new Set(opts.string || []);
3422
+ const aliasMap = buildAliasMap(opts.alias || {});
3423
+ const result = { _: [] };
3424
+ return {
3425
+ result,
3426
+ booleanFlags,
3427
+ arrayFlags,
3428
+ stringFlags,
3429
+ aliasMap,
3430
+ options: opts,
3431
+ stopEarlyTriggered: false,
3432
+ // Cache frequently accessed options for performance
3433
+ allowNegativeNumbers: opts.allowNegativeNumbers !== false,
3434
+ negatedBoolean: opts.negatedBoolean !== false,
3435
+ parseNumbers: opts.parseNumbers || false,
3436
+ stopEarly: opts.stopEarly || false,
3437
+ warnOnUnknown: opts.warnOnUnknown || false,
3438
+ strict: opts.strict || false
3439
+ };
3440
+ }
3441
+ function prePopulateDefaults(context) {
3442
+ const { defaults = {} } = context.options;
3443
+ for (const [key, val] of Object.entries(defaults)) {
3444
+ context.result[key] = val;
3445
+ }
3446
+ }
3447
+ function buildAliasMap(aliasObj) {
3448
+ const map = /* @__PURE__ */ new Map();
3449
+ for (const [key, value] of Object.entries(aliasObj)) {
3450
+ if (Array.isArray(value)) {
3451
+ const canonical = value[0];
3452
+ if (canonical) {
3453
+ map.set(key, canonical);
3454
+ for (const alias of value) {
3455
+ map.set(alias, canonical);
3392
3456
  }
3393
3457
  }
3458
+ } else {
3459
+ map.set(key, value);
3460
+ map.set(value, value);
3461
+ }
3462
+ }
3463
+ return map;
3464
+ }
3465
+ function isNegativeNumber(arg) {
3466
+ if (arg.length < 2 || arg[0] !== "-") return false;
3467
+ if (arg[1] === "-") return false;
3468
+ return NEGATIVE_NUMBER_REGEX.test(arg.slice(1));
3469
+ }
3470
+ function shouldHandleNegatedBoolean(arg, context) {
3471
+ return context.negatedBoolean && arg.length > 5 && arg[0] === "-" && arg[1] === "-" && arg[2] === "n" && arg[3] === "o" && arg[4] === "-";
3472
+ }
3473
+ function handleNegatedBooleanFlag(arg, context) {
3474
+ const flagName = arg.slice(5);
3475
+ const resolvedName = resolveFlagName(flagName, context);
3476
+ if (context.booleanFlags.has(resolvedName)) {
3477
+ setFlagValue(resolvedName, false, context);
3478
+ } else {
3479
+ handleUnknownFlag(resolvedName, context);
3480
+ }
3481
+ }
3482
+ function handleLongFlag(argv, index, context) {
3483
+ const arg = argv[index];
3484
+ if (arg === void 0) {
3485
+ return index + 1;
3486
+ }
3487
+ const flagBody = arg.slice(2);
3488
+ const eqIndex = flagBody.indexOf("=");
3489
+ let rawFlagName = flagBody;
3490
+ let value = true;
3491
+ let nextIndex = index;
3492
+ if (eqIndex !== -1) {
3493
+ rawFlagName = flagBody.slice(0, eqIndex);
3494
+ value = flagBody.slice(eqIndex + 1);
3495
+ } else {
3496
+ const nextArg = argv[index + 1];
3497
+ if (nextArg && nextArg.length > 0 && nextArg[0] !== "-") {
3498
+ value = nextArg;
3499
+ nextIndex++;
3500
+ }
3501
+ }
3502
+ const flagName = resolveFlagName(rawFlagName, context);
3503
+ const parsedValue = parseValue(value, flagName, context);
3504
+ setFlagValue(flagName, parsedValue, context);
3505
+ validateOrWarn(flagName, context);
3506
+ return nextIndex + 1;
3507
+ }
3508
+ function handleShortFlags(argv, index, context) {
3509
+ const arg = argv[index];
3510
+ if (arg === void 0) {
3511
+ return index + 1;
3512
+ }
3513
+ const shortFlags = arg.slice(1);
3514
+ const booleanFlags = context.booleanFlags;
3515
+ const aliasMap = context.aliasMap;
3516
+ const shortFlagsLength = shortFlags.length;
3517
+ let j = 0;
3518
+ while (j < shortFlagsLength) {
3519
+ const flagChar = shortFlags[j];
3520
+ if (!flagChar) {
3521
+ j++;
3522
+ continue;
3394
3523
  }
3395
- const looksLikeExplicitPath = /[\\\/]|\.ts$|\.js$/.test(normalizedPath);
3396
- if (looksLikeExplicitPath) {
3397
- const candidatePaths = await generateCandidatePaths(resolvedPath);
3398
- if (process$1.env.NODE_ENV === "development") {
3399
- relinka("log", `Candidate paths: ${candidatePaths.join(", ")}`);
3524
+ const resolvedName = aliasMap.get(flagChar) || flagChar;
3525
+ const nextChar = shortFlags[j + 1];
3526
+ if (booleanFlags.has(resolvedName)) {
3527
+ if (nextChar === "=") {
3528
+ const attachedValue = shortFlags.slice(j + 2);
3529
+ const parsed = parseValue(attachedValue, resolvedName, context);
3530
+ setFlagValue(resolvedName, parsed, context);
3531
+ j = shortFlagsLength;
3532
+ } else if (nextChar && !isAsciiLetter(nextChar)) {
3533
+ const attachedValue = shortFlags.slice(j + 1);
3534
+ const parsed = parseValue(attachedValue, resolvedName, context);
3535
+ setFlagValue(resolvedName, parsed, context);
3536
+ j = shortFlagsLength;
3537
+ } else {
3538
+ setFlagValue(resolvedName, true, context);
3539
+ j++;
3400
3540
  }
3401
- searchedPaths.push(...candidatePaths);
3402
- for (const path of candidatePaths) {
3403
- const command = await tryLoadCommand(path);
3404
- if (command) {
3405
- if (process$1.env.NODE_ENV === "development") {
3406
- relinka("log", `Successfully loaded command from: ${path}`);
3541
+ } else {
3542
+ const remainder = shortFlags.slice(j + 1);
3543
+ if (remainder.startsWith("=")) {
3544
+ const val = remainder.slice(1);
3545
+ const parsedVal = parseValue(val, resolvedName, context);
3546
+ setFlagValue(resolvedName, parsedVal, context);
3547
+ validateOrWarn(resolvedName, context);
3548
+ j = shortFlagsLength;
3549
+ } else if (remainder.length > 0) {
3550
+ const parsedVal = parseValue(remainder, resolvedName, context);
3551
+ setFlagValue(resolvedName, parsedVal, context);
3552
+ validateOrWarn(resolvedName, context);
3553
+ j = shortFlagsLength;
3554
+ } else {
3555
+ const nextArgIndex = index + 1;
3556
+ if (nextArgIndex < argv.length) {
3557
+ const nextArg = argv[nextArgIndex];
3558
+ if (nextArg && nextArg.length > 0 && nextArg[0] !== "-") {
3559
+ const parsedVal = parseValue(nextArg, resolvedName, context);
3560
+ setFlagValue(resolvedName, parsedVal, context);
3561
+ validateOrWarn(resolvedName, context);
3562
+ return index + 2;
3407
3563
  }
3408
- return command;
3409
3564
  }
3565
+ setFlagValue(resolvedName, true, context);
3566
+ validateOrWarn(resolvedName, context);
3567
+ break;
3410
3568
  }
3411
3569
  }
3412
- throw createCommandNotFoundError(cmdPath, searchedPaths);
3413
- } catch (error) {
3414
- if (error instanceof Error && error.message.includes("No command file found")) {
3415
- throw error;
3416
- }
3417
- relinka("error", `Failed to load command from ${cmdPath}:`, error);
3418
- throw createLoadError(cmdPath, error);
3419
3570
  }
3571
+ return index + 1;
3420
3572
  }
3421
-
3422
- function addCompletions(program, completion) {
3423
- const commandSymbol = Symbol("command");
3424
- const cTree = {};
3425
- function addCommandCompletions(command, cTreeNode) {
3426
- command.commands.forEach((c) => {
3427
- const node = cTreeNode[c.name()] ||= {};
3428
- Object.defineProperty(node, commandSymbol, {
3429
- value: c,
3430
- enumerable: false
3431
- });
3432
- addCommandCompletions(c, node);
3433
- });
3434
- }
3435
- addCommandCompletions(program, cTree);
3436
- completion.on("complete", (fragment, params) => {
3437
- const segments = params.line.split(/ +/).slice(1, params.fragment);
3438
- const last = segments.at(-1);
3439
- let node = cTree;
3440
- const existingFlags = /* @__PURE__ */ new Set();
3441
- for (const segment of segments) {
3442
- if (segment.startsWith("-")) {
3443
- existingFlags.add(segment);
3444
- continue;
3445
- }
3446
- if (existingFlags.size > 0) continue;
3447
- node = node[segment];
3448
- if (!node) return;
3449
- }
3450
- const correspondingCommand = node[commandSymbol];
3451
- if (correspondingCommand?.options?.length) {
3452
- const suggestions = [];
3453
- for (const o of correspondingCommand.options) {
3454
- if (last === o.long || last === o.short) {
3455
- if (o.argChoices) suggestions.push(...o.argChoices);
3456
- if (!o.isBoolean()) break;
3573
+ function resolveFlagName(rawName, context) {
3574
+ return context.aliasMap.get(rawName) || rawName;
3575
+ }
3576
+ function setFlagValue(flagName, value, context) {
3577
+ if (context.arrayFlags.has(flagName)) {
3578
+ if (!Array.isArray(context.result[flagName])) {
3579
+ context.result[flagName] = [];
3580
+ }
3581
+ context.result[flagName].push(value);
3582
+ } else {
3583
+ context.result[flagName] = value;
3584
+ }
3585
+ }
3586
+ function parseValue(val, flagName, context) {
3587
+ if (typeof val === "boolean") {
3588
+ return val;
3589
+ }
3590
+ const strVal = String(val);
3591
+ if (context.stringFlags.has(flagName)) {
3592
+ return strVal;
3593
+ }
3594
+ if (context.booleanFlags.has(flagName)) {
3595
+ if (strVal === "true") return true;
3596
+ if (strVal === "false") return false;
3597
+ return strVal;
3598
+ }
3599
+ if (context.parseNumbers && strVal.length > 0) {
3600
+ const firstChar = strVal.charAt(0);
3601
+ const lastChar = strVal.charAt(strVal.length - 1);
3602
+ if (firstChar >= "0" && firstChar <= "9" || firstChar === "-" || firstChar === "+") {
3603
+ if (lastChar >= "0" && lastChar <= "9") {
3604
+ const maybeNum = Number(strVal);
3605
+ if (!Number.isNaN(maybeNum)) {
3606
+ return maybeNum;
3457
3607
  }
3458
- if (existingFlags.has(o.long)) continue;
3459
- if (existingFlags.has(o.short)) continue;
3460
- suggestions.push(o.long);
3461
3608
  }
3462
- return params.reply(suggestions);
3463
3609
  }
3464
- });
3465
- completion.tree(cTree).init();
3466
- }
3467
-
3468
- class CliValidationError extends Error {
3469
- }
3470
- class FailedToExitError extends Error {
3471
- exitCode;
3472
- constructor(message, { exitCode, cause }) {
3473
- const fullMessage = `${message}. The process was expected to exit with exit code ${exitCode} but did not. This may be because a custom \`process\` parameter was used. The exit reason is in the \`cause\` property.`;
3474
- super(fullMessage, { cause });
3475
- this.exitCode = exitCode;
3476
3610
  }
3611
+ return strVal;
3477
3612
  }
3478
-
3479
- const commandToJSON = (command) => {
3480
- const json = {};
3481
- const name = command.name();
3482
- if (name) json.name = name;
3483
- const version = command.version();
3484
- if (version) json.version = version;
3485
- const description = command.description();
3486
- if (description) json.description = description;
3487
- const usage = command.usage();
3488
- if (usage) json.usage = usage;
3489
- json.arguments = command.registeredArguments.map((arg) => {
3490
- const result = { name: arg.name() };
3491
- result.variadic = arg.variadic;
3492
- result.required = arg.required;
3493
- if (arg.description) result.description = arg.description;
3494
- if (arg.defaultValue) result.defaultValue = arg.defaultValue;
3495
- if (arg.defaultValueDescription) result.defaultValueDescription = arg.defaultValueDescription;
3496
- if (arg.argChoices) result.choices = arg.argChoices;
3497
- return result;
3498
- });
3499
- json.options = command.options.map((o) => {
3500
- const result = { name: o.name() };
3501
- result.required = o.required;
3502
- result.optional = o.optional;
3503
- result.negate = o.negate;
3504
- result.variadic = o.variadic;
3505
- if (o.flags) result.flags = o.flags;
3506
- if (o.short) result.short = o.short;
3507
- if (o.description) result.description = o.description;
3508
- if (o.argChoices) result.choices = o.argChoices;
3509
- const attributeName = o.attributeName();
3510
- if (attributeName) result.attributeName = attributeName;
3511
- if (o.defaultValue) result.defaultValue = o.defaultValue;
3512
- if (o.defaultValueDescription) result.defaultValueDescription = o.defaultValueDescription;
3513
- return result;
3514
- });
3515
- json.commands = command.commands.map((c) => commandToJSON(c));
3516
- return json;
3517
- };
3518
-
3519
- const capitaliseFromCamelCase = (camel) => {
3520
- const parts = camel.split(/(?=[A-Z])/);
3521
- return capitalise(parts.map((p) => p.toLowerCase()).join(" "));
3522
- };
3523
- const capitalise = (s) => s.slice(0, 1).toUpperCase() + s.slice(1);
3524
- const flattenedProperties = (sch) => {
3525
- if ("properties" in sch) {
3526
- return sch.properties;
3527
- }
3528
- if ("allOf" in sch) {
3529
- return Object.fromEntries(
3530
- sch.allOf.flatMap(
3531
- (subSchema) => Object.entries(flattenedProperties(subSchema))
3532
- )
3533
- );
3534
- }
3535
- if ("anyOf" in sch) {
3536
- const isExcluded = (v) => Object.keys(v).join(",") === "not";
3537
- const entries = sch.anyOf.flatMap((subSchema) => {
3538
- const flattened = flattenedProperties(subSchema);
3539
- const excluded = Object.entries(flattened).flatMap(([name, propSchema]) => {
3540
- return isExcluded(propSchema) ? [`--${name}`] : [];
3541
- });
3542
- return Object.entries(flattened).map(([k, v]) => {
3543
- if (!isExcluded(v) && excluded.length > 0) {
3544
- return [k, { ...v, "Do not use with": excluded }];
3545
- }
3546
- return [k, v];
3547
- });
3548
- });
3549
- return Object.fromEntries(
3550
- entries.sort((a, b) => {
3551
- const scores = [a, b].map(([_k, v]) => isExcluded(v) ? 0 : 1);
3552
- return scores[0] - scores[1];
3553
- })
3554
- );
3555
- }
3556
- return {};
3557
- };
3558
- const incompatiblePropertyPairs = (sch) => {
3559
- const isUnion = "anyOf" in sch;
3560
- if (!isUnion) return [];
3561
- const sets = sch.anyOf.map((subSchema) => {
3562
- const keys = Object.keys(flattenedProperties(subSchema));
3563
- return { keys, set: new Set(keys) };
3564
- });
3565
- const compatiblityEntries = sets.flatMap(({ keys }) => {
3566
- return keys.map((key) => {
3567
- return [
3568
- key,
3569
- new Set(sets.filter((other) => other.set.has(key)).flatMap((other) => other.keys))
3570
- ];
3571
- });
3572
- });
3573
- const allKeys = sets.flatMap(({ keys }) => keys);
3574
- return compatiblityEntries.flatMap(([key, compatibleWith]) => {
3575
- const incompatibleEntries = allKeys.filter((other) => key < other && !compatibleWith.has(other)).map((other) => [key, other]);
3576
- return incompatibleEntries;
3577
- });
3578
- };
3579
- const getDescription = (v, depth = 0) => {
3580
- if ("items" in v && v.items) {
3581
- const { items, ...rest } = v;
3582
- return [getDescription(items, 1), getDescription(rest), "array"].filter(Boolean).join(" ");
3583
- }
3584
- return Object.entries(v).filter(([k, vv]) => {
3585
- if (k === "default" || k === "additionalProperties" || k === "optional") return false;
3586
- if (k === "type" && typeof vv === "string") return depth > 0;
3587
- if (k.startsWith("$")) return false;
3588
- if (k === "maximum" && vv === Number.MAX_SAFE_INTEGER) return false;
3589
- if (depth <= 1 && k === "enum" && getEnumChoices(v)?.type === "string_enum") return false;
3590
- return true;
3591
- }).sort(([a], [b]) => {
3592
- const scores = [a, b].map((k) => k === "description" ? 0 : 1);
3593
- return scores[0] - scores[1];
3594
- }).map(([k, vv], i) => {
3595
- if (k === "type" && Array.isArray(vv)) return `type: ${vv.join(" or ")}`;
3596
- if (k === "description" && i === 0) return String(vv);
3597
- if (k === "properties") return "Object (json formatted)";
3598
- if (typeof vv === "object") return `${capitaliseFromCamelCase(k)}: ${JSON.stringify(vv)}`;
3599
- return `${capitaliseFromCamelCase(k)}: ${vv}`;
3600
- }).join("; ") || "";
3601
- };
3602
- const getSchemaTypes = (propertyValue) => {
3603
- const array = [];
3604
- if ("type" in propertyValue) {
3605
- array.push(...[propertyValue.type].flat());
3606
- }
3607
- if ("enum" in propertyValue && Array.isArray(propertyValue.enum)) {
3608
- array.push(...propertyValue.enum.flatMap((s) => typeof s));
3609
- }
3610
- if ("const" in propertyValue && propertyValue.const === null) {
3611
- array.push("null");
3612
- } else if ("const" in propertyValue) {
3613
- array.push(typeof propertyValue.const);
3614
- }
3615
- if ("oneOf" in propertyValue) {
3616
- array.push(...propertyValue.oneOf.flatMap(getSchemaTypes));
3613
+ function validateOrWarn(flagName, context) {
3614
+ const { unknown, defaults } = context.options;
3615
+ if (unknown) {
3616
+ if (!unknown(flagName)) {
3617
+ handleUnknownFlag(flagName, context);
3618
+ }
3619
+ return;
3617
3620
  }
3618
- if ("anyOf" in propertyValue) {
3619
- array.push(...propertyValue.anyOf.flatMap(getSchemaTypes));
3621
+ if (context.booleanFlags.has(flagName) || context.arrayFlags.has(flagName) || context.stringFlags.has(flagName) || context.aliasMap.has(flagName)) {
3622
+ return;
3620
3623
  }
3621
- return [...new Set(array)];
3622
- };
3623
- const getEnumChoices = (propertyValue) => {
3624
- if (!propertyValue) return null;
3625
- if (!("enum" in propertyValue && Array.isArray(propertyValue.enum))) {
3626
- if ("anyOf" in propertyValue && propertyValue.anyOf?.every((subSchema) => {
3627
- if (subSchema && "const" in subSchema && Object.keys(subSchema).length === 1 && typeof subSchema.const === "string") {
3628
- return true;
3629
- }
3630
- return false;
3631
- })) {
3632
- return {
3633
- type: "string_enum",
3634
- choices: propertyValue.anyOf.map((subSchema) => subSchema.const)
3635
- };
3636
- }
3637
- if ("anyOf" in propertyValue && propertyValue.anyOf?.every((subSchema) => {
3638
- if (subSchema && "const" in subSchema && Object.keys(subSchema).length === 1 && typeof subSchema.const === "number") {
3639
- return true;
3640
- }
3641
- return false;
3642
- })) {
3643
- return {
3644
- type: "number_enum",
3645
- choices: propertyValue.anyOf.map((subSchema) => subSchema.const)
3646
- };
3647
- }
3648
- return null;
3624
+ if (defaults && Object.hasOwn(defaults, flagName)) {
3625
+ return;
3649
3626
  }
3650
- if (propertyValue.enum.every((s) => typeof s === "string")) {
3651
- return {
3652
- type: "string_enum",
3653
- choices: propertyValue.enum
3654
- };
3627
+ handleUnknownFlag(flagName, context);
3628
+ }
3629
+ function handleUnknownFlag(flagName, context) {
3630
+ if (context.strict) {
3631
+ throw new Error(`Unknown flag: --${flagName}`);
3655
3632
  }
3656
- if (propertyValue.enum.every((s) => typeof s === "number")) {
3657
- return {
3658
- type: "number_enum",
3659
- choices: propertyValue.enum
3660
- };
3633
+ if (context.warnOnUnknown) {
3634
+ console.warn(`Unknown flag: --${flagName}`);
3661
3635
  }
3662
- return null;
3663
- };
3636
+ }
3664
3637
 
3665
- const lineByLineLogger = getLoggerTransformer((log) => {
3666
- const wrapper = (args, depth) => {
3667
- if (args.length === 1 && Array.isArray(args[0]) && depth === 0) {
3668
- args[0].forEach((item) => wrapper([item], 1));
3669
- } else if (args.every(isPrimitive)) {
3670
- log(...args);
3671
- } else if (args.length === 1) {
3672
- log(JSON.stringify(args[0], null, 2));
3673
- } else {
3674
- log(JSON.stringify(args, null, 2));
3638
+ async function callCmd(command, input, options = {}) {
3639
+ const { autoExit = false, debug = false, useLifecycleHooks = true, parserOptions = {} } = options;
3640
+ const debugLog = (...args) => {
3641
+ if (debug) {
3642
+ relinka("log", "[callCmd DEBUG]", ...args);
3675
3643
  }
3676
3644
  };
3677
- return (...args) => wrapper(args, 0);
3678
- });
3679
- const isPrimitive = (value) => {
3680
- const type = typeof value;
3681
- return type === "string" || type === "number" || type === "boolean";
3682
- };
3683
- function getLoggerTransformer(transform) {
3684
- return (logger) => {
3685
- const info = logger.info && transform(logger.info);
3686
- const error = logger.error && transform(logger.error);
3687
- return { info, error };
3688
- };
3689
- }
3690
- const lineByLineConsoleLogger = lineByLineLogger(console);
3691
-
3692
- function toJsonSchema(input, dependencies) {
3645
+ debugLog("Calling command with input:", input);
3646
+ debugLog("Command meta:", command.meta);
3693
3647
  try {
3694
- const jsonSchemaConverters = getJsonSchemaConverters(dependencies);
3695
- const vendor = getVendor(input);
3696
- if (vendor && vendor in jsonSchemaConverters) {
3697
- const converter = jsonSchemaConverters[vendor];
3698
- const converted = converter(input);
3699
- return { success: true, value: converted };
3700
- }
3701
- return { success: false, error: "Schema not convertible to JSON schema" };
3702
- } catch (e) {
3703
- const message = e instanceof Error ? e.message : String(e);
3704
- return {
3705
- success: false,
3706
- error: `Failed to convert input to JSON Schema: ${message}`
3707
- };
3708
- }
3709
- }
3710
- function looksLikeJsonSchema(value) {
3711
- return typeof value === "object" && value !== null && ("type" in value && (typeof value.type === "string" || Array.isArray(value.type)) || "const" in value || "oneOf" in value || "anyOf" in value);
3712
- }
3713
- function parseProcedureInputs(inputs, dependencies) {
3714
- if (inputs.length === 0) {
3715
- return {
3716
- success: true,
3717
- value: {
3718
- positionalParameters: [],
3719
- optionsJsonSchema: {},
3720
- getPojoInput: () => ({})
3648
+ let ctx;
3649
+ if (Array.isArray(input)) {
3650
+ debugLog("Processing argv input:", input);
3651
+ ctx = await parseArgsFromArgv(command, input, parserOptions);
3652
+ } else {
3653
+ debugLog("Processing object input:", input);
3654
+ ctx = await createContextFromArgs(command, input);
3655
+ }
3656
+ debugLog("Created context:", ctx);
3657
+ if (useLifecycleHooks && command.onCmdInit) {
3658
+ debugLog("Calling onCmdInit hook");
3659
+ await command.onCmdInit(ctx);
3660
+ }
3661
+ if (command.run) {
3662
+ debugLog("Executing command run function");
3663
+ await command.run(ctx);
3664
+ } else {
3665
+ const error = "Command has no run function defined";
3666
+ debugLog(error);
3667
+ if (autoExit) {
3668
+ relinka("error", error);
3669
+ process$1.exit(1);
3721
3670
  }
3722
- };
3723
- }
3724
- const allJsonSchemaable = inputs.every((input) => looksJsonSchemaable(input));
3725
- if (!allJsonSchemaable) {
3726
- return {
3727
- success: false,
3728
- error: `Invalid input type ${inputs.map((s) => s?.constructor.name).join(", ")}, only inputs that can be converted to JSON Schema are supported`
3729
- };
3730
- }
3731
- if (inputs.length > 1) {
3732
- return parseMultiInputs(inputs, dependencies);
3733
- }
3734
- const mergedSchemaResult = toJsonSchema(inputs[0], dependencies);
3735
- if (!mergedSchemaResult.success) {
3736
- return {
3737
- success: false,
3738
- error: mergedSchemaResult.error
3739
- };
3671
+ throw new Error(error);
3672
+ }
3673
+ if (useLifecycleHooks && command.onCmdExit) {
3674
+ debugLog("Calling onCmdExit hook");
3675
+ await command.onCmdExit(ctx);
3676
+ }
3677
+ debugLog("Command execution completed successfully");
3678
+ return ctx;
3679
+ } catch (error) {
3680
+ debugLog("Error during command execution:", error);
3681
+ if (autoExit) {
3682
+ relinka("error", `Error while executing command: ${String(error)}`);
3683
+ process$1.exit(1);
3684
+ }
3685
+ throw error;
3740
3686
  }
3741
- const mergedSchema = mergedSchemaResult.value;
3742
- return handleMergedSchema(mergedSchema);
3743
3687
  }
3744
- function handleMergedSchema(mergedSchema) {
3745
- if (mergedSchema.additionalProperties) {
3746
- return {
3747
- success: false,
3748
- error: "Inputs with additional properties are not currently supported"
3749
- };
3750
- }
3751
- if (mergedSchema.type === "string") {
3752
- return {
3753
- success: true,
3754
- value: {
3755
- positionalParameters: [
3756
- {
3757
- type: "string",
3758
- array: false,
3759
- description: mergedSchema.description || "",
3760
- name: mergedSchema.title || "string",
3761
- required: !isOptional(mergedSchema)
3762
- }
3763
- ],
3764
- optionsJsonSchema: {},
3765
- getPojoInput: (argv) => argv.positionalValues[0]
3766
- }
3767
- };
3768
- }
3769
- if (acceptedPrimitiveTypes(mergedSchema).length > 0) {
3770
- return parsePrimitiveInput(mergedSchema);
3771
- }
3772
- if (isTuple(mergedSchema)) {
3773
- return parseTupleInput(mergedSchema);
3774
- }
3775
- if (mergedSchema.type === "array") {
3776
- return parseArrayInput(mergedSchema);
3777
- }
3778
- if (mergedSchema.anyOf) {
3779
- const allObjects = mergedSchema.anyOf.every((sub) => acceptsObject(toRoughJsonSchema7(sub)));
3780
- if (allObjects) {
3781
- return {
3782
- success: true,
3783
- value: {
3784
- positionalParameters: [],
3785
- optionsJsonSchema: mergedSchema,
3786
- getPojoInput: (argv) => argv.options
3787
- }
3788
- };
3789
- }
3790
- if (mergedSchema.anyOf.length === 2 && JSON.stringify(mergedSchema.anyOf[0]) === '{"not":{}}') {
3791
- return handleMergedSchema(mergedSchema.anyOf[1]);
3792
- }
3793
- }
3794
- if (mergedSchema.type !== "object") {
3795
- return {
3796
- success: false,
3797
- error: `Invalid input type ${inspect(mergedSchema, { depth: 2, breakLength: Number.POSITIVE_INFINITY })}, expected object or tuple.`
3798
- };
3799
- }
3800
- return {
3801
- success: true,
3802
- value: {
3803
- positionalParameters: [],
3804
- optionsJsonSchema: mergedSchema,
3805
- getPojoInput: (argv) => argv.options
3806
- }
3807
- };
3808
- }
3809
- function isOptional(schema) {
3810
- if (schema && typeof schema === "object" && "optional" in schema) return schema.optional === true;
3811
- const anyOf = schemaDefPropValue(schema, "anyOf");
3812
- if (anyOf?.length === 2 && JSON.stringify(anyOf[0]) === '{"not":{}}') return true;
3813
- if (anyOf?.some((sub) => isOptional(sub))) return true;
3814
- return false;
3815
- }
3816
- function parsePrimitiveInput(schema) {
3817
- const typeName = acceptedPrimitiveTypes(schema).join(" | ");
3818
- const name = (schema.title || schema.description || /\W/.test(typeName) ? "value" : typeName).replaceAll(/\s+/g, "_");
3819
- return {
3820
- success: true,
3821
- value: {
3822
- positionalParameters: [
3823
- {
3824
- name,
3825
- array: false,
3826
- description: schema.description || "",
3827
- required: !isOptional(schema),
3828
- type: typeName
3829
- }
3830
- ],
3831
- optionsJsonSchema: {},
3832
- getPojoInput: (argv) => convertPositional(schema, argv.positionalValues[0])
3833
- }
3834
- };
3835
- }
3836
- const schemaDefPropValue = (schema, prop) => {
3837
- if (schema && typeof schema === "object" && prop in schema) return schema[prop];
3838
- return;
3839
- };
3840
- const primitiveCandidateTypes = ["string", "number", "boolean", "integer"];
3841
- function acceptedPrimitiveTypes(schema) {
3842
- let constVals = [
3843
- toRoughJsonSchema7(schema).const,
3844
- toRoughJsonSchema7(schema).enum
3845
- ].flat().filter(Boolean).map((s) => typeof s);
3846
- if (constVals.length === 0) constVals = void 0;
3847
- const typeList = constVals || schemaDefPropValue(schema, "type") || schemaDefPropValue(schema, "oneOf")?.flatMap((s) => acceptedPrimitiveTypes(s)) || schemaDefPropValue(schema, "anyOf")?.flatMap((s) => acceptedPrimitiveTypes(s));
3848
- const acceptedJsonSchemaTypes = new Set([typeList].flat().filter(Boolean));
3849
- return primitiveCandidateTypes.filter((c) => acceptedJsonSchemaTypes.has(c));
3850
- }
3851
- function parseMultiInputs(inputs, dependencies) {
3852
- const parsedIndividually = inputs.map((input) => parseProcedureInputs([input], dependencies));
3853
- const failures = parsedIndividually.flatMap((p) => p.success ? [] : [p.error]);
3854
- if (failures.length > 0) {
3855
- return { success: false, error: failures.join("\n") };
3856
- }
3857
- const allObjects = parsedIndividually.every(
3858
- (p) => p.success && p.value.positionalParameters.length === 0
3688
+ async function parseArgsFromArgv(command, argv, parserOptions) {
3689
+ const booleanKeys = Object.keys(command.args || {}).filter(
3690
+ (k) => command.args?.[k]?.type === "boolean"
3859
3691
  );
3860
- if (!allObjects) {
3861
- return {
3862
- success: false,
3863
- error: `Can't use positional parameters with multi-input type.`
3864
- };
3865
- }
3866
- return {
3867
- success: true,
3868
- value: {
3869
- positionalParameters: [],
3870
- optionsJsonSchema: {
3871
- allOf: parsedIndividually.map((p) => {
3872
- const successful = p;
3873
- const optionsSchema = successful.value.optionsJsonSchema;
3874
- if ("additionalProperties" in optionsSchema && optionsSchema.additionalProperties === false) {
3875
- const { additionalProperties, ...rest } = optionsSchema;
3876
- return rest;
3877
- }
3878
- return optionsSchema;
3879
- })
3880
- },
3881
- getPojoInput: (argv) => argv.options
3882
- }
3883
- };
3884
- }
3885
- function isNullable(schema) {
3886
- if (Array.isArray(schema.type) && schema.type.includes("null")) return true;
3887
- if (schema.type === "null") return true;
3888
- if ((schema.anyOf || schema.oneOf)?.some((sub) => isNullable(toRoughJsonSchema7(sub))))
3889
- return true;
3890
- if (schema.const === null) return true;
3891
- return false;
3892
- }
3893
- const tupleItemsSchemas = (schema) => {
3894
- if (!schema || typeof schema !== "object") return;
3895
- if (Array.isArray(schema.items)) return schema.items;
3896
- if ("prefixItems" in schema && Array.isArray(schema.prefixItems))
3897
- return schema.prefixItems;
3898
- return;
3899
- };
3900
- function isTuple(schema) {
3901
- return Array.isArray(tupleItemsSchemas(schema));
3902
- }
3903
- function parseArrayInput(array) {
3904
- if (looksLikeJsonSchema(array.items) && isNullable(array.items)) {
3905
- return {
3906
- success: false,
3907
- error: `Invalid input type Array<${getSchemaTypes(array.items).join(" | ")}>. Nullable arrays are not supported.`
3908
- };
3909
- }
3910
- return {
3911
- success: true,
3912
- value: {
3913
- positionalParameters: [
3914
- {
3915
- name: parameterName(array, 1),
3916
- array: true,
3917
- description: array.description || "",
3918
- required: !isOptional(array),
3919
- type: "string"
3920
- }
3921
- ],
3922
- optionsJsonSchema: {},
3923
- getPojoInput: (argv) => argv.positionalValues.at(-1).map(
3924
- (s) => convertPositional(array.items, s)
3925
- )
3926
- }
3927
- };
3928
- }
3929
- function parseTupleInput(tuple) {
3930
- const items = tupleItemsSchemas(tuple);
3931
- if (!Array.isArray(items)) throw new Error(".items is not an array, is this really a tuple?");
3932
- const flagsSchemaIndex = items.findIndex((item) => {
3933
- if (acceptedPrimitiveTypes(item).length > 0) {
3934
- return false;
3935
- }
3936
- if (looksLikeArray(item) && acceptedPrimitiveTypes(item.items).length > 0) {
3937
- return false;
3938
- }
3939
- return true;
3940
- });
3941
- const types = `[${items.map((s) => schemaDefPropValue(s, "type")).join(", ")}]`;
3942
- if (flagsSchemaIndex > -1 && flagsSchemaIndex !== items.length - 1) {
3943
- return {
3944
- success: false,
3945
- error: `Invalid input type ${types}. Positional parameters must be strings, numbers or booleans.`
3946
- };
3947
- }
3948
- const flagsSchema = flagsSchemaIndex === -1 ? null : items[flagsSchemaIndex];
3949
- if (flagsSchema && !acceptsObject(flagsSchema)) {
3950
- return {
3951
- success: false,
3952
- error: `Invalid input type ${types}. The last type must accept object inputs.`
3953
- };
3954
- }
3955
- const positionalSchemas = flagsSchemaIndex === -1 ? items : items.slice(0, flagsSchemaIndex);
3956
- return {
3957
- success: true,
3958
- value: {
3959
- positionalParameters: positionalSchemas.map((schema, i) => ({
3960
- name: parameterName(schema, i + 1),
3961
- array: looksLikeArray(schema),
3962
- description: schemaDefPropValue(schema, "description") || "",
3963
- required: !isOptional(schema),
3964
- type: getSchemaTypes(toRoughJsonSchema7(schema)).join(" | ")
3965
- })),
3966
- optionsJsonSchema: flagsSchema && typeof flagsSchema === "object" ? flagsSchema : {},
3967
- getPojoInput: (commandArgs) => {
3968
- const inputs = commandArgs.positionalValues.map((v, i) => {
3969
- const correspondingSchema = positionalSchemas[i];
3970
- if (!correspondingSchema) {
3971
- throw new CliValidationError(`No schema found for position ${i}`);
3972
- }
3973
- if (looksLikeArray(correspondingSchema)) {
3974
- if (!Array.isArray(v)) {
3975
- throw new CliValidationError(`Expected array at position ${i}, got ${typeof v}`);
3976
- }
3977
- return v.map((s) => {
3978
- if (!correspondingSchema.items || Array.isArray(correspondingSchema.items)) return s;
3979
- return convertPositional(correspondingSchema.items, s);
3980
- });
3981
- }
3982
- if (typeof v !== "string" && v !== void 0) {
3983
- throw new CliValidationError(`Expected string at position ${i}, got ${typeof v}`);
3984
- }
3985
- return convertPositional(correspondingSchema, v);
3986
- });
3987
- if (flagsSchema) {
3988
- inputs.push(commandArgs.options);
3989
- }
3990
- return inputs;
3991
- }
3992
- }
3993
- };
3994
- }
3995
- const convertPositional = (schema, value) => {
3996
- let preprocessed;
3997
- const acceptedTypes = new Set(acceptedPrimitiveTypes(schema));
3998
- if (acceptedTypes.has("string")) {
3999
- preprocessed = value;
4000
- }
4001
- if (acceptedTypes.has("boolean")) {
4002
- if (value === "true") preprocessed = true;
4003
- else if (value === "false") preprocessed = false;
4004
- }
4005
- if (acceptedTypes.has("number")) {
4006
- const number = Number(value);
4007
- if (!Number.isNaN(number)) {
4008
- preprocessed = number;
4009
- }
4010
- }
4011
- if (acceptedTypes.has("integer")) {
4012
- const num = Number(value);
4013
- if (Number.isInteger(num)) {
4014
- preprocessed = num;
4015
- } else if (!Number.isNaN(num) && acceptedTypes === void 0) {
4016
- preprocessed = value;
4017
- }
4018
- }
4019
- if (preprocessed === void 0) {
4020
- return value;
4021
- }
4022
- return preprocessed;
4023
- };
4024
- const looksLikeArray = (schema) => {
4025
- return schemaDefPropValue(schema, "type") === "array";
4026
- };
4027
- const toRoughJsonSchema7 = (schema) => {
4028
- if (!schema || typeof schema !== "object") {
4029
- return {};
4030
- }
4031
- return schema;
4032
- };
4033
- const parameterName = (s, position) => {
4034
- if (looksLikeArray(s)) {
4035
- const items = toRoughJsonSchema7(s).items;
4036
- const elementName = parameterName(!items || Array.isArray(items) ? {} : items, position);
4037
- return `[${elementName.slice(1, -1)}...]`;
4038
- }
4039
- let name = schemaDefPropValue(s, "title") || schemaDefPropValue(s, "description") || `parameter_${position}`;
4040
- name = name.replaceAll(/\W+/g, " ").trim();
4041
- return isOptional(s) ? `[${name}]` : `<${name}>`;
4042
- };
4043
- const acceptsObject = (schema) => {
4044
- return (schema.type === "object" || schema.anyOf?.some((sub) => acceptsObject(toRoughJsonSchema7(sub)))) ?? false;
4045
- };
4046
- const getJsonSchemaConverters = (dependencies) => {
4047
- return {
4048
- zod: (input) => {
4049
- if (input._zod?.version?.major === 4) {
4050
- return zod4.toJSONSchema(input, {
4051
- // todo[zod@>=4.0.0] remove the line if https://github.com/colinhacks/zod/issues/4167 is resolved, or this comment if it's closed
4052
- io: "input",
4053
- // todo[zod@>=4.0.0] remove the override if https://github.com/colinhacks/zod/issues/4164 is resolved, or this comment if it's closed
4054
- unrepresentable: "any",
4055
- // todo[zod@>=4.0.0] remove the override if https://github.com/colinhacks/zod/issues/4164 is resolved, or this comment if it's closed
4056
- override: (ctx) => {
4057
- if (ctx.zodSchema?.constructor?.name === "ZodOptional") {
4058
- ctx.jsonSchema.optional = true;
4059
- }
4060
- }
4061
- });
4062
- }
4063
- return zodToJsonSchema(input);
4064
- },
4065
- arktype: (input) => {
4066
- const type = prepareArktypeType(input);
4067
- return type.toJsonSchema({
4068
- fallback: (ctx) => {
4069
- if (ctx.code === "unit" && ctx.unit === void 0) return { ...ctx.base, optional: true };
4070
- return ctx.base;
4071
- }
4072
- });
4073
- },
4074
- valibot: (input) => {
4075
- let valibotToJsonSchemaLib = dependencies["@valibot/to-json-schema"];
4076
- if (!valibotToJsonSchemaLib) {
4077
- try {
4078
- valibotToJsonSchemaLib = require("@valibot/to-json-schema");
4079
- } catch (e) {
4080
- throw new Error(
4081
- "@valibot/to-json-schema could not be found - try installing it and re-running",
4082
- { cause: e }
4083
- );
4084
- }
4085
- }
4086
- const valibotToJsonSchema = valibotToJsonSchemaLib?.toJsonSchema;
4087
- if (!valibotToJsonSchema) {
4088
- throw new Error(
4089
- `no 'toJsonSchema' function found in @valibot/to-json-schema - check you are using a supported version`
4090
- );
4091
- }
4092
- let v;
4093
- try {
4094
- v = require("valibot");
4095
- } catch {
4096
- return valibotToJsonSchema(input);
4097
- }
4098
- const parent = valibotToJsonSchema(
4099
- v.object({ child: input }),
4100
- {
4101
- errorMode: "ignore"
4102
- }
4103
- );
4104
- const child = parent.properties.child;
4105
- return parent.required?.length === 0 ? Object.assign(child, { optional: true }) : child;
4106
- },
4107
- effect: (input) => {
4108
- const effect = dependencies.effect || (() => {
4109
- try {
4110
- return require("effect");
4111
- } catch {
4112
- return null;
4113
- }
4114
- })();
4115
- if (!effect) {
4116
- throw new Error("effect dependency could not be found - try installing it and re-running");
4117
- }
4118
- if (!effect.Schema.isSchema(input)) {
4119
- const message = "input was not an effect schema - please use effect version 3.14.2 or higher. See https://github.com/mmkal/trpc-cli/pull/63";
4120
- throw new Error(message);
4121
- }
4122
- return effect.JSONSchema.make(input);
4123
- }
4124
- };
4125
- };
4126
- function getVendor(schema) {
4127
- return schema?.["~standard"]?.vendor ?? null;
4128
- }
4129
- const jsonSchemaVendorNames = new Set(Object.keys(getJsonSchemaConverters({})));
4130
- function looksJsonSchemaable(value) {
4131
- const vendor = getVendor(value);
4132
- return !!vendor && jsonSchemaVendorNames.has(vendor);
4133
- }
4134
- function prepareArktypeType(type) {
4135
- let innerType = type;
4136
- while (innerType) {
4137
- if (innerType?.in && innerType.in !== innerType) {
4138
- innerType = innerType.in;
4139
- } else {
4140
- break;
4141
- }
4142
- }
4143
- return innerType;
4144
- }
4145
-
4146
- const parseUpstreamOptionInfo = (value) => {
4147
- if (typeof value !== "string" || !value.startsWith("{")) return null;
4148
- try {
4149
- const info = JSON.parse(value);
4150
- if (info.typeName !== "UpstreamOptionInfo") return null;
4151
- return info;
4152
- } catch {
4153
- return null;
4154
- }
4155
- };
4156
- const parseUpstreamArgumentInfo = (value) => {
4157
- if (typeof value !== "string" || !value.startsWith("{")) return null;
4158
- try {
4159
- const info = JSON.parse(value);
4160
- if (info.typeName !== "UpstreamArgumentInfo") return null;
4161
- return info;
4162
- } catch {
4163
- return null;
4164
- }
4165
- };
4166
- const getDefaultSubcommand = (command) => {
4167
- const defaultChild = /Available subcommands:.* (\S+) \(default\)/.exec(
4168
- command.description()
4169
- )?.[1];
4170
- return defaultChild ? command.commands.find((c) => c.name() === defaultChild) : void 0;
4171
- };
4172
- const createShadowCommand = (command, onAnalyze) => {
4173
- const shadow = new Command(command.name());
4174
- shadow.exitOverride();
4175
- shadow.configureOutput({
4176
- writeOut: () => {
4177
- },
4178
- writeErr: () => {
4179
- }
4180
- });
4181
- const argumentsMap = /* @__PURE__ */ new Map();
4182
- const optionsMap = /* @__PURE__ */ new Map();
4183
- command.options.forEach((original) => {
4184
- const id = Date.now().toString() + Math.random().toString().slice(1);
4185
- const shadowOption = new Option(
4186
- original.flags.replace("<", "[").replace(">", "]"),
4187
- JSON.stringify([`id=${id}`, original.description])
4188
- );
4189
- const upstreamOptionInfo = {
4190
- typeName: "UpstreamOptionInfo",
4191
- id,
4192
- specified: false
4193
- };
4194
- shadowOption.default(JSON.stringify(upstreamOptionInfo));
4195
- shadowOption.argParser(
4196
- (value) => JSON.stringify({ ...upstreamOptionInfo, specified: true, value })
4197
- );
4198
- shadow.addOption(shadowOption);
4199
- optionsMap.set(id, { shadow: shadowOption, original });
4200
- });
4201
- command.registeredArguments.forEach((original) => {
4202
- const shadowArgument = new Argument(original.name(), original.description);
4203
- const id = Date.now().toString() + Math.random().toString().slice(1);
4204
- shadowArgument.argOptional();
4205
- const upstreamArgumentInfo = {
4206
- typeName: "UpstreamArgumentInfo",
4207
- id,
4208
- specified: false
4209
- };
4210
- shadowArgument.default(JSON.stringify(upstreamArgumentInfo));
4211
- shadowArgument.argParser(
4212
- (value) => JSON.stringify({ ...upstreamArgumentInfo, specified: true, value })
4213
- );
4214
- shadow.addArgument(shadowArgument);
4215
- argumentsMap.set(id, { shadow: shadowArgument, original });
4216
- });
4217
- const analysis = {
4218
- command: { shadow, original: command },
4219
- arguments: [],
4220
- options: []
4221
- };
4222
- shadow.action(async (...args) => {
4223
- const positionalValues = args.slice(0, -2);
4224
- const options = shadow.opts();
4225
- if (args.at(-2) !== options) {
4226
- throw new Error("Unexpected args format, second last arg is not the options object", {
4227
- cause: args
4228
- });
4229
- }
4230
- if (args.at(-1) !== shadow) {
4231
- throw new Error("Unexpected args format, last arg is not the Command instance", {
4232
- cause: args
4233
- });
4234
- }
4235
- positionalValues.forEach((value) => {
4236
- const argumentInfo = parseUpstreamArgumentInfo(value);
4237
- if (argumentInfo) {
4238
- analysis.arguments.push({
4239
- ...argumentsMap.get(argumentInfo.id),
4240
- value: argumentInfo.value,
4241
- specified: argumentInfo.specified
4242
- });
4243
- }
4244
- });
4245
- Object.values(options).forEach((value) => {
4246
- const upstreamOptionInfo = parseUpstreamOptionInfo(value);
4247
- if (upstreamOptionInfo) {
4248
- analysis.options.push({
4249
- ...optionsMap.get(upstreamOptionInfo.id),
4250
- value: upstreamOptionInfo.value,
4251
- specified: upstreamOptionInfo.specified
4252
- });
4253
- }
4254
- });
4255
- await onAnalyze(analysis);
4256
- });
4257
- command.commands.forEach((subcommand) => {
4258
- const shadowSubcommand = createShadowCommand(subcommand, onAnalyze);
4259
- shadow.addCommand(shadowSubcommand);
4260
- });
4261
- return shadow;
4262
- };
4263
- const inquirerPrompter = (prompts) => {
4264
- return prompts;
4265
- };
4266
- const clackPrompter = (prompts) => {
4267
- const clack = prompts;
4268
- class ExitPromptError extends Error {
4269
- }
4270
- const throwOnCancel = (value) => {
4271
- if (clack.isCancel(value)) throw new ExitPromptError();
4272
- return value;
4273
- };
4274
- return {
4275
- input: async (params) => {
4276
- return clack.text({
4277
- message: params.message,
4278
- initialValue: params.default,
4279
- defaultValue: params.default,
4280
- placeholder: params.default,
4281
- validate: params.validate ? (input) => {
4282
- const result = params.validate(input);
4283
- if (result === true) return;
4284
- if (result === false) return "Invalid input";
4285
- return result;
4286
- } : void 0
4287
- }).then(throwOnCancel);
4288
- },
4289
- checkbox: async (params) => {
4290
- return clack.multiselect({
4291
- message: params.message,
4292
- options: params.choices.map((c) => ({
4293
- label: c.name,
4294
- value: c.value
4295
- })),
4296
- initialValues: params.choices.flatMap((c) => c.checked ? [c.value] : [])
4297
- }).then(throwOnCancel);
4298
- },
4299
- confirm: async (params) => {
4300
- return clack.confirm({
4301
- message: params.message,
4302
- initialValue: params.default
4303
- }).then(throwOnCancel);
4304
- },
4305
- select: async (params) => {
4306
- return clack.select({
4307
- message: params.message,
4308
- options: params.choices.map((sorc) => {
4309
- const c = typeof sorc === "string" ? { name: sorc, value: sorc } : sorc;
4310
- return {
4311
- label: c.name,
4312
- value: c.value,
4313
- hint: c.description
4314
- };
4315
- }),
4316
- initialValue: params.default
4317
- }).then(throwOnCancel);
4318
- }
4319
- };
4320
- };
4321
- const promptsPrompter = (prompts) => {
4322
- const p = prompts;
4323
- function x() {
4324
- return (value) => value.x;
4325
- }
4326
- return {
4327
- input: async (params) => {
4328
- return p({
4329
- name: "x",
4330
- type: "text",
4331
- message: params.message,
4332
- validate: params.validate,
4333
- initial: params.default
4334
- }).then(x());
4335
- },
4336
- confirm: async (params) => {
4337
- return p({
4338
- name: "x",
4339
- type: "confirm",
4340
- message: params.message,
4341
- active: params.default ? "yes" : "no"
4342
- }).then(x());
4343
- },
4344
- select: async (params) => {
4345
- const choicesObjects = params.choices.map(
4346
- (c) => typeof c === "string" ? { name: c, value: c } : c
4347
- );
4348
- return p({
4349
- name: "x",
4350
- type: "select",
4351
- message: params.message,
4352
- active: params.default,
4353
- choices: choicesObjects.map((c) => ({
4354
- title: c.name || c.value,
4355
- value: c.value
4356
- })),
4357
- initial: params.default ? choicesObjects.findIndex((c) => c.value === params.default) : void 0
4358
- }).then(x());
4359
- },
4360
- checkbox: async (params) => {
4361
- const choicesObjects = params.choices.map(
4362
- (c) => typeof c === "string" ? { name: c, value: c } : c
4363
- );
4364
- return p({
4365
- name: "x",
4366
- type: "multiselect",
4367
- message: params.message,
4368
- choices: choicesObjects.map((c) => ({
4369
- title: c.name || c.value,
4370
- value: c.value,
4371
- selected: c.checked
4372
- }))
4373
- }).then(x());
4374
- }
4375
- };
4376
- };
4377
- const enquirerPrompter = (prompts) => {
4378
- const enquirer = prompts;
4379
- function x() {
4380
- return (value) => value.x;
4381
- }
4382
- return {
4383
- input: async (params) => {
4384
- return enquirer.prompt({
4385
- type: "input",
4386
- name: "x",
4387
- message: params.message,
4388
- validate: params.validate,
4389
- initial: params.default
4390
- }).then(x());
4391
- },
4392
- confirm: async (params) => {
4393
- return enquirer.prompt({
4394
- type: "confirm",
4395
- name: "x",
4396
- message: params.message,
4397
- validate: params.validate,
4398
- initial: params.default
4399
- }).then(x());
4400
- },
4401
- select: async (params) => {
4402
- return enquirer.prompt({
4403
- type: "select",
4404
- name: "x",
4405
- message: params.message,
4406
- // @ts-expect-error not sure why this is an error, in the IDE it infers the type correctly
4407
- choices: params.choices.slice(),
4408
- validate: params.validate,
4409
- initial: params.default
4410
- }).then(x());
4411
- },
4412
- checkbox: async (params) => {
4413
- return enquirer.prompt({
4414
- type: "multiselect",
4415
- name: "x",
4416
- message: params.message,
4417
- // @ts-expect-error not sure why this is an error, in the IDE it infers the type correctly
4418
- choices: params.choices.slice().map((c) => ({
4419
- name: c.name,
4420
- value: c.value
4421
- })),
4422
- // validate: params.validate ? v => params.validate!([{value: v}]) : undefined,
4423
- initial: params.choices.flatMap((c, i) => c.checked ? [i] : [])
4424
- }).then(x());
3692
+ const defaultMap = {};
3693
+ for (const [argKey, def] of Object.entries(command.args || {})) {
3694
+ if (def.type === "boolean") {
3695
+ defaultMap[argKey] = def.default !== void 0 ? def.default : false;
3696
+ } else if (def.default !== void 0) {
3697
+ defaultMap[argKey] = def.type === "array" && typeof def.default === "string" ? [def.default] : def.default;
4425
3698
  }
4426
- };
4427
- };
4428
- const promptify = (program, prompts) => {
4429
- let promptsInput = prompts;
4430
- if (promptsInput?.default) promptsInput = promptsInput.default;
4431
- let prompter;
4432
- if (typeof promptsInput === "function" && typeof promptsInput.inject === "function") {
4433
- prompter = promptsPrompter(promptsInput);
4434
- } else if (promptsInput?.name === "Enquirer") {
4435
- prompter = enquirerPrompter(promptsInput);
4436
- } else if (typeof promptsInput?.rawlist === "function") {
4437
- prompter = inquirerPrompter(promptsInput);
4438
- } else if (typeof promptsInput?.intro === "function") {
4439
- prompter = clackPrompter(promptsInput);
4440
- } else if (typeof promptsInput === "function") {
4441
- prompter = promptsInput(program);
4442
- } else {
4443
- prompter = promptsInput;
4444
3699
  }
4445
- const command = program;
4446
- const analyseThenParse = async (argv, parseOptions) => {
4447
- if (parseOptions?.from === "electron") {
4448
- console.warn(
4449
- `Warning: using prompts in electron mode is untested. The first two args of $0 are not available in electron mode. Assuming that the first two args of ${JSON.stringify(argv)} are electron-related and not intended for the CLI.`
4450
- );
4451
- }
4452
- if (parseOptions?.from !== "user") {
4453
- argv = argv.slice(2);
4454
- parseOptions = { from: "user" };
4455
- }
4456
- const f = { command, args: [...argv] };
4457
- const nextArgv = [...f.args];
4458
- let analysis;
4459
- const maxAttempts = 100;
4460
- for (let i = maxAttempts; i >= 0 && !analysis; i--) {
4461
- analysis = await new Promise((resolve, reject) => {
4462
- const shadow = createShadowCommand(f.command, async (an) => {
4463
- if (an.command.original.commands.length === 0) {
4464
- resolve(an);
4465
- return;
4466
- }
4467
- const defaultSubcommand = getDefaultSubcommand(an.command.original);
4468
- if (defaultSubcommand) {
4469
- resolve(an);
4470
- return;
4471
- }
4472
- const name = await prompter.select(
4473
- {
4474
- message: `Select a ${an.command.original.name() || ""} subcommand`.replace(" ", " "),
4475
- choices: an.command.original.commands.map((c) => ({
4476
- name: c.name(),
4477
- value: c.name(),
4478
- description: c.description()
4479
- }))
4480
- },
4481
- {}
4482
- );
4483
- nextArgv.push(name);
4484
- resolve(void 0);
4485
- });
4486
- shadow.parseAsync(nextArgv, parseOptions).catch((e) => {
4487
- if (e?.constructor?.name === "CommanderError") {
4488
- resolve({
4489
- command: { shadow: f.command, original: f.command },
4490
- arguments: [],
4491
- options: []
4492
- });
4493
- } else {
4494
- reject(e);
4495
- }
4496
- });
4497
- });
4498
- }
4499
- if (!analysis) {
4500
- const message = `Failed to find a subcommand after ${maxAttempts} attempts - failing to avoid an infinite loop. This is probably a bug in @reliverse/rempts.`;
4501
- throw new Error(message);
4502
- }
4503
- const getMessage = (argOrOpt) => {
4504
- const name = "long" in argOrOpt ? argOrOpt.flags : `[${argOrOpt.name()}]`;
4505
- const parts = [
4506
- name,
4507
- argOrOpt.description,
4508
- argOrOpt.defaultValue && `(default: ${argOrOpt.defaultValue})`,
4509
- !argOrOpt.defaultValue && !argOrOpt.required && "(optional)"
4510
- ];
4511
- return `${parts.filter(Boolean).join(" ").trim()}:`;
4512
- };
4513
- const baseContext = {
4514
- command: analysis.command.original,
4515
- inputs: {
4516
- argv,
4517
- arguments: analysis.arguments.map((a) => ({
4518
- name: a.original.name(),
4519
- specified: a.specified,
4520
- value: a.value
4521
- })),
4522
- options: analysis.options.map((o) => ({
4523
- name: o.original.name(),
4524
- specified: o.specified,
4525
- value: o.value
4526
- }))
4527
- }
4528
- };
4529
- await prompter.setup?.(baseContext);
4530
- let shouldPrompt;
4531
- {
4532
- const someRequiredArgsUnspecified = analysis.arguments.some(
4533
- (a) => a.original.required && !a.specified
4534
- );
4535
- const someRequiredOptionsUnspecified = analysis.options.some(
4536
- (o) => o.original.required && !o.specified
4537
- );
4538
- shouldPrompt = someRequiredArgsUnspecified || someRequiredOptionsUnspecified;
4539
- }
4540
- if (shouldPrompt) {
4541
- for (const arg of analysis.arguments) {
4542
- const ctx = { ...baseContext, argument: arg.original };
4543
- if (!arg.specified) {
4544
- const parseArg = "parseArg" in arg.original && typeof arg.original.parseArg === "function" ? arg.original.parseArg : void 0;
4545
- const promptedValue = await prompter.input(
4546
- {
4547
- message: getMessage(arg.original),
4548
- required: arg.original.required,
4549
- default: arg.value,
4550
- validate: (input) => {
4551
- try {
4552
- parseArg?.(input);
4553
- return true;
4554
- } catch (e) {
4555
- return e?.message || e;
4556
- }
4557
- }
4558
- },
4559
- ctx
4560
- );
4561
- nextArgv.push(promptedValue);
4562
- }
4563
- }
4564
- for (const option of analysis.options) {
4565
- const ctx = { ...baseContext, option: option.original };
4566
- if (!option.specified) {
4567
- const fullFlag = option.original.long || `--${option.original.name()}`;
4568
- const isBoolean = option.original.isBoolean() || option.original.flags.includes("[boolean]");
4569
- if (isBoolean) {
4570
- const promptedValue = await prompter.confirm(
4571
- {
4572
- message: getMessage(option.original),
4573
- default: option.original.defaultValue ?? false
4574
- },
4575
- ctx
4576
- );
4577
- if (promptedValue) nextArgv.push(fullFlag);
4578
- } else if (option.original.variadic && option.original.argChoices) {
4579
- const choices = option.original.argChoices.slice();
4580
- const results = await prompter.checkbox(
4581
- {
4582
- message: getMessage(option.original),
4583
- choices: choices.map((choice) => ({
4584
- value: choice,
4585
- name: choice,
4586
- checked: true
4587
- }))
4588
- },
4589
- ctx
4590
- );
4591
- results.forEach((result) => {
4592
- if (typeof result === "string") nextArgv.push(fullFlag, result);
4593
- });
4594
- } else if (option.original.argChoices) {
4595
- const choices = option.original.argChoices.slice();
4596
- const set = new Set(choices);
4597
- const promptedValue = await prompter.select(
4598
- {
4599
- message: getMessage(option.original),
4600
- choices,
4601
- default: option.original.defaultValue
4602
- // required: option.original.required,
4603
- },
4604
- ctx
4605
- );
4606
- if (set.has(promptedValue)) {
4607
- nextArgv.push(fullFlag, promptedValue);
4608
- }
4609
- } else if (option.original.variadic) {
4610
- const values = [];
4611
- do {
4612
- const promptedValue = await prompter.input(
4613
- {
4614
- message: getMessage(option.original),
4615
- default: option.original.defaultValue?.[values.length]
4616
- },
4617
- ctx
4618
- );
4619
- if (!promptedValue) break;
4620
- values.push(fullFlag, promptedValue);
4621
- } while (values);
4622
- nextArgv.push(...values);
4623
- } else {
4624
- const getParsedValue = (input) => {
4625
- return option.original.parseArg ? option.original.parseArg(input, void 0) : input;
4626
- };
4627
- const promptedValue = await prompter.input(
4628
- {
4629
- message: getMessage(option.original),
4630
- default: option.value,
4631
- required: option.original.required,
4632
- validate: (input) => {
4633
- const parsed = getParsedValue(input);
4634
- if (parsed == null && input != null) return "Invalid value";
4635
- return true;
4636
- }
4637
- },
4638
- ctx
4639
- );
4640
- if (promptedValue)
4641
- nextArgv.push(fullFlag, getParsedValue(promptedValue) ?? promptedValue);
4642
- }
4643
- }
4644
- }
4645
- }
4646
- await prompter.teardown?.(baseContext);
4647
- return f.command.parseAsync(nextArgv, parseOptions);
3700
+ const mergedParserOptions = {
3701
+ ...parserOptions,
3702
+ boolean: [...parserOptions.boolean || [], ...booleanKeys],
3703
+ defaults: { ...defaultMap, ...parserOptions.defaults || {} }
4648
3704
  };
4649
- const parseAsync = (args, parseOptions) => analyseThenParse(args, parseOptions).catch((e) => {
4650
- if (e?.constructor?.name === "ExitPromptError") return;
4651
- throw e;
4652
- });
4653
- return new Proxy(program, {
4654
- get(target, prop, receiver) {
4655
- if (prop === "parseAsync") return parseAsync;
4656
- return Reflect.get(target, prop, receiver);
4657
- }
4658
- });
4659
- };
4660
-
4661
- const looksLikeStandardSchemaFailure = (error) => {
4662
- return !!error && typeof error === "object" && "issues" in error && Array.isArray(error.issues);
4663
- };
4664
- const looksLikeStandardSchema = (thing) => {
4665
- return !!thing && typeof thing === "object" && "~standard" in thing && typeof thing["~standard"] === "object";
4666
- };
4667
-
4668
- const prettifyStandardSchemaError = (error) => {
4669
- if (!looksLikeStandardSchemaFailure(error)) return null;
4670
- const issues = [...error.issues].map((issue) => {
4671
- const path = issue.path || [];
4672
- const primitivePathSegments = path.map((segment) => {
4673
- if (typeof segment === "string" || typeof segment === "number" || typeof segment === "symbol")
4674
- return segment;
4675
- return segment.key;
4676
- });
4677
- const dotPath = toDotPath(primitivePathSegments);
4678
- return {
4679
- issue,
4680
- path,
4681
- primitivePathSegments,
4682
- dotPath
4683
- };
4684
- }).sort((a, b) => a.path.length - b.path.length);
4685
- const lines = [];
4686
- for (const { issue, dotPath } of issues) {
4687
- let message = `\u2716 ${issue.message}`;
4688
- if (dotPath) message += ` \u2192 at ${dotPath}`;
4689
- lines.push(message);
4690
- }
4691
- return lines.join("\n");
4692
- };
4693
- function toDotPath(path) {
4694
- const segs = [];
4695
- for (const seg of path) {
4696
- if (typeof seg === "number") segs.push(`[${seg}]`);
4697
- else if (typeof seg === "symbol") segs.push(`[${JSON.stringify(String(seg))}]`);
4698
- else if (/[^\w$]/.test(seg)) segs.push(`[${JSON.stringify(seg)}]`);
4699
- else {
4700
- if (segs.length) segs.push(".");
4701
- segs.push(seg);
4702
- }
4703
- }
4704
- return segs.join("");
4705
- }
4706
- class StandardSchemaV1Error extends Error {
4707
- issues;
4708
- constructor(failure, options) {
4709
- super("Standard Schema error - details in `issues`.", options);
4710
- this.issues = failure.issues;
4711
- }
4712
- }
4713
-
4714
- const isTrpc11Procedure = (procedure) => {
4715
- return "type" in procedure._def && typeof procedure._def.type === "string";
4716
- };
4717
- const isTrpc11Router = (router) => {
4718
- if (isOrpcRouter(router)) return false;
4719
- const procedure = Object.values(router._def.procedures)[0];
4720
- return Boolean(procedure && isTrpc11Procedure(procedure));
4721
- };
4722
- const isOrpcRouter = (router) => {
4723
- return !("_def" in router) || router._def && "~orpc" in router._def;
4724
- };
4725
-
4726
- const looksLikeInstanceof = (value, target) => {
4727
- let current = value?.constructor;
4728
- while (current?.name) {
4729
- if (current?.name === (typeof target === "string" ? target : target.name)) return true;
4730
- current = Object.getPrototypeOf(current);
3705
+ const parsed = reliArgParser(argv, mergedParserOptions);
3706
+ const finalArgs = {};
3707
+ const positionalKeys = Object.keys(command.args || {}).filter(
3708
+ (k) => command.args?.[k]?.type === "positional"
3709
+ );
3710
+ const leftoverPositionals = [...parsed._ || []];
3711
+ for (let i = 0; i < positionalKeys.length; i++) {
3712
+ const key = positionalKeys[i];
3713
+ if (!key || !command.args) continue;
3714
+ const def = command.args[key];
3715
+ const val = leftoverPositionals[i];
3716
+ finalArgs[key] = val != null && def ? castArgValue$1(def, val, key) : def?.default;
4731
3717
  }
4732
- return false;
4733
- };
4734
-
4735
- class TrpcCommand extends Command {
4736
- /** @internal track the commands that have been run, so that we can find the `__result` of the last command */
4737
- __ran = [];
4738
- __input;
4739
- /** @internal stash the return value of the underlying procedure on the command so to pass to `FailedToExitError` for use in a pinch */
4740
- __result;
4741
- }
4742
- const parseRouter = ({ router, ...params }) => {
4743
- if (isOrpcRouter(router)) return parseOrpcRouter({ router, ...params });
4744
- return parseTrpcRouter({ router, ...params });
4745
- };
4746
- const parseTrpcRouter = ({
4747
- router,
4748
- ...params
4749
- }) => {
4750
- const defEntries = Object.entries(router._def.procedures);
4751
- return defEntries.map(([procedurePath, procedure]) => {
4752
- const meta = getMeta(procedure);
4753
- if (meta.jsonInput) {
4754
- return [
4755
- procedurePath,
4756
- {
4757
- meta,
4758
- parsedProcedure: jsonProcedureInputs(),
4759
- incompatiblePairs: [],
4760
- procedure
4761
- }
4762
- ];
4763
- }
4764
- const procedureInputsResult = parseProcedureInputs(procedure._def.inputs, params);
4765
- if (!procedureInputsResult.success) {
4766
- const procedureInputs2 = jsonProcedureInputs(
4767
- `procedure's schema couldn't be converted to CLI arguments: ${procedureInputsResult.error}`
4768
- );
4769
- return [
4770
- procedurePath,
4771
- {
4772
- meta,
4773
- parsedProcedure: procedureInputs2,
4774
- incompatiblePairs: [],
4775
- procedure
4776
- }
4777
- ];
4778
- }
4779
- const procedureInputs = procedureInputsResult.value;
4780
- const incompatiblePairs = incompatiblePropertyPairs(procedureInputs.optionsJsonSchema);
4781
- return [
4782
- procedurePath,
4783
- {
4784
- meta: getMeta(procedure),
4785
- parsedProcedure: procedureInputs,
4786
- incompatiblePairs,
4787
- procedure
4788
- }
4789
- ];
4790
- });
4791
- };
4792
- const parseOrpcRouter = (params) => {
4793
- const entries = [];
4794
- const { traverseContractProcedures, isProcedure } = (() => {
4795
- try {
4796
- return require("@orpc/server");
4797
- } catch (e) {
4798
- throw new Error(
4799
- "@orpc/server dependency could not be found - try installing it and re-running",
4800
- { cause: e }
4801
- );
4802
- }
4803
- })();
4804
- const router = params.router;
4805
- const lazyRoutes = traverseContractProcedures({ path: [], router }, ({ contract, path }) => {
4806
- let procedure = params.router;
4807
- for (const p of path) procedure = procedure[p];
4808
- if (!isProcedure(procedure)) return;
4809
- const procedureInputsResult = parseProcedureInputs([contract["~orpc"].inputSchema], {
4810
- "@valibot/to-json-schema": params["@valibot/to-json-schema"],
4811
- effect: params.effect
4812
- });
4813
- const procedurePath = path.join(".");
4814
- const procedureish = {
4815
- _def: { meta: contract["~orpc"].meta }
4816
- };
4817
- const meta = getMeta(procedureish);
4818
- if (meta.jsonInput) {
4819
- entries.push([
4820
- procedurePath,
4821
- {
4822
- meta,
4823
- parsedProcedure: jsonProcedureInputs(),
4824
- incompatiblePairs: [],
4825
- procedure
4826
- }
4827
- ]);
4828
- return;
4829
- }
4830
- if (!procedureInputsResult.success) {
4831
- const parsedProcedure2 = jsonProcedureInputs(
4832
- `procedure's schema couldn't be converted to CLI arguments: ${procedureInputsResult.error}`
4833
- );
4834
- entries.push([
4835
- procedurePath,
4836
- {
4837
- meta,
4838
- parsedProcedure: parsedProcedure2,
4839
- incompatiblePairs: [],
4840
- procedure
4841
- }
4842
- ]);
4843
- return;
3718
+ const otherKeys = Object.keys(command.args || {}).filter(
3719
+ (k) => command.args?.[k]?.type !== "positional"
3720
+ );
3721
+ for (const key of otherKeys) {
3722
+ const def = command.args?.[key];
3723
+ if (!def) continue;
3724
+ let rawVal = parsed[key];
3725
+ if (def.type === "array" && rawVal !== void 0 && !Array.isArray(rawVal)) {
3726
+ rawVal = [rawVal];
4844
3727
  }
4845
- const parsedProcedure = procedureInputsResult.value;
4846
- const incompatiblePairs = incompatiblePropertyPairs(parsedProcedure.optionsJsonSchema);
4847
- entries.push([procedurePath, { procedure, meta, incompatiblePairs, parsedProcedure }]);
4848
- });
4849
- if (lazyRoutes.length) {
4850
- const suggestion = `Please use \`import {unlazyRouter} from '@orpc/server'\` to unlazy the router before passing it to @reliverse/rempts`;
4851
- const routes = lazyRoutes.map(({ path }) => path.join(".")).join(", ");
4852
- throw new Error(
4853
- `Lazy routers are not supported. ${suggestion}. Lazy routes detected: ${routes}`
4854
- );
4855
- }
4856
- return entries;
4857
- };
4858
- const jsonProcedureInputs = (reason) => {
4859
- let description = "Input formatted as JSON";
4860
- if (reason) description += ` (${reason})`;
4861
- return {
4862
- positionalParameters: [],
4863
- optionsJsonSchema: {
4864
- type: "object",
4865
- properties: {
4866
- input: { type: "json", description }
4867
- }
4868
- },
4869
- getPojoInput: (parsedCliParams) => {
4870
- if (parsedCliParams.options.input == null) return parsedCliParams.options.input;
4871
- return JSON.parse(parsedCliParams.options.input);
3728
+ const casted = rawVal !== void 0 ? castArgValue$1(def, rawVal, key) : def.default;
3729
+ const argUsed = rawVal !== void 0 && (def.type === "boolean" ? casted === true : true);
3730
+ if (casted == null && def.required) {
3731
+ throw new Error(`Missing required argument: --${key}`);
4872
3732
  }
4873
- };
4874
- };
4875
- function createRpcCli({
4876
- router,
4877
- ...params
4878
- }) {
4879
- const procedureEntries = parseRouter({ router, ...params });
4880
- function buildProgram(runParams) {
4881
- const logger = { ...lineByLineConsoleLogger, ...runParams?.logger };
4882
- const program = new TrpcCommand(params.name);
4883
- if (params.version) program.version(params.version);
4884
- if (params.description) program.description(params.description);
4885
- if (params.usage) [params.usage].flat().forEach((usage) => program.usage(usage));
4886
- program.showHelpAfterError();
4887
- program.showSuggestionAfterError();
4888
- const commandTree = {
4889
- "": program
4890
- // Root level
4891
- };
4892
- const defaultCommands = {};
4893
- const _process = runParams?.process || process;
4894
- const configureCommand = (command, procedurePath, { meta, parsedProcedure, incompatiblePairs, procedure }) => {
4895
- const optionJsonSchemaProperties = flattenedProperties(parsedProcedure.optionsJsonSchema);
4896
- command.exitOverride((ec) => {
4897
- _process.exit(ec.exitCode);
4898
- throw new FailedToExitError(`Command ${command.name()} exitOverride`, {
4899
- exitCode: ec.exitCode,
4900
- cause: ec
4901
- });
4902
- });
4903
- command.configureOutput({
4904
- writeOut: (str) => {
4905
- logger.info?.(str);
4906
- },
4907
- writeErr: (str) => {
4908
- logger.error?.(str);
4909
- }
4910
- });
4911
- command.showHelpAfterError();
4912
- if (meta.usage) command.usage([meta.usage].flat().join("\n"));
4913
- if (meta.examples)
4914
- command.addHelpText("after", `
4915
- Examples:
4916
- ${[meta.examples].flat().join("\n")}`);
4917
- meta?.aliases?.command?.forEach((alias) => {
4918
- command.alias(alias);
4919
- });
4920
- command.description(meta?.description || "");
4921
- parsedProcedure.positionalParameters.forEach((param) => {
4922
- const descriptionParts = [
4923
- param.type === "string" ? "" : param.type,
4924
- // "string" is the default assumption, don't bother showing it
4925
- param.description,
4926
- param.required ? "(required)" : ""
4927
- ];
4928
- const argument = new Argument(param.name, descriptionParts.filter(Boolean).join(" "));
4929
- if (param.type === "number") {
4930
- argument.argParser((value) => {
4931
- const number = numberParser(value, { fallback: null });
4932
- if (number == null) throw new InvalidArgumentError(`Invalid number: ${value}`);
4933
- return value;
4934
- });
4935
- }
4936
- argument.required = param.required;
4937
- argument.variadic = param.array;
4938
- command.addArgument(argument);
4939
- });
4940
- const unusedOptionAliases = {
4941
- ...meta.aliases?.options
4942
- };
4943
- const addOptionForProperty = ([propertyKey, propertyValue]) => {
4944
- const description = getDescription(propertyValue);
4945
- const longOption = `--${kebabCase(propertyKey)}`;
4946
- let flags = longOption;
4947
- const alias = meta.aliases?.options?.[propertyKey];
4948
- if (alias) {
4949
- let prefix = "-";
4950
- if (alias.startsWith("-")) prefix = "";
4951
- else if (alias.length > 1) prefix = "--";
4952
- flags = `${prefix}${alias}, ${flags}`;
4953
- delete unusedOptionAliases[propertyKey];
4954
- }
4955
- const defaultValue = "default" in propertyValue ? { exists: true, value: propertyValue.default } : { exists: false };
4956
- const rootTypes = getSchemaTypes(propertyValue).sort();
4957
- const getValueParser = (types) => {
4958
- types = types.map((t) => t === "integer" ? "number" : t);
4959
- if (types.length === 2 && types[0] === "boolean" && types[1] === "number") {
4960
- return {
4961
- type: "boolean|number",
4962
- parser: (value) => booleanParser(value, { fallback: null }) ?? numberParser(value)
4963
- };
4964
- }
4965
- if (types.length === 1 && types[0] === "boolean") {
4966
- return {
4967
- type: "boolean",
4968
- parser: (value) => booleanParser(value)
4969
- };
4970
- }
4971
- if (types.length === 1 && types[0] === "number") {
4972
- return {
4973
- type: "number",
4974
- parser: (value) => numberParser(value)
4975
- };
4976
- }
4977
- if (types.length === 1 && types[0] === "string") {
4978
- return { type: "string", parser: null };
4979
- }
4980
- return {
4981
- type: "json",
4982
- parser: (value) => {
4983
- let parsed;
4984
- try {
4985
- parsed = JSON.parse(value);
4986
- } catch {
4987
- throw new InvalidArgumentError("Malformed JSON.");
4988
- }
4989
- const jsonSchemaType = Array.isArray(parsed) ? "array" : parsed === null ? "null" : typeof parsed;
4990
- if (!types.includes(jsonSchemaType)) {
4991
- throw new InvalidArgumentError(
4992
- `Got ${jsonSchemaType} but expected ${types.join(" or ")}`
4993
- );
4994
- }
4995
- return parsed;
4996
- }
4997
- };
4998
- };
4999
- const propertyType = rootTypes[0];
5000
- const isValueRequired = "required" in parsedProcedure.optionsJsonSchema && parsedProcedure.optionsJsonSchema.required?.includes(propertyKey);
5001
- const isCliOptionRequired = isValueRequired && propertyType !== "boolean" && !defaultValue.exists;
5002
- function negate() {
5003
- const negation = new Option(
5004
- longOption.replace("--", "--no-"),
5005
- `Negate \`${longOption}\` option.`.trim()
5006
- );
5007
- command.addOption(negation);
5008
- }
5009
- const bracketise = (name) => isCliOptionRequired ? `<${name}>` : `[${name}]`;
5010
- if (rootTypes.length === 2 && rootTypes[0] === "boolean" && rootTypes[1] === "string") {
5011
- const option2 = new Option(`${flags} [value]`, description);
5012
- option2.default(defaultValue.exists ? defaultValue.value : false);
5013
- command.addOption(option2);
5014
- negate();
5015
- return;
5016
- }
5017
- if (rootTypes.length === 2 && rootTypes[0] === "boolean" && rootTypes[1] === "number") {
5018
- const option2 = new Option(`${flags} [value]`, description);
5019
- option2.argParser(getValueParser(rootTypes).parser);
5020
- option2.default(defaultValue.exists ? defaultValue.value : false);
5021
- command.addOption(option2);
5022
- negate();
5023
- return;
5024
- }
5025
- if (rootTypes.length === 2 && rootTypes[0] === "number" && rootTypes[1] === "string") {
5026
- const option2 = new Option(`${flags} ${bracketise("value")}`, description);
5027
- option2.argParser((value) => {
5028
- const number = numberParser(value, { fallback: null });
5029
- return number ?? value;
5030
- });
5031
- if (defaultValue.exists) option2.default(defaultValue.value);
5032
- command.addOption(option2);
5033
- return;
5034
- }
5035
- if (rootTypes.length !== 1) {
5036
- const option2 = new Option(
5037
- `${flags} ${bracketise("json")}`,
5038
- `${description} (value will be parsed as JSON)`
5039
- );
5040
- option2.argParser(getValueParser(rootTypes).parser);
5041
- command.addOption(option2);
5042
- return;
5043
- }
5044
- if (propertyType === "boolean" && isValueRequired) {
5045
- const option2 = new Option(flags, description);
5046
- option2.default(defaultValue.exists ? defaultValue.value : false);
5047
- command.addOption(option2);
5048
- negate();
5049
- return;
5050
- }
5051
- if (propertyType === "boolean") {
5052
- const option2 = new Option(`${flags} [boolean]`, description);
5053
- option2.argParser((value) => booleanParser(value));
5054
- if (defaultValue.exists) option2.default(defaultValue.value);
5055
- command.addOption(option2);
5056
- negate();
5057
- return;
5058
- }
5059
- let option;
5060
- if (propertyType === "string") {
5061
- option = new Option(`${flags} ${bracketise("string")}`, description);
5062
- } else if (propertyType === "boolean") {
5063
- option = new Option(flags, description);
5064
- } else if (propertyType === "number" || propertyType === "integer") {
5065
- option = new Option(`${flags} ${bracketise("number")}`, description);
5066
- option.argParser((value) => numberParser(value, { fallback: null }));
5067
- } else if (propertyType === "array") {
5068
- option = new Option(`${flags} [values...]`, description);
5069
- if (defaultValue.exists) option.default(defaultValue.value);
5070
- else if (isValueRequired) option.default([]);
5071
- const itemsProp = "items" in propertyValue ? propertyValue.items : null;
5072
- const itemTypes = itemsProp ? getSchemaTypes(itemsProp) : [];
5073
- const itemEnumTypes = itemsProp && getEnumChoices(itemsProp);
5074
- if (itemEnumTypes?.type === "string_enum") {
5075
- option.choices(itemEnumTypes.choices);
5076
- }
5077
- const itemParser = getValueParser(itemTypes);
5078
- if (itemParser.parser) {
5079
- option.argParser((value, previous) => {
5080
- const parsed = itemParser.parser(value);
5081
- if (Array.isArray(previous)) return [...previous, parsed];
5082
- return [parsed];
5083
- });
5084
- }
5085
- }
5086
- option ||= new Option(`${flags} [json]`, description);
5087
- if (defaultValue.exists && option.defaultValue !== defaultValue.value) {
5088
- option.default(defaultValue.value);
5089
- }
5090
- if (option.flags.includes("<")) {
5091
- option.makeOptionMandatory();
5092
- }
5093
- const enumChoices = getEnumChoices(propertyValue);
5094
- if (enumChoices?.type === "string_enum") {
5095
- option.choices(enumChoices.choices);
5096
- }
5097
- option.conflicts(
5098
- incompatiblePairs.flatMap((pair) => {
5099
- const filtered = pair.filter((p) => p !== propertyKey);
5100
- if (filtered.length === pair.length) return [];
5101
- return filtered;
5102
- })
3733
+ if (argUsed && def.dependencies?.length) {
3734
+ const missingDeps = def.dependencies.filter((d) => {
3735
+ const depVal = parsed[d] ?? defaultMap[d];
3736
+ return !depVal;
3737
+ });
3738
+ if (missingDeps.length > 0) {
3739
+ const depsList = missingDeps.map((d) => `--${d}`).join(", ");
3740
+ throw new Error(
3741
+ `Argument --${key} can only be used when ${depsList} ${missingDeps.length === 1 ? "is" : "are"} set`
5103
3742
  );
5104
- command.addOption(option);
5105
- if (propertyType === "boolean") negate();
5106
- };
5107
- Object.entries(optionJsonSchemaProperties).forEach(addOptionForProperty);
5108
- const invalidOptionAliases = Object.entries(unusedOptionAliases).map(
5109
- ([option, alias]) => `${option}: ${alias}`
5110
- );
5111
- if (invalidOptionAliases.length) {
5112
- throw new Error(`Invalid option aliases: ${invalidOptionAliases.join(", ")}`);
5113
3743
  }
5114
- command.action(async (...args) => {
5115
- program.__ran ||= [];
5116
- program.__ran.push(command);
5117
- const options = command.opts();
5118
- if (args.at(-2) !== options) {
5119
- throw new Error("Unexpected args format, second last arg is not the options object", {
5120
- cause: args
5121
- });
5122
- }
5123
- if (args.at(-1) !== command) {
5124
- throw new Error("Unexpected args format, last arg is not the Command instance", {
5125
- cause: args
5126
- });
5127
- }
5128
- const positionalValues = args.slice(0, -2);
5129
- const input = parsedProcedure.getPojoInput({
5130
- positionalValues,
5131
- options
5132
- });
5133
- const resolvedTrpcServer = await (params.trpcServer || trpcServer11);
5134
- let caller;
5135
- const deprecatedCreateCaller = Reflect.get(params, "createCallerFactory");
5136
- if (deprecatedCreateCaller) {
5137
- const message = `Using deprecated \`createCallerFactory\` option. Use \`trpcServer\` instead. e.g. \`createRpcCli({router: myRouter, trpcServer: import('@trpc/server')})\``;
5138
- logger.error?.(message);
5139
- caller = deprecatedCreateCaller(router)(params.context);
5140
- } else if (isOrpcRouter(router)) {
5141
- const { call } = (() => {
5142
- try {
5143
- return require("@orpc/server");
5144
- } catch (e) {
5145
- throw new Error(
5146
- "@orpc/server dependency could not be found - try installing it and re-running",
5147
- { cause: e }
5148
- );
5149
- }
5150
- })();
5151
- caller = {
5152
- [procedurePath]: (_input) => call(procedure, _input, { context: params.context })
5153
- };
5154
- } else {
5155
- const createCallerFactor = resolvedTrpcServer.initTRPC.create().createCallerFactory;
5156
- caller = createCallerFactor(router)(params.context);
5157
- }
5158
- const result = await (caller[procedurePath]?.(input)).catch((err) => {
5159
- throw transformError(err, command);
5160
- });
5161
- command.__result = result;
5162
- if (result != null) logger.info?.(result);
3744
+ }
3745
+ finalArgs[key] = def.type === "boolean" ? Boolean(casted) : casted;
3746
+ }
3747
+ return {
3748
+ args: finalArgs,
3749
+ raw: argv
3750
+ };
3751
+ }
3752
+ async function createContextFromArgs(command, inputArgs) {
3753
+ const finalArgs = {};
3754
+ for (const [key, def] of Object.entries(command.args || {})) {
3755
+ const inputValue = inputArgs[key];
3756
+ let value;
3757
+ if (inputValue !== void 0) {
3758
+ value = castArgValue$1(def, inputValue, key);
3759
+ } else if (def.default !== void 0) {
3760
+ value = def.type === "array" && typeof def.default === "string" ? [def.default] : def.default;
3761
+ } else if (def.type === "boolean") {
3762
+ value = false;
3763
+ } else {
3764
+ value = void 0;
3765
+ }
3766
+ if (value == null && def.required) {
3767
+ throw new Error(`Missing required argument: ${key}`);
3768
+ }
3769
+ if (value != null && def.dependencies?.length) {
3770
+ const missingDeps = def.dependencies.filter((d) => {
3771
+ const depVal = inputArgs[d];
3772
+ return !depVal;
5163
3773
  });
5164
- };
5165
- procedureEntries.forEach(([procedurePath, commandConfig]) => {
5166
- const segments = procedurePath.split(".");
5167
- let currentPath = "";
5168
- for (let i = 0; i < segments.length - 1; i++) {
5169
- const segment = segments[i];
5170
- if (!segment) continue;
5171
- const parentPath2 = currentPath;
5172
- currentPath = currentPath ? `${currentPath}.${segment}` : segment;
5173
- if (!commandTree[currentPath]) {
5174
- const parentCommand2 = commandTree[parentPath2];
5175
- if (!parentCommand2) continue;
5176
- const newCommand = new TrpcCommand(kebabCase(segment));
5177
- newCommand.showHelpAfterError();
5178
- parentCommand2.addCommand(newCommand);
5179
- commandTree[currentPath] = newCommand;
5180
- }
5181
- }
5182
- const leafName = segments.at(-1);
5183
- if (!leafName) return;
5184
- const parentPath = segments.length > 1 ? segments.slice(0, -1).join(".") : "";
5185
- const parentCommand = commandTree[parentPath];
5186
- if (!parentCommand) return;
5187
- const leafCommand = new TrpcCommand(kebabCase(leafName));
5188
- configureCommand(leafCommand, procedurePath, commandConfig);
5189
- parentCommand.addCommand(leafCommand);
5190
- const meta = commandConfig.meta;
5191
- if (meta.default === true) {
5192
- parentCommand.allowExcessArguments();
5193
- parentCommand.allowUnknownOption();
5194
- parentCommand.addHelpText("after", leafCommand.helpInformation());
5195
- parentCommand.action(async () => {
5196
- await leafCommand.parseAsync([...parentCommand.args], {
5197
- from: "user"
5198
- });
5199
- });
5200
- defaultCommands[parentPath] = {
5201
- procedurePath,
5202
- config: commandConfig,
5203
- command: leafCommand
5204
- };
3774
+ if (missingDeps.length > 0) {
3775
+ const depsList = missingDeps.join(", ");
3776
+ throw new Error(
3777
+ `Argument '${key}' can only be used when ${depsList} ${missingDeps.length === 1 ? "is" : "are"} provided`
3778
+ );
5205
3779
  }
5206
- });
5207
- Object.entries(commandTree).forEach(([path, command]) => {
5208
- if (command.commands.length === 0) return;
5209
- const subcommandNames = command.commands.map((cmd) => cmd.name());
5210
- const defaultCommand = defaultCommands[path]?.command.name();
5211
- const formattedSubcommands = subcommandNames.map((name) => name === defaultCommand ? `${name} (default)` : name).join(", ");
5212
- const existingDescription = command.description() || "";
5213
- const descriptionParts = [
5214
- existingDescription,
5215
- `Available subcommands: ${formattedSubcommands}`
5216
- ];
5217
- command.description(descriptionParts.filter(Boolean).join("\n"));
5218
- });
5219
- return program;
5220
- }
5221
- const run = async (runParams, program = buildProgram(runParams)) => {
5222
- if (!looksLikeInstanceof(program, "TrpcCommand"))
5223
- throw new Error("program is not a TrpcCommand instance");
5224
- const opts = runParams?.argv ? { from: "user" } : void 0;
5225
- const argv = [...runParams?.argv || process.argv];
5226
- const _process = runParams?.process || process;
5227
- const logger = { ...lineByLineConsoleLogger, ...runParams?.logger };
5228
- program.exitOverride((exit) => {
5229
- _process.exit(exit.exitCode);
5230
- throw new FailedToExitError("Root command exitOverride", {
5231
- exitCode: exit.exitCode,
5232
- cause: exit
5233
- });
5234
- });
5235
- program.configureOutput({
5236
- writeOut: (str) => logger.info?.(str),
5237
- writeErr: (str) => logger.error?.(str)
5238
- });
5239
- if (runParams?.completion) {
5240
- const completion = typeof runParams.completion === "function" ? await runParams.completion() : runParams.completion;
5241
- addCompletions(program, completion);
5242
3780
  }
5243
- const formatError = runParams?.formatError || ((err) => {
5244
- if (err instanceof CliValidationError) {
5245
- return err.message;
5246
- }
5247
- return inspect(err);
5248
- });
5249
- if (runParams?.prompts) {
5250
- program = promptify(program, runParams.prompts);
5251
- }
5252
- await program.parseAsync(argv, opts).catch((err) => {
5253
- if (err instanceof FailedToExitError) throw err;
5254
- const logMessage = looksLikeInstanceof(err, Error) ? formatError(err) || err.message : `Non-error of type ${typeof err} thrown: ${err}`;
5255
- logger.error?.(logMessage);
5256
- _process.exit(1);
5257
- throw new FailedToExitError("Program exit after failure", {
5258
- exitCode: 1,
5259
- cause: err
5260
- });
5261
- });
5262
- _process.exit(0);
5263
- throw new FailedToExitError("Program exit after success", {
5264
- exitCode: 0,
5265
- cause: program.__ran.at(-1)?.__result
5266
- });
5267
- };
3781
+ finalArgs[key] = value;
3782
+ }
5268
3783
  return {
5269
- run,
5270
- buildProgram,
5271
- toJSON: (program = buildProgram()) => commandToJSON(program)
3784
+ args: finalArgs,
3785
+ raw: []
3786
+ // No raw argv for object input
5272
3787
  };
5273
3788
  }
5274
- function getMeta(procedure) {
5275
- const meta = procedure._def.meta;
5276
- return meta?.cliMeta || meta || {};
5277
- }
5278
- function kebabCase(propName) {
5279
- return propName.replaceAll(/([A-Z])/g, "-$1").toLowerCase();
5280
- }
5281
- function transformError(err, command) {
5282
- if (looksLikeInstanceof(err, Error) && err.message.includes("This is a client-only function")) {
5283
- return new Error(
5284
- "Failed to create trpc caller. If using trpc v10, either upgrade to v11 or pass in the `@trpc/server` module to `createRpcCli` explicitly"
5285
- );
5286
- }
5287
- if (looksLikeInstanceof(err, "TRPCError")) {
5288
- const cause = err.cause;
5289
- if (looksLikeStandardSchemaFailure(cause)) {
5290
- const prettyMessage = prettifyStandardSchemaError(cause);
5291
- return new CliValidationError(`${prettyMessage}
5292
-
5293
- ${command.helpInformation()}`);
3789
+ function castArgValue$1(def, rawVal, argName) {
3790
+ if (rawVal == null) {
3791
+ if (def.type === "array" && typeof def.default === "string") {
3792
+ return [def.default];
5294
3793
  }
5295
- if (err.code === "BAD_REQUEST" && (err.cause?.constructor?.name === "TraversalError" || // arktype error
5296
- err.cause?.constructor?.name === "StandardSchemaV1Error")) {
5297
- return new CliValidationError(`${err.cause.message}
5298
-
5299
- ${command.helpInformation()}`);
3794
+ return def.default ?? void 0;
3795
+ }
3796
+ let castedValue;
3797
+ switch (def.type) {
3798
+ case "boolean":
3799
+ if (typeof rawVal === "string") {
3800
+ const lower = rawVal.toLowerCase();
3801
+ if (lower === "true") castedValue = true;
3802
+ else if (lower === "false") castedValue = false;
3803
+ else castedValue = Boolean(rawVal);
3804
+ } else {
3805
+ castedValue = Boolean(rawVal);
3806
+ }
3807
+ if (def.allowed && !def.allowed.includes(castedValue)) {
3808
+ throw new Error(
3809
+ `Invalid value for ${argName}: ${rawVal}. Allowed values are: ${def.allowed.join(", ")}`
3810
+ );
3811
+ }
3812
+ return castedValue;
3813
+ case "string":
3814
+ castedValue = typeof rawVal === "string" ? rawVal : String(rawVal);
3815
+ if (def.allowed && !def.allowed.includes(castedValue)) {
3816
+ throw new Error(
3817
+ `Invalid value for ${argName}: ${rawVal}. Allowed values are: ${def.allowed.join(", ")}`
3818
+ );
3819
+ }
3820
+ return castedValue;
3821
+ case "number": {
3822
+ const n = Number(rawVal);
3823
+ if (Number.isNaN(n)) {
3824
+ throw new Error(`Invalid number provided for ${argName}: ${rawVal}`);
3825
+ }
3826
+ if (def.allowed && !def.allowed.includes(n)) {
3827
+ throw new Error(
3828
+ `Invalid value for ${argName}: ${rawVal}. Allowed values are: ${def.allowed.join(", ")}`
3829
+ );
3830
+ }
3831
+ return n;
5300
3832
  }
5301
- if (err.code === "INTERNAL_SERVER_ERROR") {
5302
- return cause;
3833
+ case "positional":
3834
+ castedValue = String(rawVal);
3835
+ if (def.allowed && !def.allowed.includes(castedValue)) {
3836
+ throw new Error(
3837
+ `Invalid value for ${argName}: ${rawVal}. Allowed values are: ${def.allowed.join(", ")}`
3838
+ );
3839
+ }
3840
+ return castedValue;
3841
+ case "array": {
3842
+ const arrVal = Array.isArray(rawVal) ? rawVal : [String(rawVal)];
3843
+ const result = [];
3844
+ for (let v of arrVal.map(String)) {
3845
+ if (v.startsWith("[") && v.endsWith("]")) {
3846
+ v = v.slice(1, -1);
3847
+ }
3848
+ const parts = v.split(/\s*,\s*/).filter(Boolean);
3849
+ for (const p of parts) {
3850
+ if (def.allowed && !def.allowed.includes(p)) {
3851
+ throw new Error(
3852
+ `Invalid value in array ${argName}: ${p}. Allowed values are: ${def.allowed.join(", ")}`
3853
+ );
3854
+ }
3855
+ }
3856
+ result.push(...parts);
3857
+ }
3858
+ return result;
5303
3859
  }
3860
+ default:
3861
+ return rawVal;
5304
3862
  }
5305
- return err;
5306
3863
  }
5307
- const numberParser = (val, { fallback = val } = {}) => {
5308
- const number = Number(val);
5309
- return Number.isNaN(number) ? fallback : number;
5310
- };
5311
- const booleanParser = (val, { fallback = val } = {}) => {
5312
- if (val === "true") return true;
5313
- if (val === "false") return false;
5314
- return fallback;
5315
- };
5316
3864
 
3865
+ async function pathExists(path2) {
3866
+ try {
3867
+ await stat(path2);
3868
+ return true;
3869
+ } catch (error) {
3870
+ return false;
3871
+ }
3872
+ }
5317
3873
  function buildExampleArgs(args) {
5318
3874
  const parts = [];
5319
3875
  const positionalKeys = Object.keys(args || {}).filter((k) => args?.[k]?.type === "positional");
@@ -5376,7 +3932,6 @@ function defineCommand(options) {
5376
3932
  onCmdExit,
5377
3933
  onLauncherInit,
5378
3934
  onLauncherExit,
5379
- router: options.router,
5380
3935
  // Backward-compatible aliases
5381
3936
  setup: onCmdInit,
5382
3937
  cleanup: onCmdExit
@@ -5410,7 +3965,7 @@ async function getDefaultCliNameAndVersion() {
5410
3965
  }
5411
3966
  async function findRecursiveFileBasedCommands(baseDir, currentPath = []) {
5412
3967
  const results = [];
5413
- const items = await fs.readdir(path.join(baseDir, ...currentPath), {
3968
+ const items = await readdir(path.join(baseDir, ...currentPath), {
5414
3969
  withFileTypes: true
5415
3970
  });
5416
3971
  for (const dirent of items) {
@@ -5418,7 +3973,7 @@ async function findRecursiveFileBasedCommands(baseDir, currentPath = []) {
5418
3973
  const newPath = [...currentPath, dirent.name];
5419
3974
  for (const fname of ["cmd.ts", "cmd.js"]) {
5420
3975
  const fpath = path.join(baseDir, ...newPath, fname);
5421
- if (await fs.pathExists(fpath)) {
3976
+ if (await pathExists(fpath)) {
5422
3977
  try {
5423
3978
  const imported = await import(path.resolve(fpath));
5424
3979
  if (imported.default && !imported.default.meta?.hidden) {
@@ -5676,84 +4231,6 @@ function createCli(options, legacyParserOptions) {
5676
4231
  };
5677
4232
  }
5678
4233
  const execute = async (_ctx) => {
5679
- if (options && typeof options === "object" && "rpc" in options && options.rpc) {
5680
- const rpcOptions = options.rpc;
5681
- const rpcRunParams = options.rpcRunParams || {};
5682
- debugLog("RPC integration detected, creating RPC CLI...");
5683
- try {
5684
- require("tsx/cjs");
5685
- await import('tsx/esm');
5686
- debugLog("tsx loaded successfully for TypeScript support");
5687
- } catch {
5688
- debugLog("tsx not available, continuing without TypeScript support");
5689
- }
5690
- const getRouterMeta = (router) => {
5691
- if ("_def" in router && router._def && "meta" in router._def) {
5692
- return router._def.meta;
5693
- }
5694
- return;
5695
- };
5696
- const routerMeta = getRouterMeta(rpcOptions.router);
5697
- const rpcCli = createRpcCli({
5698
- router: rpcOptions.router,
5699
- name: globalCliMeta.name || routerMeta?.name,
5700
- version: globalCliMeta.version || routerMeta?.version,
5701
- description: globalCliMeta.description || routerMeta?.description,
5702
- usage: rpcOptions.usage,
5703
- context: rpcOptions.context,
5704
- trpcServer: rpcOptions.trpcServer,
5705
- "@valibot/to-json-schema": rpcOptions["@valibot/to-json-schema"],
5706
- effect: rpcOptions.effect
5707
- });
5708
- debugLog("RPC CLI created, running with argv:", rpcRunParams.argv || process$1.argv.slice(2));
5709
- await rpcCli.run({
5710
- argv: rpcRunParams.argv || process$1.argv.slice(2),
5711
- logger: rpcRunParams.logger || {
5712
- info: console.log,
5713
- error: console.error
5714
- },
5715
- completion: rpcRunParams.completion,
5716
- prompts: rpcRunParams.prompts,
5717
- formatError: rpcRunParams.formatError,
5718
- process: rpcRunParams.process
5719
- });
5720
- return;
5721
- }
5722
- if (command.router) {
5723
- debugLog("Router detected in command, automatically enabling RPC mode...");
5724
- try {
5725
- require("tsx/cjs");
5726
- await import('tsx/esm');
5727
- debugLog("tsx loaded successfully for TypeScript support");
5728
- } catch {
5729
- debugLog("tsx not available, continuing without TypeScript support");
5730
- }
5731
- const getRouterMeta = (router) => {
5732
- if ("_def" in router && router._def && "meta" in router._def) {
5733
- return router._def.meta;
5734
- }
5735
- return;
5736
- };
5737
- const routerMeta = getRouterMeta(command.router);
5738
- const rpcCli = createRpcCli({
5739
- router: command.router,
5740
- name: globalCliMeta.name || command.meta?.name || routerMeta?.name,
5741
- version: globalCliMeta.version || command.meta?.version || routerMeta?.version,
5742
- description: globalCliMeta.description || command.meta?.description || routerMeta?.description
5743
- });
5744
- debugLog("RPC CLI created from command router, running with argv:", process$1.argv.slice(2));
5745
- await rpcCli.run({
5746
- argv: process$1.argv.slice(2),
5747
- logger: {
5748
- info: console.log,
5749
- error: console.error
5750
- },
5751
- process: {
5752
- exit: process$1.exit
5753
- }
5754
- });
5755
- return;
5756
- }
5757
4234
  if (typeof command.onLauncherInit === "function") {
5758
4235
  try {
5759
4236
  await command.onLauncherInit();
@@ -5767,7 +4244,7 @@ function createCli(options, legacyParserOptions) {
5767
4244
  if (!parserOptions.fileBased && !command.commands) {
5768
4245
  const mainEntry = process$1.argv[1] ? path.dirname(path.resolve(process$1.argv[1])) : process$1.cwd();
5769
4246
  const defaultCmdsRoot = path.join(mainEntry, "src", "app");
5770
- const exists = await fs.pathExists(defaultCmdsRoot);
4247
+ const exists = await pathExists(defaultCmdsRoot);
5771
4248
  const finalCmdsRoot = exists ? defaultCmdsRoot : path.join(mainEntry, "app");
5772
4249
  parserOptions.fileBased = {
5773
4250
  enable: true,
@@ -5776,10 +4253,10 @@ function createCli(options, legacyParserOptions) {
5776
4253
  }
5777
4254
  const rawArgv = process$1.argv.slice(2);
5778
4255
  const autoExit = parserOptions.autoExit !== false;
5779
- if (!(parserOptions.fileBased?.enable || command.commands && Object.keys(command.commands).length > 0 || command.run || command.router)) {
4256
+ if (!(parserOptions.fileBased?.enable || command.commands && Object.keys(command.commands).length > 0 || command.run)) {
5780
4257
  relinka(
5781
4258
  "error",
5782
- "Invalid CLI configuration: No file-based commands, subCommands, run() handler, or router are defined. This CLI will not do anything.\n\u2502 To fix: add file-based commands (./app), or provide at least one subCommand, a run() handler, or a router."
4259
+ "Invalid CLI configuration: No file-based commands, subCommands, or run() handler are defined. This CLI will not do anything.\n\u2502 To fix: add file-based commands (./app), or provide at least one subCommand, or a run() handler."
5783
4260
  );
5784
4261
  process$1.exit(1);
5785
4262
  }
@@ -5961,7 +4438,7 @@ async function runFileBasedSubCmd(subName, argv, fileCmdOpts, parserOptions, par
5961
4438
  if (args.length === 0 || args[0] && isFlag(args[0])) {
5962
4439
  const possibleFiles2 = [path.join(baseDir, "cmd.js"), path.join(baseDir, "cmd.ts")];
5963
4440
  for (const file of possibleFiles2) {
5964
- if (await fs.pathExists(file)) {
4441
+ if (await pathExists(file)) {
5965
4442
  return { importPath: file, leftoverArgv: args };
5966
4443
  }
5967
4444
  }
@@ -5973,12 +4450,12 @@ Info for this CLI's developer: No valid command file found in ${baseDir}`
5973
4450
  );
5974
4451
  }
5975
4452
  const nextDir = path.join(baseDir, args[0] || "");
5976
- if (await fs.pathExists(nextDir) && (await fs.stat(nextDir)).isDirectory()) {
4453
+ if (await pathExists(nextDir) && (await stat(nextDir)).isDirectory()) {
5977
4454
  return resolveCmdPath(nextDir, args.slice(1));
5978
4455
  }
5979
4456
  const possibleFiles = [path.join(baseDir, "cmd.js"), path.join(baseDir, "cmd.ts")];
5980
4457
  for (const file of possibleFiles) {
5981
- if (await fs.pathExists(file)) {
4458
+ if (await pathExists(file)) {
5982
4459
  return { importPath: file, leftoverArgv: args };
5983
4460
  }
5984
4461
  }
@@ -5990,7 +4467,7 @@ Info for this CLI's developer: No valid command file found in ${baseDir}`
5990
4467
  );
5991
4468
  }
5992
4469
  const startDir = path.join(fileCmdOpts.cmdsRootPath, subName);
5993
- if (!await fs.pathExists(startDir) || !(await fs.stat(startDir)).isDirectory()) {
4470
+ if (!await pathExists(startDir) || !(await stat(startDir)).isDirectory()) {
5994
4471
  const attempted = [subName, ...argv].join(" ");
5995
4472
  const expectedPath = path.relative(
5996
4473
  process$1.cwd(),
@@ -6113,7 +4590,7 @@ async function runCommandWithArgs(command, argv, parserOptions, globalCliMeta, r
6113
4590
  if (command.run) {
6114
4591
  await command.run(ctx);
6115
4592
  } else {
6116
- const isDispatcher = parserOptions.fileBased?.enable || command.commands && Object.keys(command.commands).length > 0 || command.router;
4593
+ const isDispatcher = parserOptions.fileBased?.enable || command.commands && Object.keys(command.commands).length > 0;
6117
4594
  const noSubcommandArgInCurrentCall = !argv.some((arg) => !isFlag(arg));
6118
4595
  if (isDispatcher && noSubcommandArgInCurrentCall) {
6119
4596
  relinka("warn", "Please specify a command");
@@ -6250,110 +4727,6 @@ function normalizeArgv(argv) {
6250
4727
  }
6251
4728
  return normalized;
6252
4729
  }
6253
- async function runCmdWithSubcommands(command, argv = [], parserOptions = {}) {
6254
- const normalizedArgv = normalizeArgv(argv);
6255
- let currentCommand = command;
6256
- let currentArgv = normalizedArgv;
6257
- while (currentCommand.commands && currentArgv.length > 0 && currentArgv[0] && !isFlag(currentArgv[0])) {
6258
- const [maybeSub, ...restArgv] = currentArgv;
6259
- let subSpec;
6260
- for (const [key, spec] of Object.entries(currentCommand.commands)) {
6261
- if (key === maybeSub) {
6262
- subSpec = spec;
6263
- break;
6264
- }
6265
- try {
6266
- const cmd = await loadSubCommand(spec);
6267
- if (cmd.meta?.aliases?.includes(maybeSub)) {
6268
- subSpec = spec;
6269
- break;
6270
- }
6271
- } catch (err) {
6272
- debugLog(`Error checking alias for command ${key}:`, err);
6273
- }
6274
- }
6275
- if (!subSpec) break;
6276
- const loaded = await loadSubCommand(subSpec);
6277
- currentCommand = loaded;
6278
- currentArgv = restArgv;
6279
- }
6280
- return await runCommandWithArgs(currentCommand, currentArgv, {
6281
- ...parserOptions,
6282
- autoExit: false
6283
- // Don't exit process in programmatic usage
6284
- });
6285
- }
6286
- async function runCmd(command, argv = [], parserOptions = {}) {
6287
- const normalizedArgv = normalizeArgv(argv);
6288
- const booleanKeys = Object.keys(command.args || {}).filter(
6289
- (k) => command.args?.[k]?.type === "boolean"
6290
- );
6291
- const defaultMap = {};
6292
- for (const [argKey, def] of Object.entries(command.args || {})) {
6293
- if (def.type === "boolean") {
6294
- defaultMap[argKey] = def.default !== void 0 ? def.default : false;
6295
- } else if (def.default !== void 0) {
6296
- defaultMap[argKey] = def.type === "array" && typeof def.default === "string" ? [def.default] : def.default;
6297
- }
6298
- }
6299
- const mergedParserOptions = {
6300
- ...parserOptions,
6301
- boolean: [...parserOptions.boolean || [], ...booleanKeys],
6302
- defaults: { ...defaultMap, ...parserOptions.defaults || {} }
6303
- };
6304
- const parsed = reliArgParser(normalizedArgv, mergedParserOptions);
6305
- debugLog("Parsed arguments (runCmd):", parsed);
6306
- const finalArgs = {};
6307
- const positionalKeys = Object.keys(command.args || {}).filter(
6308
- (k) => command.args?.[k]?.type === "positional"
6309
- );
6310
- const leftoverPositionals = [...parsed._ || []];
6311
- for (let i = 0; i < positionalKeys.length; i++) {
6312
- const key = positionalKeys[i];
6313
- if (!key || !command.args) continue;
6314
- const def = command.args[key];
6315
- const val = leftoverPositionals[i];
6316
- finalArgs[key] = val != null && def ? castArgValue(def, val, key) : def?.default;
6317
- }
6318
- const otherKeys = Object.keys(command.args || {}).filter(
6319
- (k) => command.args?.[k]?.type !== "positional"
6320
- );
6321
- for (const key of otherKeys) {
6322
- const def = command.args?.[key];
6323
- if (!def) continue;
6324
- let rawVal = parsed[key];
6325
- if (def.type === "array" && rawVal !== void 0 && !Array.isArray(rawVal)) {
6326
- rawVal = [rawVal];
6327
- }
6328
- const casted = rawVal !== void 0 ? castArgValue(def, rawVal, key) : def.default;
6329
- const argUsed = rawVal !== void 0 && (def.type === "boolean" ? casted === true : true);
6330
- if (casted == null && def.required) {
6331
- throw new Error(`Missing required argument: --${key}`);
6332
- }
6333
- if (argUsed && def.dependencies?.length) {
6334
- const missingDeps = def.dependencies.filter((d) => {
6335
- const depVal = parsed[d] ?? defaultMap[d];
6336
- return !depVal;
6337
- });
6338
- if (missingDeps.length) {
6339
- const depsList = missingDeps.map((d) => `--${d}`).join(", ");
6340
- throw new Error(
6341
- `Argument --${key} can only be used when ${depsList} ${missingDeps.length === 1 ? "is" : "are"} set`
6342
- );
6343
- }
6344
- }
6345
- finalArgs[key] = def.type === "boolean" ? Boolean(casted) : casted;
6346
- }
6347
- const ctx = {
6348
- args: finalArgs,
6349
- raw: argv
6350
- };
6351
- if (typeof command.run === "function") {
6352
- await command.run(ctx);
6353
- } else {
6354
- throw new Error("Command has no run() handler.");
6355
- }
6356
- }
6357
4730
  function getParsedContext(command, argv, parserOptions) {
6358
4731
  const normalizedArgv = normalizeArgv(argv);
6359
4732
  const booleanKeys = Object.keys(command.args || {}).filter(
@@ -6409,7 +4782,7 @@ async function resolveFileBasedCommandPath(cmdsRoot, argv) {
6409
4782
  let leftover = [...argv];
6410
4783
  while (leftover.length > 0 && leftover[0] && !isFlag(leftover[0])) {
6411
4784
  const nextDir = path.join(currentDir, leftover[0]);
6412
- if (await fs.pathExists(nextDir) && (await fs.stat(nextDir)).isDirectory()) {
4785
+ if (await pathExists(nextDir) && (await stat(nextDir)).isDirectory()) {
6413
4786
  currentDir = nextDir;
6414
4787
  pathSegments.push(leftover[0]);
6415
4788
  leftover = leftover.slice(1);
@@ -6419,7 +4792,7 @@ async function resolveFileBasedCommandPath(cmdsRoot, argv) {
6419
4792
  }
6420
4793
  for (const fname of ["cmd.ts", "cmd.js"]) {
6421
4794
  const fpath = path.join(currentDir, fname);
6422
- if (await fs.pathExists(fpath)) {
4795
+ if (await pathExists(fpath)) {
6423
4796
  const imported = await import(path.resolve(fpath));
6424
4797
  if (imported.default) {
6425
4798
  return {
@@ -6461,65 +4834,6 @@ function levenshteinDistance(a, b) {
6461
4834
  return matrix[b.length][a.length];
6462
4835
  }
6463
4836
 
6464
- function argsToStringArray(args) {
6465
- const result = [];
6466
- for (const [key, value] of Object.entries(args)) {
6467
- if (value === void 0 || value === null) continue;
6468
- if (typeof value === "boolean") {
6469
- result.push(`--${key}=${value}`);
6470
- } else if (Array.isArray(value)) {
6471
- result.push(`--${key}=${value.join(",")}`);
6472
- } else {
6473
- result.push(`--${key}=${String(value)}`);
6474
- }
6475
- }
6476
- return result;
6477
- }
6478
- async function createCallCmd() {
6479
- return async function callCmd(cmdName, args) {
6480
- try {
6481
- const command = await loadCommand(cmdName);
6482
- const stringArgs = args ? argsToStringArray(args) : [];
6483
- await runCmd(command, stringArgs);
6484
- } catch (error) {
6485
- console.error(`Error running command '${String(cmdName)}':`, error);
6486
- throw error;
6487
- }
6488
- };
6489
- }
6490
- async function createGetTypedCmd() {
6491
- return async function getTypedCmd(cmdName) {
6492
- const command = await loadCommand(cmdName);
6493
- return {
6494
- command,
6495
- run: async (args) => {
6496
- const stringArgs = args ? argsToStringArray(args) : [];
6497
- await runCmd(command, stringArgs);
6498
- }
6499
- };
6500
- };
6501
- }
6502
- async function callCmdImpl(cmdName, args) {
6503
- try {
6504
- const command = await loadCommand(cmdName);
6505
- const stringArgs = args ? argsToStringArray(args) : [];
6506
- await runCmd(command, stringArgs);
6507
- } catch (error) {
6508
- console.error(`Error running command '${String(cmdName)}':`, error);
6509
- throw error;
6510
- }
6511
- }
6512
- async function getTypedCmdImpl(cmdName) {
6513
- const command = await loadCommand(cmdName);
6514
- return {
6515
- command,
6516
- run: async (args) => {
6517
- const stringArgs = args ? argsToStringArray(args) : [];
6518
- await runCmd(command, stringArgs);
6519
- }
6520
- };
6521
- }
6522
-
6523
4837
  const runMain = createCli;
6524
4838
 
6525
4839
  const log = relinka;
@@ -8462,4 +6776,4 @@ function normalizeName(name) {
8462
6776
  return lastSegment.replace(/[^a-zA-Z0-9-]/g, "");
8463
6777
  }
8464
6778
 
8465
- export { CANCEL, CliValidationError, FailedToExitError, StandardSchemaV1Error, TrpcCommand, addCompletions, animateText, animationMap, anykeyPrompt, applyVariant, argsToStringArray, bar, block, breakLines, callCmdImpl, cancel, colorMap, colorize, commandToJSON, completePrompt, confirm, confirmPrompt, countLines$1 as countLines, createAsciiArt, createCallCmd, createCancel, createCli, createGetTypedCmd, createMultiStep, createRpcCli, createShadowCommand, createStep, datePrompt, defineArgs, defineCommand, deleteLastLine, deleteLastLines, endPrompt, errorHandler, fallbackSymbols, figures, flattenedProperties, fmt, getColumns, getDescription, getEnumChoices, getExactTerminalWidth, getSchemaTypes, getTerminalHeight, getTerminalWidth$1 as getTerminalWidth, getTypedCmdImpl, group, incompatiblePropertyPairs, input, inputPrompt, intro, introPrompt, isCancel, isOrpcRouter, isTerminalInteractive, isTrpc11Procedure, isTrpc11Router, isValidName, isValidVariant, isWindows, lineByLineConsoleLogger, lineByLineLogger, loadCommand, log, looksLikeInstanceof, looksLikeStandardSchema, looksLikeStandardSchemaFailure, mainSymbols, msg, msgUndo, msgUndoAll, multiselect, multiselectPrompt, nextStepsPrompt, normalizeName, numMultiSelectPrompt, numSelectPrompt, numberPrompt, outro, outroPrompt, parseProcedureInputs, parseRouter, password, pm, prettifyStandardSchemaError, preventUnsupportedTTY, preventWindowsHomeDirRoot, preventWrongTerminalSize, printLineBar, promptify, relinkaAsyncByRemptsDeprecated, relinkaByRemptsDeprecated, reliversePrompts, removeCursor, renderEndLine, renderEndLineInput, restoreCursor, resultPrompt, runCmd, runCmdWithSubcommands, runMain, select, selectPrompt, selectSimple, setRawMode, showUsage, spinner, startEditor, startPrompt, streamText, streamTextBox, streamTextWithSpinner, symbols, taskProgressPrompt, taskSpinPrompt, text, throwError, toBaseColor, toDotPath, toSolidColor, togglePrompt, typographyMap, useSpinner, variantMap };
6779
+ export { CANCEL, animateText, animationMap, anykeyPrompt, applyVariant, bar, block, breakLines, callCmd, cancel, colorMap, colorize, completePrompt, confirm, confirmPrompt, countLines$1 as countLines, createAsciiArt, createCancel, createCli, createMultiStep, createStep, datePrompt, defineArgs, defineCommand, deleteLastLine, deleteLastLines, endPrompt, errorHandler, fallbackSymbols, figures, fmt, getColumns, getExactTerminalWidth, getTerminalHeight, getTerminalWidth$1 as getTerminalWidth, group, input, inputPrompt, intro, introPrompt, isCancel, isTerminalInteractive, isValidName, isValidVariant, isWindows, log, mainSymbols, msg, msgUndo, msgUndoAll, multiselect, multiselectPrompt, nextStepsPrompt, normalizeName, numMultiSelectPrompt, numSelectPrompt, numberPrompt, outro, outroPrompt, password, pm, preventUnsupportedTTY, preventWindowsHomeDirRoot, preventWrongTerminalSize, printLineBar, relinkaAsyncByRemptsDeprecated, relinkaByRemptsDeprecated, reliversePrompts, removeCursor, renderEndLine, renderEndLineInput, restoreCursor, resultPrompt, runMain, select, selectPrompt, selectSimple, setRawMode, showUsage, spinner, startEditor, startPrompt, streamText, streamTextBox, streamTextWithSpinner, symbols, taskProgressPrompt, taskSpinPrompt, text, throwError, toBaseColor, toSolidColor, togglePrompt, typographyMap, useSpinner, variantMap };