politty 0.5.1 → 0.7.0

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.
Files changed (82) hide show
  1. package/README.md +47 -0
  2. package/dist/{arg-registry-6E0WHOh_.d.ts → arg-registry-DDJpsUea.d.cts} +47 -23
  3. package/dist/arg-registry-DDJpsUea.d.cts.map +1 -0
  4. package/dist/{arg-registry--NRaNFJM.d.cts → arg-registry-DDJpsUea.d.ts} +47 -23
  5. package/dist/arg-registry-DDJpsUea.d.ts.map +1 -0
  6. package/dist/augment.d.cts +1 -1
  7. package/dist/augment.d.ts +1 -1
  8. package/dist/cli.cjs +54 -0
  9. package/dist/cli.cjs.map +1 -0
  10. package/dist/cli.d.cts +1 -0
  11. package/dist/cli.d.ts +1 -0
  12. package/dist/cli.js +55 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/completion/index.cjs +6 -1
  15. package/dist/completion/index.d.cts +3 -3
  16. package/dist/completion/index.d.ts +3 -3
  17. package/dist/completion/index.js +2 -2
  18. package/dist/{completion-BFOAOg95.cjs → completion-CLHO3Xaz.cjs} +1812 -337
  19. package/dist/completion-CLHO3Xaz.cjs.map +1 -0
  20. package/dist/{completion-K5LGh1hO.js → completion-DHnVx9Zk.js} +1786 -340
  21. package/dist/completion-DHnVx9Zk.js.map +1 -0
  22. package/dist/docs/index.cjs +3 -3
  23. package/dist/docs/index.cjs.map +1 -1
  24. package/dist/docs/index.d.cts +1 -1
  25. package/dist/docs/index.d.cts.map +1 -1
  26. package/dist/docs/index.d.ts +1 -1
  27. package/dist/docs/index.d.ts.map +1 -1
  28. package/dist/docs/index.js +3 -3
  29. package/dist/docs/index.js.map +1 -1
  30. package/dist/{index-Cg8qstsT.d.cts → index-DKGn3lIl.d.ts} +119 -4
  31. package/dist/index-DKGn3lIl.d.ts.map +1 -0
  32. package/dist/{index-O3yn97Ed.d.ts → index-WyViqW59.d.cts} +119 -4
  33. package/dist/index-WyViqW59.d.cts.map +1 -0
  34. package/dist/index.cjs +4 -3
  35. package/dist/index.d.cts +3 -3
  36. package/dist/index.d.cts.map +1 -1
  37. package/dist/index.d.ts +3 -3
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +4 -4
  40. package/dist/{log-collector-Cu6MCtAx.js → log-collector-DK32-73m.js} +1 -1
  41. package/dist/{log-collector-Cu6MCtAx.js.map → log-collector-DK32-73m.js.map} +1 -1
  42. package/dist/{log-collector-Cd2_mv87.cjs → log-collector-DUqC427m.cjs} +1 -1
  43. package/dist/{log-collector-Cd2_mv87.cjs.map → log-collector-DUqC427m.cjs.map} +1 -1
  44. package/dist/prompt/clack/index.cjs +1 -2
  45. package/dist/prompt/clack/index.cjs.map +1 -1
  46. package/dist/prompt/clack/index.d.cts +1 -1
  47. package/dist/prompt/clack/index.d.ts +1 -1
  48. package/dist/prompt/clack/index.js +1 -1
  49. package/dist/prompt/index.cjs +1 -1
  50. package/dist/prompt/index.d.cts +1 -1
  51. package/dist/prompt/index.d.cts.map +1 -1
  52. package/dist/prompt/index.d.ts +1 -1
  53. package/dist/prompt/index.d.ts.map +1 -1
  54. package/dist/prompt/index.js +1 -1
  55. package/dist/prompt/inquirer/index.cjs +1 -2
  56. package/dist/prompt/inquirer/index.cjs.map +1 -1
  57. package/dist/prompt/inquirer/index.d.cts +1 -1
  58. package/dist/prompt/inquirer/index.d.ts +1 -1
  59. package/dist/prompt/inquirer/index.js +1 -1
  60. package/dist/{prompt-aXfSf27y.cjs → prompt-Bs9e-Em3.cjs} +1 -1
  61. package/dist/{prompt-aXfSf27y.cjs.map → prompt-Bs9e-Em3.cjs.map} +1 -1
  62. package/dist/{prompt-BKHqGrFw.js → prompt-Cc8Tfmdv.js} +1 -1
  63. package/dist/{prompt-BKHqGrFw.js.map → prompt-Cc8Tfmdv.js.map} +1 -1
  64. package/dist/{runner-BmSEiD9A.js → runner-D43SkHt5.js} +121 -20
  65. package/dist/runner-D43SkHt5.js.map +1 -0
  66. package/dist/{runner-CRZ_7Y9i.cjs → runner-DvFvokV6.cjs} +121 -20
  67. package/dist/runner-DvFvokV6.cjs.map +1 -0
  68. package/dist/{schema-extractor-SLPgBNgZ.cjs → schema-extractor-BxSRwLrx.cjs} +1 -2
  69. package/dist/schema-extractor-BxSRwLrx.cjs.map +1 -0
  70. package/dist/{schema-extractor-C50R-1re.js → schema-extractor-Dqe7_kyQ.js} +1 -1
  71. package/dist/schema-extractor-Dqe7_kyQ.js.map +1 -0
  72. package/package.json +15 -12
  73. package/dist/arg-registry--NRaNFJM.d.cts.map +0 -1
  74. package/dist/arg-registry-6E0WHOh_.d.ts.map +0 -1
  75. package/dist/completion-BFOAOg95.cjs.map +0 -1
  76. package/dist/completion-K5LGh1hO.js.map +0 -1
  77. package/dist/index-Cg8qstsT.d.cts.map +0 -1
  78. package/dist/index-O3yn97Ed.d.ts.map +0 -1
  79. package/dist/runner-BmSEiD9A.js.map +0 -1
  80. package/dist/runner-CRZ_7Y9i.cjs.map +0 -1
  81. package/dist/schema-extractor-C50R-1re.js.map +0 -1
  82. package/dist/schema-extractor-SLPgBNgZ.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"log-collector-Cd2_mv87.cjs","names":[],"sources":["../src/executor/log-collector.ts"],"sourcesContent":["import type { CollectedLogs, LogEntry, LogLevel, LogStream } from \"../types.js\";\n\n/**\n * Mapping from log level to output stream\n */\nconst LOG_STREAM_MAP: Record<LogLevel, LogStream> = {\n log: \"stdout\",\n info: \"stdout\",\n debug: \"stdout\",\n warn: \"stderr\",\n error: \"stderr\",\n};\n\n/**\n * All log levels\n */\nconst ALL_LOG_LEVELS: LogLevel[] = [\"log\", \"info\", \"debug\", \"warn\", \"error\"];\n\n/**\n * Options for log collector\n */\nexport interface LogCollectorOptions {\n /** Log levels to capture (default: all) */\n levels?: LogLevel[];\n /** Whether to call original console methods (default: true) */\n passthrough?: boolean;\n}\n\n/**\n * Log collector that intercepts console methods\n */\nexport interface LogCollector {\n /** Get collected logs */\n getLogs: () => CollectedLogs;\n /** Start collecting logs */\n start: () => void;\n /** Stop collecting and restore original console methods */\n stop: () => void;\n}\n\n/**\n * Format console arguments to string\n */\nexport function formatArgs(args: unknown[]): string {\n return args\n .map((arg) => {\n if (arg instanceof Error) {\n return arg.message;\n }\n if (typeof arg === \"object\" && arg !== null) {\n try {\n return JSON.stringify(arg);\n } catch {\n return String(arg);\n }\n }\n return String(arg);\n })\n .join(\" \");\n}\n\n/**\n * Create a log collector that intercepts console methods\n *\n * @param options - Options for the log collector\n * @returns A log collector instance\n *\n * @example\n * ```ts\n * const collector = createLogCollector();\n * collector.start();\n *\n * console.log(\"Info message\");\n * console.error(\"Something went wrong\");\n * console.warn(\"This is a warning\");\n *\n * collector.stop();\n * const logs = collector.getLogs();\n * // {\n * // entries: [\n * // { message: \"Info message\", level: \"log\", stream: \"stdout\", timestamp: ... },\n * // { message: \"Something went wrong\", level: \"error\", stream: \"stderr\", timestamp: ... },\n * // { message: \"This is a warning\", level: \"warn\", stream: \"stderr\", timestamp: ... }\n * // ]\n * // }\n * ```\n */\nexport function createLogCollector(options: LogCollectorOptions = {}): LogCollector {\n const entries: LogEntry[] = [];\n const levels = options.levels ?? ALL_LOG_LEVELS;\n const passthrough = options.passthrough ?? true;\n\n let originals: Record<LogLevel, typeof console.log> | null = null;\n\n const createInterceptor = (level: LogLevel, original: typeof console.log) => {\n return (...args: unknown[]) => {\n entries.push({\n message: formatArgs(args),\n timestamp: new Date(),\n level,\n stream: LOG_STREAM_MAP[level],\n });\n if (passthrough) {\n original.apply(console, args);\n }\n };\n };\n\n return {\n getLogs() {\n return { entries: [...entries] };\n },\n start() {\n if (originals !== null) {\n // Already started\n return;\n }\n originals = {\n log: console.log,\n info: console.info,\n debug: console.debug,\n warn: console.warn,\n error: console.error,\n };\n for (const level of levels) {\n console[level] = createInterceptor(level, originals[level]);\n }\n },\n stop() {\n if (originals === null) {\n return;\n }\n for (const level of levels) {\n console[level] = originals[level];\n }\n originals = null;\n },\n };\n}\n\n/**\n * Merge multiple CollectedLogs into one (sorted by timestamp)\n */\nexport function mergeLogs(...logsArray: CollectedLogs[]): CollectedLogs {\n return {\n entries: logsArray\n .flatMap((l) => l.entries)\n .sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime()),\n };\n}\n\n/**\n * Create an empty CollectedLogs object\n */\nexport function emptyLogs(): CollectedLogs {\n return { entries: [] };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,MAAM,iBAA8C;CAClD,KAAK;CACL,MAAM;CACN,OAAO;CACP,MAAM;CACN,OAAO;AACT;;;;AAKA,MAAM,iBAA6B;CAAC;CAAO;CAAQ;CAAS;CAAQ;AAAO;;;;AA2B3E,SAAgB,WAAW,MAAyB;CAClD,OAAO,KACJ,KAAK,QAAQ;EACZ,IAAI,eAAe,OACjB,OAAO,IAAI;EAEb,IAAI,OAAO,QAAQ,YAAY,QAAQ,MACrC,IAAI;GACF,OAAO,KAAK,UAAU,GAAG;EAC3B,QAAQ;GACN,OAAO,OAAO,GAAG;EACnB;EAEF,OAAO,OAAO,GAAG;CACnB,CAAC,EACA,KAAK,GAAG;AACb;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,mBAAmB,UAA+B,CAAC,GAAiB;CAClF,MAAM,UAAsB,CAAC;CAC7B,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,cAAc,QAAQ,eAAe;CAE3C,IAAI,YAAyD;CAE7D,MAAM,qBAAqB,OAAiB,aAAiC;EAC3E,QAAQ,GAAG,SAAoB;GAC7B,QAAQ,KAAK;IACX,SAAS,WAAW,IAAI;IACxB,2BAAW,IAAI,KAAK;IACpB;IACA,QAAQ,eAAe;GACzB,CAAC;GACD,IAAI,aACF,SAAS,MAAM,SAAS,IAAI;EAEhC;CACF;CAEA,OAAO;EACL,UAAU;GACR,OAAO,EAAE,SAAS,CAAC,GAAG,OAAO,EAAE;EACjC;EACA,QAAQ;GACN,IAAI,cAAc,MAEhB;GAEF,YAAY;IACV,KAAK,QAAQ;IACb,MAAM,QAAQ;IACd,OAAO,QAAQ;IACf,MAAM,QAAQ;IACd,OAAO,QAAQ;GACjB;GACA,KAAK,MAAM,SAAS,QAClB,QAAQ,SAAS,kBAAkB,OAAO,UAAU,MAAM;EAE9D;EACA,OAAO;GACL,IAAI,cAAc,MAChB;GAEF,KAAK,MAAM,SAAS,QAClB,QAAQ,SAAS,UAAU;GAE7B,YAAY;EACd;CACF;AACF;;;;AAKA,SAAgB,UAAU,GAAG,WAA2C;CACtE,OAAO,EACL,SAAS,UACN,SAAS,MAAM,EAAE,OAAO,EACxB,MAAM,GAAG,MAAM,EAAE,UAAU,QAAQ,IAAI,EAAE,UAAU,QAAQ,CAAC,EACjE;AACF;;;;AAKA,SAAgB,YAA2B;CACzC,OAAO,EAAE,SAAS,CAAC,EAAE;AACvB"}
1
+ {"version":3,"file":"log-collector-DUqC427m.cjs","names":[],"sources":["../src/executor/log-collector.ts"],"sourcesContent":["import type { CollectedLogs, LogEntry, LogLevel, LogStream } from \"../types.js\";\n\n/**\n * Mapping from log level to output stream\n */\nconst LOG_STREAM_MAP: Record<LogLevel, LogStream> = {\n log: \"stdout\",\n info: \"stdout\",\n debug: \"stdout\",\n warn: \"stderr\",\n error: \"stderr\",\n};\n\n/**\n * All log levels\n */\nconst ALL_LOG_LEVELS: LogLevel[] = [\"log\", \"info\", \"debug\", \"warn\", \"error\"];\n\n/**\n * Options for log collector\n */\nexport interface LogCollectorOptions {\n /** Log levels to capture (default: all) */\n levels?: LogLevel[];\n /** Whether to call original console methods (default: true) */\n passthrough?: boolean;\n}\n\n/**\n * Log collector that intercepts console methods\n */\nexport interface LogCollector {\n /** Get collected logs */\n getLogs: () => CollectedLogs;\n /** Start collecting logs */\n start: () => void;\n /** Stop collecting and restore original console methods */\n stop: () => void;\n}\n\n/**\n * Format console arguments to string\n */\nexport function formatArgs(args: unknown[]): string {\n return args\n .map((arg) => {\n if (arg instanceof Error) {\n return arg.message;\n }\n if (typeof arg === \"object\" && arg !== null) {\n try {\n return JSON.stringify(arg);\n } catch {\n return String(arg);\n }\n }\n return String(arg);\n })\n .join(\" \");\n}\n\n/**\n * Create a log collector that intercepts console methods\n *\n * @param options - Options for the log collector\n * @returns A log collector instance\n *\n * @example\n * ```ts\n * const collector = createLogCollector();\n * collector.start();\n *\n * console.log(\"Info message\");\n * console.error(\"Something went wrong\");\n * console.warn(\"This is a warning\");\n *\n * collector.stop();\n * const logs = collector.getLogs();\n * // {\n * // entries: [\n * // { message: \"Info message\", level: \"log\", stream: \"stdout\", timestamp: ... },\n * // { message: \"Something went wrong\", level: \"error\", stream: \"stderr\", timestamp: ... },\n * // { message: \"This is a warning\", level: \"warn\", stream: \"stderr\", timestamp: ... }\n * // ]\n * // }\n * ```\n */\nexport function createLogCollector(options: LogCollectorOptions = {}): LogCollector {\n const entries: LogEntry[] = [];\n const levels = options.levels ?? ALL_LOG_LEVELS;\n const passthrough = options.passthrough ?? true;\n\n let originals: Record<LogLevel, typeof console.log> | null = null;\n\n const createInterceptor = (level: LogLevel, original: typeof console.log) => {\n return (...args: unknown[]) => {\n entries.push({\n message: formatArgs(args),\n timestamp: new Date(),\n level,\n stream: LOG_STREAM_MAP[level],\n });\n if (passthrough) {\n original.apply(console, args);\n }\n };\n };\n\n return {\n getLogs() {\n return { entries: [...entries] };\n },\n start() {\n if (originals !== null) {\n // Already started\n return;\n }\n originals = {\n log: console.log,\n info: console.info,\n debug: console.debug,\n warn: console.warn,\n error: console.error,\n };\n for (const level of levels) {\n console[level] = createInterceptor(level, originals[level]);\n }\n },\n stop() {\n if (originals === null) {\n return;\n }\n for (const level of levels) {\n console[level] = originals[level];\n }\n originals = null;\n },\n };\n}\n\n/**\n * Merge multiple CollectedLogs into one (sorted by timestamp)\n */\nexport function mergeLogs(...logsArray: CollectedLogs[]): CollectedLogs {\n return {\n entries: logsArray\n .flatMap((l) => l.entries)\n .sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime()),\n };\n}\n\n/**\n * Create an empty CollectedLogs object\n */\nexport function emptyLogs(): CollectedLogs {\n return { entries: [] };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,MAAM,iBAA8C;CAClD,KAAK;CACL,MAAM;CACN,OAAO;CACP,MAAM;CACN,OAAO;AACT;;;;AAKA,MAAM,iBAA6B;CAAC;CAAO;CAAQ;CAAS;CAAQ;AAAO;;;;AA2B3E,SAAgB,WAAW,MAAyB;CAClD,OAAO,KACJ,KAAK,QAAQ;EACZ,IAAI,eAAe,OACjB,OAAO,IAAI;EAEb,IAAI,OAAO,QAAQ,YAAY,QAAQ,MACrC,IAAI;GACF,OAAO,KAAK,UAAU,GAAG;EAC3B,QAAQ;GACN,OAAO,OAAO,GAAG;EACnB;EAEF,OAAO,OAAO,GAAG;CACnB,CAAC,CAAC,CACD,KAAK,GAAG;AACb;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,mBAAmB,UAA+B,CAAC,GAAiB;CAClF,MAAM,UAAsB,CAAC;CAC7B,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,cAAc,QAAQ,eAAe;CAE3C,IAAI,YAAyD;CAE7D,MAAM,qBAAqB,OAAiB,aAAiC;EAC3E,QAAQ,GAAG,SAAoB;GAC7B,QAAQ,KAAK;IACX,SAAS,WAAW,IAAI;IACxB,2BAAW,IAAI,KAAK;IACpB;IACA,QAAQ,eAAe;GACzB,CAAC;GACD,IAAI,aACF,SAAS,MAAM,SAAS,IAAI;EAEhC;CACF;CAEA,OAAO;EACL,UAAU;GACR,OAAO,EAAE,SAAS,CAAC,GAAG,OAAO,EAAE;EACjC;EACA,QAAQ;GACN,IAAI,cAAc,MAEhB;GAEF,YAAY;IACV,KAAK,QAAQ;IACb,MAAM,QAAQ;IACd,OAAO,QAAQ;IACf,MAAM,QAAQ;IACd,OAAO,QAAQ;GACjB;GACA,KAAK,MAAM,SAAS,QAClB,QAAQ,SAAS,kBAAkB,OAAO,UAAU,MAAM;EAE9D;EACA,OAAO;GACL,IAAI,cAAc,MAChB;GAEF,KAAK,MAAM,SAAS,QAClB,QAAQ,SAAS,UAAU;GAE7B,YAAY;EACd;CACF;AACF;;;;AAKA,SAAgB,UAAU,GAAG,WAA2C;CACtE,OAAO,EACL,SAAS,UACN,SAAS,MAAM,EAAE,OAAO,CAAC,CACzB,MAAM,GAAG,MAAM,EAAE,UAAU,QAAQ,IAAI,EAAE,UAAU,QAAQ,CAAC,EACjE;AACF;;;;AAKA,SAAgB,YAA2B;CACzC,OAAO,EAAE,SAAS,CAAC,EAAE;AACvB"}
@@ -1,6 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_log_collector = require('../../log-collector-Cd2_mv87.cjs');
3
- const require_prompt = require('../../prompt-aXfSf27y.cjs');
2
+ const require_prompt = require('../../prompt-Bs9e-Em3.cjs');
4
3
  let _clack_prompts = require("@clack/prompts");
5
4
 
6
5
  //#region src/prompt/clack/index.ts
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["isCancel","promptMissingArgs"],"sources":["../../../src/prompt/clack/index.ts"],"sourcesContent":["import { confirm, isCancel, password, select, text } from \"@clack/prompts\";\nimport type { PromptResolver } from \"../../types.js\";\nimport { promptMissingArgs } from \"../index.js\";\nimport type { PromptAdapter } from \"../types.js\";\n\nfunction createClackAdapter(): PromptAdapter {\n return {\n text: (config) =>\n text({\n message: config.message,\n ...(config.placeholder !== undefined && { placeholder: config.placeholder }),\n }),\n password: (config) => password(config),\n confirm: (config) => confirm(config),\n select: (config) => select(config),\n isCancelled: isCancel,\n };\n}\n\n/**\n * Prompt resolver backed by @clack/prompts.\n *\n * @example\n * ```ts\n * import { runMain, defineCommand } from \"politty\";\n * import { prompt } from \"politty/prompt/clack\";\n *\n * runMain(cmd, { version: \"1.0.0\", prompt });\n * ```\n */\nexport const prompt: PromptResolver = (rawArgs, extracted) =>\n promptMissingArgs(rawArgs, extracted, { adapter: createClackAdapter() });\n"],"mappings":";;;;;;AAKA,SAAS,qBAAoC;CAC3C,OAAO;EACL,OAAO,oCACA;GACH,SAAS,OAAO;GAChB,GAAI,OAAO,gBAAgB,UAAa,EAAE,aAAa,OAAO,YAAY;EAC5E,CAAC;EACH,WAAW,wCAAoB,MAAM;EACrC,UAAU,uCAAmB,MAAM;EACnC,SAAS,sCAAkB,MAAM;EACjC,aAAaA;CACf;AACF;;;;;;;;;;;;AAaA,MAAa,UAA0B,SAAS,cAC9CC,iCAAkB,SAAS,WAAW,EAAE,SAAS,mBAAmB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.cjs","names":["isCancel","promptMissingArgs"],"sources":["../../../src/prompt/clack/index.ts"],"sourcesContent":["import { confirm, isCancel, password, select, text } from \"@clack/prompts\";\nimport type { PromptResolver } from \"../../types.js\";\nimport { promptMissingArgs } from \"../index.js\";\nimport type { PromptAdapter } from \"../types.js\";\n\nfunction createClackAdapter(): PromptAdapter {\n return {\n text: (config) =>\n text({\n message: config.message,\n ...(config.placeholder !== undefined && { placeholder: config.placeholder }),\n }),\n password: (config) => password(config),\n confirm: (config) => confirm(config),\n select: (config) => select(config),\n isCancelled: isCancel,\n };\n}\n\n/**\n * Prompt resolver backed by @clack/prompts.\n *\n * @example\n * ```ts\n * import { runMain, defineCommand } from \"politty\";\n * import { prompt } from \"politty/prompt/clack\";\n *\n * runMain(cmd, { version: \"1.0.0\", prompt });\n * ```\n */\nexport const prompt: PromptResolver = (rawArgs, extracted) =>\n promptMissingArgs(rawArgs, extracted, { adapter: createClackAdapter() });\n"],"mappings":";;;;;AAKA,SAAS,qBAAoC;CAC3C,OAAO;EACL,OAAO,oCACA;GACH,SAAS,OAAO;GAChB,GAAI,OAAO,gBAAgB,UAAa,EAAE,aAAa,OAAO,YAAY;EAC5E,CAAC;EACH,WAAW,wCAAoB,MAAM;EACrC,UAAU,uCAAmB,MAAM;EACnC,SAAS,sCAAkB,MAAM;EACjC,aAAaA;CACf;AACF;;;;;;;;;;;;AAaA,MAAa,UAA0B,SAAS,cAC9CC,iCAAkB,SAAS,WAAW,EAAE,SAAS,mBAAmB,EAAE,CAAC"}
@@ -1,4 +1,4 @@
1
- import { P as PromptResolver } from "../../arg-registry--NRaNFJM.cjs";
1
+ import { P as PromptResolver } from "../../arg-registry-DDJpsUea.cjs";
2
2
 
3
3
  //#region src/prompt/clack/index.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { P as PromptResolver } from "../../arg-registry-6E0WHOh_.js";
1
+ import { P as PromptResolver } from "../../arg-registry-DDJpsUea.js";
2
2
 
3
3
  //#region src/prompt/clack/index.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as promptMissingArgs } from "../../prompt-BKHqGrFw.js";
1
+ import { t as promptMissingArgs } from "../../prompt-Cc8Tfmdv.js";
2
2
  import { confirm, isCancel, password, select, text } from "@clack/prompts";
3
3
 
4
4
  //#region src/prompt/clack/index.ts
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_prompt = require('../prompt-aXfSf27y.cjs');
2
+ const require_prompt = require('../prompt-Bs9e-Em3.cjs');
3
3
 
4
4
  exports.getFieldsToPrompt = require_prompt.getFieldsToPrompt;
5
5
  exports.isInteractive = require_prompt.isInteractive;
@@ -1,4 +1,4 @@
1
- import { K as ExtractedFields, q as ResolvedFieldMeta } from "../arg-registry--NRaNFJM.cjs";
1
+ import { J as ResolvedFieldMeta, q as ExtractedFields } from "../arg-registry-DDJpsUea.cjs";
2
2
 
3
3
  //#region src/prompt/types.d.ts
4
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/prompt/types.ts","../../src/prompt/prompt-resolver.ts","../../src/prompt/tty-detector.ts","../../src/prompt/index.ts"],"mappings":";;;;;AAKA;UAAiB,oBAAA;;EAEf,KAAA,EAAO,iBAAA;EAAP;EAEA,IAAA;EAAA;EAEA,OAAA;EAEA;EAAA,OAAA,GAAU,KAAK;IAAG,KAAA;IAAe,KAAA;EAAA;AAAA;AAOnC;;;;AAAA,UAAiB,aAAA;EAMuB;EAJtC,IAAA,CAAK,MAAA;IAAU,OAAA;IAAiB,WAAA;EAAA,IAAqC,OAAA;EAArE;EAEA,QAAA,CAAS,MAAA;IAAU,OAAA;EAAA,IAAoB,OAAA;EAF8B;EAIrE,OAAA,CAAQ,MAAA;IAAU,OAAA;EAAA,IAAoB,OAAA;EAFC;EAIvC,MAAA,CAAO,MAAA;IACL,OAAA;IACA,OAAA,EAAS,KAAA;MAAQ,KAAA;MAAe,KAAA;IAAA;EAAA,IAC9B,OAAA;EADO;EAGX,WAAA,CAAY,KAAA;AAAA;;;;AA5Bd;;;;;;;;;;;;;iBCYgB,mBAAA,CAAoB,KAAA,EAAO,iBAAA,GAAoB,oBAAoB;ADGnF;;;;;;;;;;;;;AAAA,iBC+DgB,iBAAA,CACd,MAAA,EAAQ,iBAAA,IACR,OAAA,EAAS,MAAA,oBACR,oBAAA;;;;;;ADjFH;iBEDgB,aAAA,CAAA;;;;;;UCQC,aAAA;EHHf;EGKA,OAAA,EAAS,aAAa;EHDtB;EGGA,WAAA;AAAA;;;AHHsC;AAOxC;;;;iBGMsB,iBAAA,CACpB,OAAA,EAAS,MAAA,mBACT,SAAA,EAAW,eAAA,EACX,OAAA,EAAS,aAAA,GACR,OAAA,CAAQ,MAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/prompt/types.ts","../../src/prompt/prompt-resolver.ts","../../src/prompt/tty-detector.ts","../../src/prompt/index.ts"],"mappings":";;;;;AAKA;UAAiB,oBAAA;;EAEf,KAAA,EAAO,iBAAA;EAAP;EAEA,IAAA;EAAA;EAEA,OAAA;EAEA;EAAA,OAAA,GAAU,KAAK;IAAG,KAAA;IAAe,KAAA;EAAA;AAAA;AAOnC;;;;AAAA,UAAiB,aAAA;EAMuB;EAJtC,IAAA,CAAK,MAAA;IAAU,OAAA;IAAiB,WAAA;EAAA,IAAqC,OAAA;EAArE;EAEA,QAAA,CAAS,MAAA;IAAU,OAAA;EAAA,IAAoB,OAAA;EAF8B;EAIrE,OAAA,CAAQ,MAAA;IAAU,OAAA;EAAA,IAAoB,OAAA;EAFC;EAIvC,MAAA,CAAO,MAAA;IACL,OAAA;IACA,OAAA,EAAS,KAAA;MAAQ,KAAA;MAAe,KAAA;IAAA;EAAA,IAC9B,OAAA;EADO;EAGX,WAAA,CAAY,KAAA;AAAA;;;;AA5Bd;;;;;;;;;;;;;iBCYgB,mBAAA,CAAoB,KAAA,EAAO,iBAAA,GAAoB,oBAAoB;ADGnF;;;;;;;;;;;;;AAAA,iBC+DgB,iBAAA,CACd,MAAA,EAAQ,iBAAA,IACR,OAAA,EAAS,MAAA,oBACR,oBAAA;;;;;;ADjFH;iBEDgB,aAAA;;;;;;UCQC,aAAA;EHHf;EGKA,OAAA,EAAS,aAAa;EHDtB;EGGA,WAAA;AAAA;;;AHHsC;AAOxC;;;;iBGMsB,iBAAA,CACpB,OAAA,EAAS,MAAA,mBACT,SAAA,EAAW,eAAA,EACX,OAAA,EAAS,aAAA,GACR,OAAA,CAAQ,MAAA"}
@@ -1,4 +1,4 @@
1
- import { K as ExtractedFields, q as ResolvedFieldMeta } from "../arg-registry-6E0WHOh_.js";
1
+ import { J as ResolvedFieldMeta, q as ExtractedFields } from "../arg-registry-DDJpsUea.js";
2
2
 
3
3
  //#region src/prompt/types.d.ts
4
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/prompt/types.ts","../../src/prompt/prompt-resolver.ts","../../src/prompt/tty-detector.ts","../../src/prompt/index.ts"],"mappings":";;;;;AAKA;UAAiB,oBAAA;;EAEf,KAAA,EAAO,iBAAA;EAAP;EAEA,IAAA;EAAA;EAEA,OAAA;EAEA;EAAA,OAAA,GAAU,KAAK;IAAG,KAAA;IAAe,KAAA;EAAA;AAAA;AAOnC;;;;AAAA,UAAiB,aAAA;EAMuB;EAJtC,IAAA,CAAK,MAAA;IAAU,OAAA;IAAiB,WAAA;EAAA,IAAqC,OAAA;EAArE;EAEA,QAAA,CAAS,MAAA;IAAU,OAAA;EAAA,IAAoB,OAAA;EAF8B;EAIrE,OAAA,CAAQ,MAAA;IAAU,OAAA;EAAA,IAAoB,OAAA;EAFC;EAIvC,MAAA,CAAO,MAAA;IACL,OAAA;IACA,OAAA,EAAS,KAAA;MAAQ,KAAA;MAAe,KAAA;IAAA;EAAA,IAC9B,OAAA;EADO;EAGX,WAAA,CAAY,KAAA;AAAA;;;;AA5Bd;;;;;;;;;;;;;iBCYgB,mBAAA,CAAoB,KAAA,EAAO,iBAAA,GAAoB,oBAAoB;ADGnF;;;;;;;;;;;;;AAAA,iBC+DgB,iBAAA,CACd,MAAA,EAAQ,iBAAA,IACR,OAAA,EAAS,MAAA,oBACR,oBAAA;;;;;;ADjFH;iBEDgB,aAAA,CAAA;;;;;;UCQC,aAAA;EHHf;EGKA,OAAA,EAAS,aAAa;EHDtB;EGGA,WAAA;AAAA;;;AHHsC;AAOxC;;;;iBGMsB,iBAAA,CACpB,OAAA,EAAS,MAAA,mBACT,SAAA,EAAW,eAAA,EACX,OAAA,EAAS,aAAA,GACR,OAAA,CAAQ,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/prompt/types.ts","../../src/prompt/prompt-resolver.ts","../../src/prompt/tty-detector.ts","../../src/prompt/index.ts"],"mappings":";;;;;AAKA;UAAiB,oBAAA;;EAEf,KAAA,EAAO,iBAAA;EAAP;EAEA,IAAA;EAAA;EAEA,OAAA;EAEA;EAAA,OAAA,GAAU,KAAK;IAAG,KAAA;IAAe,KAAA;EAAA;AAAA;AAOnC;;;;AAAA,UAAiB,aAAA;EAMuB;EAJtC,IAAA,CAAK,MAAA;IAAU,OAAA;IAAiB,WAAA;EAAA,IAAqC,OAAA;EAArE;EAEA,QAAA,CAAS,MAAA;IAAU,OAAA;EAAA,IAAoB,OAAA;EAF8B;EAIrE,OAAA,CAAQ,MAAA;IAAU,OAAA;EAAA,IAAoB,OAAA;EAFC;EAIvC,MAAA,CAAO,MAAA;IACL,OAAA;IACA,OAAA,EAAS,KAAA;MAAQ,KAAA;MAAe,KAAA;IAAA;EAAA,IAC9B,OAAA;EADO;EAGX,WAAA,CAAY,KAAA;AAAA;;;;AA5Bd;;;;;;;;;;;;;iBCYgB,mBAAA,CAAoB,KAAA,EAAO,iBAAA,GAAoB,oBAAoB;ADGnF;;;;;;;;;;;;;AAAA,iBC+DgB,iBAAA,CACd,MAAA,EAAQ,iBAAA,IACR,OAAA,EAAS,MAAA,oBACR,oBAAA;;;;;;ADjFH;iBEDgB,aAAA;;;;;;UCQC,aAAA;EHHf;EGKA,OAAA,EAAS,aAAa;EHDtB;EGGA,WAAA;AAAA;;;AHHsC;AAOxC;;;;iBGMsB,iBAAA,CACpB,OAAA,EAAS,MAAA,mBACT,SAAA,EAAW,eAAA,EACX,OAAA,EAAS,aAAA,GACR,OAAA,CAAQ,MAAA"}
@@ -1,3 +1,3 @@
1
- import { i as resolvePromptConfig, n as isInteractive, r as getFieldsToPrompt, t as promptMissingArgs } from "../prompt-BKHqGrFw.js";
1
+ import { i as resolvePromptConfig, n as isInteractive, r as getFieldsToPrompt, t as promptMissingArgs } from "../prompt-Cc8Tfmdv.js";
2
2
 
3
3
  export { getFieldsToPrompt, isInteractive, promptMissingArgs, resolvePromptConfig };
@@ -1,6 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_log_collector = require('../../log-collector-Cd2_mv87.cjs');
3
- const require_prompt = require('../../prompt-aXfSf27y.cjs');
2
+ const require_prompt = require('../../prompt-Bs9e-Em3.cjs');
4
3
  let _inquirer_prompts = require("@inquirer/prompts");
5
4
 
6
5
  //#region src/prompt/inquirer/index.ts
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["promptMissingArgs"],"sources":["../../../src/prompt/inquirer/index.ts"],"sourcesContent":["import { confirm, input, password, select } from \"@inquirer/prompts\";\nimport type { PromptResolver } from \"../../types.js\";\nimport { promptMissingArgs } from \"../index.js\";\nimport type { PromptAdapter } from \"../types.js\";\n\nconst cancelSymbol = Symbol(\"inquirer-cancel\");\n\nasync function wrapCancellation<T>(fn: () => Promise<T>): Promise<T | symbol> {\n try {\n return await fn();\n } catch (error) {\n if (error instanceof Error && error.name === \"ExitPromptError\") {\n return cancelSymbol;\n }\n throw error;\n }\n}\n\nfunction createInquirerAdapter(): PromptAdapter {\n return {\n text: (config) =>\n wrapCancellation(() =>\n input({\n message: config.message,\n ...(config.placeholder !== undefined && { default: config.placeholder }),\n }),\n ),\n password: (config) => wrapCancellation(() => password({ message: config.message })),\n confirm: (config) => wrapCancellation(() => confirm({ message: config.message })),\n select: (config) =>\n wrapCancellation(() =>\n select({\n message: config.message,\n choices: config.options.map((o) => ({ name: o.label, value: o.value })),\n }),\n ),\n isCancelled: (value) => value === cancelSymbol,\n };\n}\n\n/**\n * Prompt resolver backed by @inquirer/prompts.\n *\n * @example\n * ```ts\n * import { runMain, defineCommand } from \"politty\";\n * import { prompt } from \"politty/prompt/inquirer\";\n *\n * runMain(cmd, { version: \"1.0.0\", prompt });\n * ```\n */\nexport const prompt: PromptResolver = (rawArgs, extracted) =>\n promptMissingArgs(rawArgs, extracted, { adapter: createInquirerAdapter() });\n"],"mappings":";;;;;;AAKA,MAAM,eAAe,OAAO,iBAAiB;AAE7C,eAAe,iBAAoB,IAA2C;CAC5E,IAAI;EACF,OAAO,MAAM,GAAG;CAClB,SAAS,OAAO;EACd,IAAI,iBAAiB,SAAS,MAAM,SAAS,mBAC3C,OAAO;EAET,MAAM;CACR;AACF;AAEA,SAAS,wBAAuC;CAC9C,OAAO;EACL,OAAO,WACL,oDACQ;GACJ,SAAS,OAAO;GAChB,GAAI,OAAO,gBAAgB,UAAa,EAAE,SAAS,OAAO,YAAY;EACxE,CAAC,CACH;EACF,WAAW,WAAW,uDAAgC,EAAE,SAAS,OAAO,QAAQ,CAAC,CAAC;EAClF,UAAU,WAAW,sDAA+B,EAAE,SAAS,OAAO,QAAQ,CAAC,CAAC;EAChF,SAAS,WACP,qDACS;GACL,SAAS,OAAO;GAChB,SAAS,OAAO,QAAQ,KAAK,OAAO;IAAE,MAAM,EAAE;IAAO,OAAO,EAAE;GAAM,EAAE;EACxE,CAAC,CACH;EACF,cAAc,UAAU,UAAU;CACpC;AACF;;;;;;;;;;;;AAaA,MAAa,UAA0B,SAAS,cAC9CA,iCAAkB,SAAS,WAAW,EAAE,SAAS,sBAAsB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.cjs","names":["promptMissingArgs"],"sources":["../../../src/prompt/inquirer/index.ts"],"sourcesContent":["import { confirm, input, password, select } from \"@inquirer/prompts\";\nimport type { PromptResolver } from \"../../types.js\";\nimport { promptMissingArgs } from \"../index.js\";\nimport type { PromptAdapter } from \"../types.js\";\n\nconst cancelSymbol = Symbol(\"inquirer-cancel\");\n\nasync function wrapCancellation<T>(fn: () => Promise<T>): Promise<T | symbol> {\n try {\n return await fn();\n } catch (error) {\n if (error instanceof Error && error.name === \"ExitPromptError\") {\n return cancelSymbol;\n }\n throw error;\n }\n}\n\nfunction createInquirerAdapter(): PromptAdapter {\n return {\n text: (config) =>\n wrapCancellation(() =>\n input({\n message: config.message,\n ...(config.placeholder !== undefined && { default: config.placeholder }),\n }),\n ),\n password: (config) => wrapCancellation(() => password({ message: config.message })),\n confirm: (config) => wrapCancellation(() => confirm({ message: config.message })),\n select: (config) =>\n wrapCancellation(() =>\n select({\n message: config.message,\n choices: config.options.map((o) => ({ name: o.label, value: o.value })),\n }),\n ),\n isCancelled: (value) => value === cancelSymbol,\n };\n}\n\n/**\n * Prompt resolver backed by @inquirer/prompts.\n *\n * @example\n * ```ts\n * import { runMain, defineCommand } from \"politty\";\n * import { prompt } from \"politty/prompt/inquirer\";\n *\n * runMain(cmd, { version: \"1.0.0\", prompt });\n * ```\n */\nexport const prompt: PromptResolver = (rawArgs, extracted) =>\n promptMissingArgs(rawArgs, extracted, { adapter: createInquirerAdapter() });\n"],"mappings":";;;;;AAKA,MAAM,eAAe,OAAO,iBAAiB;AAE7C,eAAe,iBAAoB,IAA2C;CAC5E,IAAI;EACF,OAAO,MAAM,GAAG;CAClB,SAAS,OAAO;EACd,IAAI,iBAAiB,SAAS,MAAM,SAAS,mBAC3C,OAAO;EAET,MAAM;CACR;AACF;AAEA,SAAS,wBAAuC;CAC9C,OAAO;EACL,OAAO,WACL,oDACQ;GACJ,SAAS,OAAO;GAChB,GAAI,OAAO,gBAAgB,UAAa,EAAE,SAAS,OAAO,YAAY;EACxE,CAAC,CACH;EACF,WAAW,WAAW,uDAAgC,EAAE,SAAS,OAAO,QAAQ,CAAC,CAAC;EAClF,UAAU,WAAW,sDAA+B,EAAE,SAAS,OAAO,QAAQ,CAAC,CAAC;EAChF,SAAS,WACP,qDACS;GACL,SAAS,OAAO;GAChB,SAAS,OAAO,QAAQ,KAAK,OAAO;IAAE,MAAM,EAAE;IAAO,OAAO,EAAE;GAAM,EAAE;EACxE,CAAC,CACH;EACF,cAAc,UAAU,UAAU;CACpC;AACF;;;;;;;;;;;;AAaA,MAAa,UAA0B,SAAS,cAC9CA,iCAAkB,SAAS,WAAW,EAAE,SAAS,sBAAsB,EAAE,CAAC"}
@@ -1,4 +1,4 @@
1
- import { P as PromptResolver } from "../../arg-registry--NRaNFJM.cjs";
1
+ import { P as PromptResolver } from "../../arg-registry-DDJpsUea.cjs";
2
2
 
3
3
  //#region src/prompt/inquirer/index.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { P as PromptResolver } from "../../arg-registry-6E0WHOh_.js";
1
+ import { P as PromptResolver } from "../../arg-registry-DDJpsUea.js";
2
2
 
3
3
  //#region src/prompt/inquirer/index.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as promptMissingArgs } from "../../prompt-BKHqGrFw.js";
1
+ import { t as promptMissingArgs } from "../../prompt-Cc8Tfmdv.js";
2
2
  import { confirm, input, password, select } from "@inquirer/prompts";
3
3
 
4
4
  //#region src/prompt/inquirer/index.ts
@@ -193,4 +193,4 @@ Object.defineProperty(exports, 'resolvePromptConfig', {
193
193
  return resolvePromptConfig;
194
194
  }
195
195
  });
196
- //# sourceMappingURL=prompt-aXfSf27y.cjs.map
196
+ //# sourceMappingURL=prompt-Bs9e-Em3.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-aXfSf27y.cjs","names":[],"sources":["../src/prompt/prompt-resolver.ts","../src/prompt/tty-detector.ts","../src/prompt/index.ts"],"sourcesContent":["import type { ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport type { ResolvedPromptConfig } from \"./types.js\";\n\n/**\n * Resolve prompt configuration for a field.\n *\n * Priority for prompt type:\n * 1. Explicit type from prompt.type\n * 2. Explicit choices from prompt.choices (forces \"select\")\n * 3. Inherited from completion metadata (file/directory -> \"text\")\n * 4. Auto-detected from Zod schema type:\n * - enum (has enumValues) -> \"select\"\n * - boolean -> \"confirm\"\n * - string/number/unknown -> \"text\"\n *\n * Returns null if the field has no prompt metadata or prompting is disabled.\n */\nexport function resolvePromptConfig(field: ResolvedFieldMeta): ResolvedPromptConfig | null {\n const promptMeta = field.prompt;\n if (!promptMeta || promptMeta.enabled === false) return null;\n\n const message = promptMeta.message ?? field.description ?? field.name;\n const rawType = resolvePromptType(field, promptMeta);\n const choices = resolveChoices(field, promptMeta, rawType);\n // Fall back to text when select has no choices to avoid adapter crash\n const type = rawType === \"select\" && !choices ? \"text\" : rawType;\n\n return { field, type, message, ...(choices && { choices }) };\n}\n\nfunction hasChoices(list: unknown[] | undefined): list is unknown[] {\n return list !== undefined && list.length > 0;\n}\n\nfunction resolvePromptType(\n field: ResolvedFieldMeta,\n promptMeta: NonNullable<ResolvedFieldMeta[\"prompt\"]>,\n): ResolvedPromptConfig[\"type\"] {\n // Priority 1: Explicit type\n if (promptMeta.type) {\n return promptMeta.type === \"file\" || promptMeta.type === \"directory\" ? \"text\" : promptMeta.type;\n }\n // Priority 2: Explicit choices\n if (hasChoices(promptMeta.choices)) return \"select\";\n // Priority 3: Inherited from completion type\n if (field.completion?.type === \"file\" || field.completion?.type === \"directory\") {\n return \"text\";\n }\n // Priority 4: Auto-detect from schema\n if (hasChoices(field.enumValues)) return \"select\";\n if (field.type === \"boolean\") return \"confirm\";\n return \"text\";\n}\n\nfunction resolveChoices(\n field: ResolvedFieldMeta,\n promptMeta: NonNullable<ResolvedFieldMeta[\"prompt\"]>,\n type: ResolvedPromptConfig[\"type\"],\n): ResolvedPromptConfig[\"choices\"] | undefined {\n // Explicit choices always win\n if (hasChoices(promptMeta.choices)) {\n return promptMeta.choices.map((c) => (typeof c === \"string\" ? { label: c, value: c } : c));\n }\n // Auto-populate from enum values for select type\n if (type === \"select\" && hasChoices(field.enumValues)) {\n return field.enumValues.map((v) => ({ label: v, value: v }));\n }\n return undefined;\n}\n\n/**\n * Filter fields that need prompting (missing value + prompt configured).\n *\n * For discriminatedUnion schemas, variant-aware narrowing is handled by the\n * caller (promptMissingArgs) which prompts the discriminator first and then\n * passes only the active variant's fields. For plain union schemas, this\n * iterates all fields across every variant without narrowing.\n *\n * Fields with Zod defaults that also have prompt metadata will be prompted\n * when the raw value is undefined. This is intentional: `prompt: {}` is an\n * explicit opt-in to interactive input. Omit prompt metadata to let the\n * default apply silently.\n */\nexport function getFieldsToPrompt(\n fields: ResolvedFieldMeta[],\n rawArgs: Record<string, unknown>,\n): ResolvedPromptConfig[] {\n const configs: ResolvedPromptConfig[] = [];\n for (const field of fields) {\n if (rawArgs[field.name] !== undefined) continue;\n // Array fields are not supported for interactive prompting yet;\n // a scalar text response would fail Zod array validation.\n // Object-valued fields (detected as type \"unknown\") are also unsupported\n // but share the \"unknown\" bucket with literals, so they are not filtered\n // here. Putting prompt metadata on object fields yields a Zod validation\n // error at parse time, which is an acceptable misconfiguration signal.\n if (field.type === \"array\") continue;\n const config = resolvePromptConfig(field);\n if (config) configs.push(config);\n }\n return configs;\n}\n","/**\n * Detect whether the current environment supports interactive prompts.\n * Returns false in CI, piped input, or non-TTY environments.\n */\nexport function isInteractive(): boolean {\n if (!process.stdin.isTTY) return false;\n if (!process.stdout.isTTY) return false;\n if (process.env.CI) return false;\n if (process.env.POLITTY_NO_PROMPT) return false;\n return true;\n}\n","import type { ExtractedFields, ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport { getFieldsToPrompt, resolvePromptConfig } from \"./prompt-resolver.js\";\nimport { isInteractive } from \"./tty-detector.js\";\nimport type { PromptAdapter, ResolvedPromptConfig } from \"./types.js\";\n\nexport { getFieldsToPrompt, resolvePromptConfig } from \"./prompt-resolver.js\";\nexport { isInteractive } from \"./tty-detector.js\";\nexport type { PromptAdapter, ResolvedPromptConfig } from \"./types.js\";\n\n/**\n * Options for promptMissingArgs behavior\n */\nexport interface PromptOptions {\n /** Prompt adapter to use for rendering prompts */\n adapter: PromptAdapter;\n /** Override interactive detection (force enable/disable prompts) */\n interactive?: boolean;\n}\n\n/**\n * Prompt for missing argument values interactively.\n *\n * Only prompts for fields that have `prompt` metadata set via `arg()` and\n * whose values are still undefined after CLI and env resolution.\n * Returns rawArgs unchanged in non-interactive environments.\n */\nexport async function promptMissingArgs(\n rawArgs: Record<string, unknown>,\n extracted: ExtractedFields,\n options: PromptOptions,\n): Promise<Record<string, unknown>> {\n const interactive = options.interactive ?? isInteractive();\n if (!interactive) return rawArgs;\n\n const adapter = options.adapter;\n const result = { ...rawArgs };\n\n // For discriminatedUnion schemas, prompt the discriminator first then\n // narrow to the active variant to avoid prompting irrelevant fields.\n if (\n extracted.schemaType === \"discriminatedUnion\" &&\n extracted.discriminator &&\n extracted.variants\n ) {\n await promptDiscriminatedUnion(adapter, result, extracted);\n } else if (extracted.schemaType === \"union\" || extracted.schemaType === \"xor\") {\n // Plain unions have no discriminator to narrow by. Prompting the merged\n // field set would collect answers for incompatible branches, causing\n // silent data loss (strip mode) or validation errors (strict mode).\n // Skip prompting and let Zod validation handle it.\n } else {\n // For object and intersection schemas, prompt all fields as a flat list.\n // Limitation: intersection schemas that compose a discriminatedUnion\n // (e.g. sharedOptions.and(z.discriminatedUnion(...))) lose variant\n // structure here because extractFields flattens both operands. Variant-\n // aware prompting for intersections requires architectural changes to\n // preserve sub-schema structure through extraction.\n await promptAllFields(adapter, result, extracted.fields);\n }\n\n return result;\n}\n\nasync function promptDiscriminatedUnion(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n extracted: ExtractedFields,\n): Promise<void> {\n const { discriminator, variants } = extracted;\n if (!discriminator || !variants) return;\n\n // Prompt for discriminator if not already provided.\n // The deduplicated extracted.fields only keeps the first variant's\n // discriminator, so scan all variants for prompt metadata and build\n // choices from every variant's discriminator value.\n if (result[discriminator] === undefined) {\n const discField = findDiscriminatorField(extracted.fields, variants, discriminator);\n const discConfig = discField ? resolvePromptConfig(discField) : null;\n if (discConfig) {\n const allValues = variants.map((v) => v.discriminatorValue).filter(Boolean);\n if (allValues.length > 0) {\n discConfig.type = \"select\";\n discConfig.choices = allValues.map((v) => ({ label: v, value: v }));\n }\n await promptAndCollect(adapter, result, discConfig);\n }\n }\n\n // Find the active variant based on discriminator value\n const discValue = String(result[discriminator] ?? \"\");\n const activeVariant = variants.find((v) => v.discriminatorValue === discValue);\n\n if (activeVariant) {\n // Prompt only the active variant's fields (excluding discriminator)\n const variantFields = activeVariant.fields.filter((f) => f.name !== discriminator);\n await promptAllFields(adapter, result, variantFields);\n }\n // When no variant matches (invalid value or unextracted discriminator),\n // skip prompting and let Zod validation surface the error.\n}\n\n/**\n * Find the discriminator field with prompt metadata, checking the\n * deduplicated top-level fields first, then scanning per-variant fields.\n */\nfunction findDiscriminatorField(\n fields: ResolvedFieldMeta[],\n variants: NonNullable<ExtractedFields[\"variants\"]>,\n discriminator: string,\n): ResolvedFieldMeta | undefined {\n const topLevel = fields.find((f) => f.name === discriminator);\n if (topLevel?.prompt) return topLevel;\n for (const variant of variants) {\n const field = variant.fields.find((f) => f.name === discriminator);\n if (field?.prompt) return field;\n }\n return undefined;\n}\n\nasync function promptAllFields(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n fields: ResolvedFieldMeta[],\n): Promise<void> {\n const fieldsToPrompt = getFieldsToPrompt(fields, result);\n for (const config of fieldsToPrompt) {\n await promptAndCollect(adapter, result, config);\n }\n}\n\nasync function promptAndCollect(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n config: ResolvedPromptConfig,\n): Promise<void> {\n const { message } = config;\n let value: unknown;\n switch (config.type) {\n case \"text\":\n value = await adapter.text({ message, placeholder: config.field.placeholder });\n break;\n case \"password\":\n value = await adapter.password({ message });\n break;\n case \"confirm\":\n value = await adapter.confirm({ message });\n break;\n case \"select\":\n value = await adapter.select({ message, options: config.choices ?? [] });\n break;\n }\n if (adapter.isCancelled(value)) {\n throw new Error(\"Prompt cancelled by user\");\n }\n result[config.field.name] = value;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"prompt-Bs9e-Em3.cjs","names":[],"sources":["../src/prompt/prompt-resolver.ts","../src/prompt/tty-detector.ts","../src/prompt/index.ts"],"sourcesContent":["import type { ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport type { ResolvedPromptConfig } from \"./types.js\";\n\n/**\n * Resolve prompt configuration for a field.\n *\n * Priority for prompt type:\n * 1. Explicit type from prompt.type\n * 2. Explicit choices from prompt.choices (forces \"select\")\n * 3. Inherited from completion metadata (file/directory -> \"text\")\n * 4. Auto-detected from Zod schema type:\n * - enum (has enumValues) -> \"select\"\n * - boolean -> \"confirm\"\n * - string/number/unknown -> \"text\"\n *\n * Returns null if the field has no prompt metadata or prompting is disabled.\n */\nexport function resolvePromptConfig(field: ResolvedFieldMeta): ResolvedPromptConfig | null {\n const promptMeta = field.prompt;\n if (!promptMeta || promptMeta.enabled === false) return null;\n\n const message = promptMeta.message ?? field.description ?? field.name;\n const rawType = resolvePromptType(field, promptMeta);\n const choices = resolveChoices(field, promptMeta, rawType);\n // Fall back to text when select has no choices to avoid adapter crash\n const type = rawType === \"select\" && !choices ? \"text\" : rawType;\n\n return { field, type, message, ...(choices && { choices }) };\n}\n\nfunction hasChoices(list: unknown[] | undefined): list is unknown[] {\n return list !== undefined && list.length > 0;\n}\n\nfunction resolvePromptType(\n field: ResolvedFieldMeta,\n promptMeta: NonNullable<ResolvedFieldMeta[\"prompt\"]>,\n): ResolvedPromptConfig[\"type\"] {\n // Priority 1: Explicit type\n if (promptMeta.type) {\n return promptMeta.type === \"file\" || promptMeta.type === \"directory\" ? \"text\" : promptMeta.type;\n }\n // Priority 2: Explicit choices\n if (hasChoices(promptMeta.choices)) return \"select\";\n // Priority 3: Inherited from completion type\n if (field.completion?.type === \"file\" || field.completion?.type === \"directory\") {\n return \"text\";\n }\n // Priority 4: Auto-detect from schema\n if (hasChoices(field.enumValues)) return \"select\";\n if (field.type === \"boolean\") return \"confirm\";\n return \"text\";\n}\n\nfunction resolveChoices(\n field: ResolvedFieldMeta,\n promptMeta: NonNullable<ResolvedFieldMeta[\"prompt\"]>,\n type: ResolvedPromptConfig[\"type\"],\n): ResolvedPromptConfig[\"choices\"] | undefined {\n // Explicit choices always win\n if (hasChoices(promptMeta.choices)) {\n return promptMeta.choices.map((c) => (typeof c === \"string\" ? { label: c, value: c } : c));\n }\n // Auto-populate from enum values for select type\n if (type === \"select\" && hasChoices(field.enumValues)) {\n return field.enumValues.map((v) => ({ label: v, value: v }));\n }\n return undefined;\n}\n\n/**\n * Filter fields that need prompting (missing value + prompt configured).\n *\n * For discriminatedUnion schemas, variant-aware narrowing is handled by the\n * caller (promptMissingArgs) which prompts the discriminator first and then\n * passes only the active variant's fields. For plain union schemas, this\n * iterates all fields across every variant without narrowing.\n *\n * Fields with Zod defaults that also have prompt metadata will be prompted\n * when the raw value is undefined. This is intentional: `prompt: {}` is an\n * explicit opt-in to interactive input. Omit prompt metadata to let the\n * default apply silently.\n */\nexport function getFieldsToPrompt(\n fields: ResolvedFieldMeta[],\n rawArgs: Record<string, unknown>,\n): ResolvedPromptConfig[] {\n const configs: ResolvedPromptConfig[] = [];\n for (const field of fields) {\n if (rawArgs[field.name] !== undefined) continue;\n // Array fields are not supported for interactive prompting yet;\n // a scalar text response would fail Zod array validation.\n // Object-valued fields (detected as type \"unknown\") are also unsupported\n // but share the \"unknown\" bucket with literals, so they are not filtered\n // here. Putting prompt metadata on object fields yields a Zod validation\n // error at parse time, which is an acceptable misconfiguration signal.\n if (field.type === \"array\") continue;\n const config = resolvePromptConfig(field);\n if (config) configs.push(config);\n }\n return configs;\n}\n","/**\n * Detect whether the current environment supports interactive prompts.\n * Returns false in CI, piped input, or non-TTY environments.\n */\nexport function isInteractive(): boolean {\n if (!process.stdin.isTTY) return false;\n if (!process.stdout.isTTY) return false;\n if (process.env.CI) return false;\n if (process.env.POLITTY_NO_PROMPT) return false;\n return true;\n}\n","import type { ExtractedFields, ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport { getFieldsToPrompt, resolvePromptConfig } from \"./prompt-resolver.js\";\nimport { isInteractive } from \"./tty-detector.js\";\nimport type { PromptAdapter, ResolvedPromptConfig } from \"./types.js\";\n\nexport { getFieldsToPrompt, resolvePromptConfig } from \"./prompt-resolver.js\";\nexport { isInteractive } from \"./tty-detector.js\";\nexport type { PromptAdapter, ResolvedPromptConfig } from \"./types.js\";\n\n/**\n * Options for promptMissingArgs behavior\n */\nexport interface PromptOptions {\n /** Prompt adapter to use for rendering prompts */\n adapter: PromptAdapter;\n /** Override interactive detection (force enable/disable prompts) */\n interactive?: boolean;\n}\n\n/**\n * Prompt for missing argument values interactively.\n *\n * Only prompts for fields that have `prompt` metadata set via `arg()` and\n * whose values are still undefined after CLI and env resolution.\n * Returns rawArgs unchanged in non-interactive environments.\n */\nexport async function promptMissingArgs(\n rawArgs: Record<string, unknown>,\n extracted: ExtractedFields,\n options: PromptOptions,\n): Promise<Record<string, unknown>> {\n const interactive = options.interactive ?? isInteractive();\n if (!interactive) return rawArgs;\n\n const adapter = options.adapter;\n const result = { ...rawArgs };\n\n // For discriminatedUnion schemas, prompt the discriminator first then\n // narrow to the active variant to avoid prompting irrelevant fields.\n if (\n extracted.schemaType === \"discriminatedUnion\" &&\n extracted.discriminator &&\n extracted.variants\n ) {\n await promptDiscriminatedUnion(adapter, result, extracted);\n } else if (extracted.schemaType === \"union\" || extracted.schemaType === \"xor\") {\n // Plain unions have no discriminator to narrow by. Prompting the merged\n // field set would collect answers for incompatible branches, causing\n // silent data loss (strip mode) or validation errors (strict mode).\n // Skip prompting and let Zod validation handle it.\n } else {\n // For object and intersection schemas, prompt all fields as a flat list.\n // Limitation: intersection schemas that compose a discriminatedUnion\n // (e.g. sharedOptions.and(z.discriminatedUnion(...))) lose variant\n // structure here because extractFields flattens both operands. Variant-\n // aware prompting for intersections requires architectural changes to\n // preserve sub-schema structure through extraction.\n await promptAllFields(adapter, result, extracted.fields);\n }\n\n return result;\n}\n\nasync function promptDiscriminatedUnion(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n extracted: ExtractedFields,\n): Promise<void> {\n const { discriminator, variants } = extracted;\n if (!discriminator || !variants) return;\n\n // Prompt for discriminator if not already provided.\n // The deduplicated extracted.fields only keeps the first variant's\n // discriminator, so scan all variants for prompt metadata and build\n // choices from every variant's discriminator value.\n if (result[discriminator] === undefined) {\n const discField = findDiscriminatorField(extracted.fields, variants, discriminator);\n const discConfig = discField ? resolvePromptConfig(discField) : null;\n if (discConfig) {\n const allValues = variants.map((v) => v.discriminatorValue).filter(Boolean);\n if (allValues.length > 0) {\n discConfig.type = \"select\";\n discConfig.choices = allValues.map((v) => ({ label: v, value: v }));\n }\n await promptAndCollect(adapter, result, discConfig);\n }\n }\n\n // Find the active variant based on discriminator value\n const discValue = String(result[discriminator] ?? \"\");\n const activeVariant = variants.find((v) => v.discriminatorValue === discValue);\n\n if (activeVariant) {\n // Prompt only the active variant's fields (excluding discriminator)\n const variantFields = activeVariant.fields.filter((f) => f.name !== discriminator);\n await promptAllFields(adapter, result, variantFields);\n }\n // When no variant matches (invalid value or unextracted discriminator),\n // skip prompting and let Zod validation surface the error.\n}\n\n/**\n * Find the discriminator field with prompt metadata, checking the\n * deduplicated top-level fields first, then scanning per-variant fields.\n */\nfunction findDiscriminatorField(\n fields: ResolvedFieldMeta[],\n variants: NonNullable<ExtractedFields[\"variants\"]>,\n discriminator: string,\n): ResolvedFieldMeta | undefined {\n const topLevel = fields.find((f) => f.name === discriminator);\n if (topLevel?.prompt) return topLevel;\n for (const variant of variants) {\n const field = variant.fields.find((f) => f.name === discriminator);\n if (field?.prompt) return field;\n }\n return undefined;\n}\n\nasync function promptAllFields(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n fields: ResolvedFieldMeta[],\n): Promise<void> {\n const fieldsToPrompt = getFieldsToPrompt(fields, result);\n for (const config of fieldsToPrompt) {\n await promptAndCollect(adapter, result, config);\n }\n}\n\nasync function promptAndCollect(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n config: ResolvedPromptConfig,\n): Promise<void> {\n const { message } = config;\n let value: unknown;\n switch (config.type) {\n case \"text\":\n value = await adapter.text({ message, placeholder: config.field.placeholder });\n break;\n case \"password\":\n value = await adapter.password({ message });\n break;\n case \"confirm\":\n value = await adapter.confirm({ message });\n break;\n case \"select\":\n value = await adapter.select({ message, options: config.choices ?? [] });\n break;\n }\n if (adapter.isCancelled(value)) {\n throw new Error(\"Prompt cancelled by user\");\n }\n result[config.field.name] = value;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiBA,SAAgB,oBAAoB,OAAuD;CACzF,MAAM,aAAa,MAAM;CACzB,IAAI,CAAC,cAAc,WAAW,YAAY,OAAO,OAAO;CAExD,MAAM,UAAU,WAAW,WAAW,MAAM,eAAe,MAAM;CACjE,MAAM,UAAU,kBAAkB,OAAO,UAAU;CACnD,MAAM,UAAU,eAAe,OAAO,YAAY,OAAO;CAIzD,OAAO;EAAE;EAAO,MAFH,YAAY,YAAY,CAAC,UAAU,SAAS;EAEnC;EAAS,GAAI,WAAW,EAAE,QAAQ;CAAG;AAC7D;AAEA,SAAS,WAAW,MAAgD;CAClE,OAAO,SAAS,UAAa,KAAK,SAAS;AAC7C;AAEA,SAAS,kBACP,OACA,YAC8B;CAE9B,IAAI,WAAW,MACb,OAAO,WAAW,SAAS,UAAU,WAAW,SAAS,cAAc,SAAS,WAAW;CAG7F,IAAI,WAAW,WAAW,OAAO,GAAG,OAAO;CAE3C,IAAI,MAAM,YAAY,SAAS,UAAU,MAAM,YAAY,SAAS,aAClE,OAAO;CAGT,IAAI,WAAW,MAAM,UAAU,GAAG,OAAO;CACzC,IAAI,MAAM,SAAS,WAAW,OAAO;CACrC,OAAO;AACT;AAEA,SAAS,eACP,OACA,YACA,MAC6C;CAE7C,IAAI,WAAW,WAAW,OAAO,GAC/B,OAAO,WAAW,QAAQ,KAAK,MAAO,OAAO,MAAM,WAAW;EAAE,OAAO;EAAG,OAAO;CAAE,IAAI,CAAE;CAG3F,IAAI,SAAS,YAAY,WAAW,MAAM,UAAU,GAClD,OAAO,MAAM,WAAW,KAAK,OAAO;EAAE,OAAO;EAAG,OAAO;CAAE,EAAE;AAG/D;;;;;;;;;;;;;;AAeA,SAAgB,kBACd,QACA,SACwB;CACxB,MAAM,UAAkC,CAAC;CACzC,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,QAAQ,MAAM,UAAU,QAAW;EAOvC,IAAI,MAAM,SAAS,SAAS;EAC5B,MAAM,SAAS,oBAAoB,KAAK;EACxC,IAAI,QAAQ,QAAQ,KAAK,MAAM;CACjC;CACA,OAAO;AACT;;;;;;;;ACjGA,SAAgB,gBAAyB;CACvC,IAAI,CAAC,QAAQ,MAAM,OAAO,OAAO;CACjC,IAAI,CAAC,QAAQ,OAAO,OAAO,OAAO;CAClC,IAAI,QAAQ,IAAI,IAAI,OAAO;CAC3B,IAAI,QAAQ,IAAI,mBAAmB,OAAO;CAC1C,OAAO;AACT;;;;;;;;;;;ACgBA,eAAsB,kBACpB,SACA,WACA,SACkC;CAElC,IAAI,EADgB,QAAQ,eAAe,cAAc,IACvC,OAAO;CAEzB,MAAM,UAAU,QAAQ;CACxB,MAAM,SAAS,EAAE,GAAG,QAAQ;CAI5B,IACE,UAAU,eAAe,wBACzB,UAAU,iBACV,UAAU,UAEV,MAAM,yBAAyB,SAAS,QAAQ,SAAS;MACpD,IAAI,UAAU,eAAe,WAAW,UAAU,eAAe,OAAO,CAK/E,OAOE,MAAM,gBAAgB,SAAS,QAAQ,UAAU,MAAM;CAGzD,OAAO;AACT;AAEA,eAAe,yBACb,SACA,QACA,WACe;CACf,MAAM,EAAE,eAAe,aAAa;CACpC,IAAI,CAAC,iBAAiB,CAAC,UAAU;CAMjC,IAAI,OAAO,mBAAmB,QAAW;EACvC,MAAM,YAAY,uBAAuB,UAAU,QAAQ,UAAU,aAAa;EAClF,MAAM,aAAa,YAAY,oBAAoB,SAAS,IAAI;EAChE,IAAI,YAAY;GACd,MAAM,YAAY,SAAS,KAAK,MAAM,EAAE,kBAAkB,CAAC,CAAC,OAAO,OAAO;GAC1E,IAAI,UAAU,SAAS,GAAG;IACxB,WAAW,OAAO;IAClB,WAAW,UAAU,UAAU,KAAK,OAAO;KAAE,OAAO;KAAG,OAAO;IAAE,EAAE;GACpE;GACA,MAAM,iBAAiB,SAAS,QAAQ,UAAU;EACpD;CACF;CAGA,MAAM,YAAY,OAAO,OAAO,kBAAkB,EAAE;CACpD,MAAM,gBAAgB,SAAS,MAAM,MAAM,EAAE,uBAAuB,SAAS;CAE7E,IAAI,eAGF,MAAM,gBAAgB,SAAS,QADT,cAAc,OAAO,QAAQ,MAAM,EAAE,SAAS,aACjB,CAAC;AAIxD;;;;;AAMA,SAAS,uBACP,QACA,UACA,eAC+B;CAC/B,MAAM,WAAW,OAAO,MAAM,MAAM,EAAE,SAAS,aAAa;CAC5D,IAAI,UAAU,QAAQ,OAAO;CAC7B,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,QAAQ,QAAQ,OAAO,MAAM,MAAM,EAAE,SAAS,aAAa;EACjE,IAAI,OAAO,QAAQ,OAAO;CAC5B;AAEF;AAEA,eAAe,gBACb,SACA,QACA,QACe;CACf,MAAM,iBAAiB,kBAAkB,QAAQ,MAAM;CACvD,KAAK,MAAM,UAAU,gBACnB,MAAM,iBAAiB,SAAS,QAAQ,MAAM;AAElD;AAEA,eAAe,iBACb,SACA,QACA,QACe;CACf,MAAM,EAAE,YAAY;CACpB,IAAI;CACJ,QAAQ,OAAO,MAAf;EACE,KAAK;GACH,QAAQ,MAAM,QAAQ,KAAK;IAAE;IAAS,aAAa,OAAO,MAAM;GAAY,CAAC;GAC7E;EACF,KAAK;GACH,QAAQ,MAAM,QAAQ,SAAS,EAAE,QAAQ,CAAC;GAC1C;EACF,KAAK;GACH,QAAQ,MAAM,QAAQ,QAAQ,EAAE,QAAQ,CAAC;GACzC;EACF,KAAK;GACH,QAAQ,MAAM,QAAQ,OAAO;IAAE;IAAS,SAAS,OAAO,WAAW,CAAC;GAAE,CAAC;GACvE;CACJ;CACA,IAAI,QAAQ,YAAY,KAAK,GAC3B,MAAM,IAAI,MAAM,0BAA0B;CAE5C,OAAO,OAAO,MAAM,QAAQ;AAC9B"}
@@ -169,4 +169,4 @@ async function promptAndCollect(adapter, result, config) {
169
169
 
170
170
  //#endregion
171
171
  export { resolvePromptConfig as i, isInteractive as n, getFieldsToPrompt as r, promptMissingArgs as t };
172
- //# sourceMappingURL=prompt-BKHqGrFw.js.map
172
+ //# sourceMappingURL=prompt-Cc8Tfmdv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-BKHqGrFw.js","names":[],"sources":["../src/prompt/prompt-resolver.ts","../src/prompt/tty-detector.ts","../src/prompt/index.ts"],"sourcesContent":["import type { ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport type { ResolvedPromptConfig } from \"./types.js\";\n\n/**\n * Resolve prompt configuration for a field.\n *\n * Priority for prompt type:\n * 1. Explicit type from prompt.type\n * 2. Explicit choices from prompt.choices (forces \"select\")\n * 3. Inherited from completion metadata (file/directory -> \"text\")\n * 4. Auto-detected from Zod schema type:\n * - enum (has enumValues) -> \"select\"\n * - boolean -> \"confirm\"\n * - string/number/unknown -> \"text\"\n *\n * Returns null if the field has no prompt metadata or prompting is disabled.\n */\nexport function resolvePromptConfig(field: ResolvedFieldMeta): ResolvedPromptConfig | null {\n const promptMeta = field.prompt;\n if (!promptMeta || promptMeta.enabled === false) return null;\n\n const message = promptMeta.message ?? field.description ?? field.name;\n const rawType = resolvePromptType(field, promptMeta);\n const choices = resolveChoices(field, promptMeta, rawType);\n // Fall back to text when select has no choices to avoid adapter crash\n const type = rawType === \"select\" && !choices ? \"text\" : rawType;\n\n return { field, type, message, ...(choices && { choices }) };\n}\n\nfunction hasChoices(list: unknown[] | undefined): list is unknown[] {\n return list !== undefined && list.length > 0;\n}\n\nfunction resolvePromptType(\n field: ResolvedFieldMeta,\n promptMeta: NonNullable<ResolvedFieldMeta[\"prompt\"]>,\n): ResolvedPromptConfig[\"type\"] {\n // Priority 1: Explicit type\n if (promptMeta.type) {\n return promptMeta.type === \"file\" || promptMeta.type === \"directory\" ? \"text\" : promptMeta.type;\n }\n // Priority 2: Explicit choices\n if (hasChoices(promptMeta.choices)) return \"select\";\n // Priority 3: Inherited from completion type\n if (field.completion?.type === \"file\" || field.completion?.type === \"directory\") {\n return \"text\";\n }\n // Priority 4: Auto-detect from schema\n if (hasChoices(field.enumValues)) return \"select\";\n if (field.type === \"boolean\") return \"confirm\";\n return \"text\";\n}\n\nfunction resolveChoices(\n field: ResolvedFieldMeta,\n promptMeta: NonNullable<ResolvedFieldMeta[\"prompt\"]>,\n type: ResolvedPromptConfig[\"type\"],\n): ResolvedPromptConfig[\"choices\"] | undefined {\n // Explicit choices always win\n if (hasChoices(promptMeta.choices)) {\n return promptMeta.choices.map((c) => (typeof c === \"string\" ? { label: c, value: c } : c));\n }\n // Auto-populate from enum values for select type\n if (type === \"select\" && hasChoices(field.enumValues)) {\n return field.enumValues.map((v) => ({ label: v, value: v }));\n }\n return undefined;\n}\n\n/**\n * Filter fields that need prompting (missing value + prompt configured).\n *\n * For discriminatedUnion schemas, variant-aware narrowing is handled by the\n * caller (promptMissingArgs) which prompts the discriminator first and then\n * passes only the active variant's fields. For plain union schemas, this\n * iterates all fields across every variant without narrowing.\n *\n * Fields with Zod defaults that also have prompt metadata will be prompted\n * when the raw value is undefined. This is intentional: `prompt: {}` is an\n * explicit opt-in to interactive input. Omit prompt metadata to let the\n * default apply silently.\n */\nexport function getFieldsToPrompt(\n fields: ResolvedFieldMeta[],\n rawArgs: Record<string, unknown>,\n): ResolvedPromptConfig[] {\n const configs: ResolvedPromptConfig[] = [];\n for (const field of fields) {\n if (rawArgs[field.name] !== undefined) continue;\n // Array fields are not supported for interactive prompting yet;\n // a scalar text response would fail Zod array validation.\n // Object-valued fields (detected as type \"unknown\") are also unsupported\n // but share the \"unknown\" bucket with literals, so they are not filtered\n // here. Putting prompt metadata on object fields yields a Zod validation\n // error at parse time, which is an acceptable misconfiguration signal.\n if (field.type === \"array\") continue;\n const config = resolvePromptConfig(field);\n if (config) configs.push(config);\n }\n return configs;\n}\n","/**\n * Detect whether the current environment supports interactive prompts.\n * Returns false in CI, piped input, or non-TTY environments.\n */\nexport function isInteractive(): boolean {\n if (!process.stdin.isTTY) return false;\n if (!process.stdout.isTTY) return false;\n if (process.env.CI) return false;\n if (process.env.POLITTY_NO_PROMPT) return false;\n return true;\n}\n","import type { ExtractedFields, ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport { getFieldsToPrompt, resolvePromptConfig } from \"./prompt-resolver.js\";\nimport { isInteractive } from \"./tty-detector.js\";\nimport type { PromptAdapter, ResolvedPromptConfig } from \"./types.js\";\n\nexport { getFieldsToPrompt, resolvePromptConfig } from \"./prompt-resolver.js\";\nexport { isInteractive } from \"./tty-detector.js\";\nexport type { PromptAdapter, ResolvedPromptConfig } from \"./types.js\";\n\n/**\n * Options for promptMissingArgs behavior\n */\nexport interface PromptOptions {\n /** Prompt adapter to use for rendering prompts */\n adapter: PromptAdapter;\n /** Override interactive detection (force enable/disable prompts) */\n interactive?: boolean;\n}\n\n/**\n * Prompt for missing argument values interactively.\n *\n * Only prompts for fields that have `prompt` metadata set via `arg()` and\n * whose values are still undefined after CLI and env resolution.\n * Returns rawArgs unchanged in non-interactive environments.\n */\nexport async function promptMissingArgs(\n rawArgs: Record<string, unknown>,\n extracted: ExtractedFields,\n options: PromptOptions,\n): Promise<Record<string, unknown>> {\n const interactive = options.interactive ?? isInteractive();\n if (!interactive) return rawArgs;\n\n const adapter = options.adapter;\n const result = { ...rawArgs };\n\n // For discriminatedUnion schemas, prompt the discriminator first then\n // narrow to the active variant to avoid prompting irrelevant fields.\n if (\n extracted.schemaType === \"discriminatedUnion\" &&\n extracted.discriminator &&\n extracted.variants\n ) {\n await promptDiscriminatedUnion(adapter, result, extracted);\n } else if (extracted.schemaType === \"union\" || extracted.schemaType === \"xor\") {\n // Plain unions have no discriminator to narrow by. Prompting the merged\n // field set would collect answers for incompatible branches, causing\n // silent data loss (strip mode) or validation errors (strict mode).\n // Skip prompting and let Zod validation handle it.\n } else {\n // For object and intersection schemas, prompt all fields as a flat list.\n // Limitation: intersection schemas that compose a discriminatedUnion\n // (e.g. sharedOptions.and(z.discriminatedUnion(...))) lose variant\n // structure here because extractFields flattens both operands. Variant-\n // aware prompting for intersections requires architectural changes to\n // preserve sub-schema structure through extraction.\n await promptAllFields(adapter, result, extracted.fields);\n }\n\n return result;\n}\n\nasync function promptDiscriminatedUnion(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n extracted: ExtractedFields,\n): Promise<void> {\n const { discriminator, variants } = extracted;\n if (!discriminator || !variants) return;\n\n // Prompt for discriminator if not already provided.\n // The deduplicated extracted.fields only keeps the first variant's\n // discriminator, so scan all variants for prompt metadata and build\n // choices from every variant's discriminator value.\n if (result[discriminator] === undefined) {\n const discField = findDiscriminatorField(extracted.fields, variants, discriminator);\n const discConfig = discField ? resolvePromptConfig(discField) : null;\n if (discConfig) {\n const allValues = variants.map((v) => v.discriminatorValue).filter(Boolean);\n if (allValues.length > 0) {\n discConfig.type = \"select\";\n discConfig.choices = allValues.map((v) => ({ label: v, value: v }));\n }\n await promptAndCollect(adapter, result, discConfig);\n }\n }\n\n // Find the active variant based on discriminator value\n const discValue = String(result[discriminator] ?? \"\");\n const activeVariant = variants.find((v) => v.discriminatorValue === discValue);\n\n if (activeVariant) {\n // Prompt only the active variant's fields (excluding discriminator)\n const variantFields = activeVariant.fields.filter((f) => f.name !== discriminator);\n await promptAllFields(adapter, result, variantFields);\n }\n // When no variant matches (invalid value or unextracted discriminator),\n // skip prompting and let Zod validation surface the error.\n}\n\n/**\n * Find the discriminator field with prompt metadata, checking the\n * deduplicated top-level fields first, then scanning per-variant fields.\n */\nfunction findDiscriminatorField(\n fields: ResolvedFieldMeta[],\n variants: NonNullable<ExtractedFields[\"variants\"]>,\n discriminator: string,\n): ResolvedFieldMeta | undefined {\n const topLevel = fields.find((f) => f.name === discriminator);\n if (topLevel?.prompt) return topLevel;\n for (const variant of variants) {\n const field = variant.fields.find((f) => f.name === discriminator);\n if (field?.prompt) return field;\n }\n return undefined;\n}\n\nasync function promptAllFields(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n fields: ResolvedFieldMeta[],\n): Promise<void> {\n const fieldsToPrompt = getFieldsToPrompt(fields, result);\n for (const config of fieldsToPrompt) {\n await promptAndCollect(adapter, result, config);\n }\n}\n\nasync function promptAndCollect(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n config: ResolvedPromptConfig,\n): Promise<void> {\n const { message } = config;\n let value: unknown;\n switch (config.type) {\n case \"text\":\n value = await adapter.text({ message, placeholder: config.field.placeholder });\n break;\n case \"password\":\n value = await adapter.password({ message });\n break;\n case \"confirm\":\n value = await adapter.confirm({ message });\n break;\n case \"select\":\n value = await adapter.select({ message, options: config.choices ?? [] });\n break;\n }\n if (adapter.isCancelled(value)) {\n throw new Error(\"Prompt cancelled by user\");\n }\n result[config.field.name] = value;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"prompt-Cc8Tfmdv.js","names":[],"sources":["../src/prompt/prompt-resolver.ts","../src/prompt/tty-detector.ts","../src/prompt/index.ts"],"sourcesContent":["import type { ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport type { ResolvedPromptConfig } from \"./types.js\";\n\n/**\n * Resolve prompt configuration for a field.\n *\n * Priority for prompt type:\n * 1. Explicit type from prompt.type\n * 2. Explicit choices from prompt.choices (forces \"select\")\n * 3. Inherited from completion metadata (file/directory -> \"text\")\n * 4. Auto-detected from Zod schema type:\n * - enum (has enumValues) -> \"select\"\n * - boolean -> \"confirm\"\n * - string/number/unknown -> \"text\"\n *\n * Returns null if the field has no prompt metadata or prompting is disabled.\n */\nexport function resolvePromptConfig(field: ResolvedFieldMeta): ResolvedPromptConfig | null {\n const promptMeta = field.prompt;\n if (!promptMeta || promptMeta.enabled === false) return null;\n\n const message = promptMeta.message ?? field.description ?? field.name;\n const rawType = resolvePromptType(field, promptMeta);\n const choices = resolveChoices(field, promptMeta, rawType);\n // Fall back to text when select has no choices to avoid adapter crash\n const type = rawType === \"select\" && !choices ? \"text\" : rawType;\n\n return { field, type, message, ...(choices && { choices }) };\n}\n\nfunction hasChoices(list: unknown[] | undefined): list is unknown[] {\n return list !== undefined && list.length > 0;\n}\n\nfunction resolvePromptType(\n field: ResolvedFieldMeta,\n promptMeta: NonNullable<ResolvedFieldMeta[\"prompt\"]>,\n): ResolvedPromptConfig[\"type\"] {\n // Priority 1: Explicit type\n if (promptMeta.type) {\n return promptMeta.type === \"file\" || promptMeta.type === \"directory\" ? \"text\" : promptMeta.type;\n }\n // Priority 2: Explicit choices\n if (hasChoices(promptMeta.choices)) return \"select\";\n // Priority 3: Inherited from completion type\n if (field.completion?.type === \"file\" || field.completion?.type === \"directory\") {\n return \"text\";\n }\n // Priority 4: Auto-detect from schema\n if (hasChoices(field.enumValues)) return \"select\";\n if (field.type === \"boolean\") return \"confirm\";\n return \"text\";\n}\n\nfunction resolveChoices(\n field: ResolvedFieldMeta,\n promptMeta: NonNullable<ResolvedFieldMeta[\"prompt\"]>,\n type: ResolvedPromptConfig[\"type\"],\n): ResolvedPromptConfig[\"choices\"] | undefined {\n // Explicit choices always win\n if (hasChoices(promptMeta.choices)) {\n return promptMeta.choices.map((c) => (typeof c === \"string\" ? { label: c, value: c } : c));\n }\n // Auto-populate from enum values for select type\n if (type === \"select\" && hasChoices(field.enumValues)) {\n return field.enumValues.map((v) => ({ label: v, value: v }));\n }\n return undefined;\n}\n\n/**\n * Filter fields that need prompting (missing value + prompt configured).\n *\n * For discriminatedUnion schemas, variant-aware narrowing is handled by the\n * caller (promptMissingArgs) which prompts the discriminator first and then\n * passes only the active variant's fields. For plain union schemas, this\n * iterates all fields across every variant without narrowing.\n *\n * Fields with Zod defaults that also have prompt metadata will be prompted\n * when the raw value is undefined. This is intentional: `prompt: {}` is an\n * explicit opt-in to interactive input. Omit prompt metadata to let the\n * default apply silently.\n */\nexport function getFieldsToPrompt(\n fields: ResolvedFieldMeta[],\n rawArgs: Record<string, unknown>,\n): ResolvedPromptConfig[] {\n const configs: ResolvedPromptConfig[] = [];\n for (const field of fields) {\n if (rawArgs[field.name] !== undefined) continue;\n // Array fields are not supported for interactive prompting yet;\n // a scalar text response would fail Zod array validation.\n // Object-valued fields (detected as type \"unknown\") are also unsupported\n // but share the \"unknown\" bucket with literals, so they are not filtered\n // here. Putting prompt metadata on object fields yields a Zod validation\n // error at parse time, which is an acceptable misconfiguration signal.\n if (field.type === \"array\") continue;\n const config = resolvePromptConfig(field);\n if (config) configs.push(config);\n }\n return configs;\n}\n","/**\n * Detect whether the current environment supports interactive prompts.\n * Returns false in CI, piped input, or non-TTY environments.\n */\nexport function isInteractive(): boolean {\n if (!process.stdin.isTTY) return false;\n if (!process.stdout.isTTY) return false;\n if (process.env.CI) return false;\n if (process.env.POLITTY_NO_PROMPT) return false;\n return true;\n}\n","import type { ExtractedFields, ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport { getFieldsToPrompt, resolvePromptConfig } from \"./prompt-resolver.js\";\nimport { isInteractive } from \"./tty-detector.js\";\nimport type { PromptAdapter, ResolvedPromptConfig } from \"./types.js\";\n\nexport { getFieldsToPrompt, resolvePromptConfig } from \"./prompt-resolver.js\";\nexport { isInteractive } from \"./tty-detector.js\";\nexport type { PromptAdapter, ResolvedPromptConfig } from \"./types.js\";\n\n/**\n * Options for promptMissingArgs behavior\n */\nexport interface PromptOptions {\n /** Prompt adapter to use for rendering prompts */\n adapter: PromptAdapter;\n /** Override interactive detection (force enable/disable prompts) */\n interactive?: boolean;\n}\n\n/**\n * Prompt for missing argument values interactively.\n *\n * Only prompts for fields that have `prompt` metadata set via `arg()` and\n * whose values are still undefined after CLI and env resolution.\n * Returns rawArgs unchanged in non-interactive environments.\n */\nexport async function promptMissingArgs(\n rawArgs: Record<string, unknown>,\n extracted: ExtractedFields,\n options: PromptOptions,\n): Promise<Record<string, unknown>> {\n const interactive = options.interactive ?? isInteractive();\n if (!interactive) return rawArgs;\n\n const adapter = options.adapter;\n const result = { ...rawArgs };\n\n // For discriminatedUnion schemas, prompt the discriminator first then\n // narrow to the active variant to avoid prompting irrelevant fields.\n if (\n extracted.schemaType === \"discriminatedUnion\" &&\n extracted.discriminator &&\n extracted.variants\n ) {\n await promptDiscriminatedUnion(adapter, result, extracted);\n } else if (extracted.schemaType === \"union\" || extracted.schemaType === \"xor\") {\n // Plain unions have no discriminator to narrow by. Prompting the merged\n // field set would collect answers for incompatible branches, causing\n // silent data loss (strip mode) or validation errors (strict mode).\n // Skip prompting and let Zod validation handle it.\n } else {\n // For object and intersection schemas, prompt all fields as a flat list.\n // Limitation: intersection schemas that compose a discriminatedUnion\n // (e.g. sharedOptions.and(z.discriminatedUnion(...))) lose variant\n // structure here because extractFields flattens both operands. Variant-\n // aware prompting for intersections requires architectural changes to\n // preserve sub-schema structure through extraction.\n await promptAllFields(adapter, result, extracted.fields);\n }\n\n return result;\n}\n\nasync function promptDiscriminatedUnion(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n extracted: ExtractedFields,\n): Promise<void> {\n const { discriminator, variants } = extracted;\n if (!discriminator || !variants) return;\n\n // Prompt for discriminator if not already provided.\n // The deduplicated extracted.fields only keeps the first variant's\n // discriminator, so scan all variants for prompt metadata and build\n // choices from every variant's discriminator value.\n if (result[discriminator] === undefined) {\n const discField = findDiscriminatorField(extracted.fields, variants, discriminator);\n const discConfig = discField ? resolvePromptConfig(discField) : null;\n if (discConfig) {\n const allValues = variants.map((v) => v.discriminatorValue).filter(Boolean);\n if (allValues.length > 0) {\n discConfig.type = \"select\";\n discConfig.choices = allValues.map((v) => ({ label: v, value: v }));\n }\n await promptAndCollect(adapter, result, discConfig);\n }\n }\n\n // Find the active variant based on discriminator value\n const discValue = String(result[discriminator] ?? \"\");\n const activeVariant = variants.find((v) => v.discriminatorValue === discValue);\n\n if (activeVariant) {\n // Prompt only the active variant's fields (excluding discriminator)\n const variantFields = activeVariant.fields.filter((f) => f.name !== discriminator);\n await promptAllFields(adapter, result, variantFields);\n }\n // When no variant matches (invalid value or unextracted discriminator),\n // skip prompting and let Zod validation surface the error.\n}\n\n/**\n * Find the discriminator field with prompt metadata, checking the\n * deduplicated top-level fields first, then scanning per-variant fields.\n */\nfunction findDiscriminatorField(\n fields: ResolvedFieldMeta[],\n variants: NonNullable<ExtractedFields[\"variants\"]>,\n discriminator: string,\n): ResolvedFieldMeta | undefined {\n const topLevel = fields.find((f) => f.name === discriminator);\n if (topLevel?.prompt) return topLevel;\n for (const variant of variants) {\n const field = variant.fields.find((f) => f.name === discriminator);\n if (field?.prompt) return field;\n }\n return undefined;\n}\n\nasync function promptAllFields(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n fields: ResolvedFieldMeta[],\n): Promise<void> {\n const fieldsToPrompt = getFieldsToPrompt(fields, result);\n for (const config of fieldsToPrompt) {\n await promptAndCollect(adapter, result, config);\n }\n}\n\nasync function promptAndCollect(\n adapter: PromptAdapter,\n result: Record<string, unknown>,\n config: ResolvedPromptConfig,\n): Promise<void> {\n const { message } = config;\n let value: unknown;\n switch (config.type) {\n case \"text\":\n value = await adapter.text({ message, placeholder: config.field.placeholder });\n break;\n case \"password\":\n value = await adapter.password({ message });\n break;\n case \"confirm\":\n value = await adapter.confirm({ message });\n break;\n case \"select\":\n value = await adapter.select({ message, options: config.choices ?? [] });\n break;\n }\n if (adapter.isCancelled(value)) {\n throw new Error(\"Prompt cancelled by user\");\n }\n result[config.field.name] = value;\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { a as toCamelCase, c as listSubCommands, d as resolveSubcommandWithAlias, f as isLazyCommand, l as resolveLazyCommand, m as resolveSubCommandMeta, n as getAllAliases, o as toKebabCase, r as getExtractedFields, s as listSubCommandNamesWithAliases, t as extractFields } from "./schema-extractor-C50R-1re.js";
2
- import { n as emptyLogs, r as mergeLogs, t as createLogCollector } from "./log-collector-Cu6MCtAx.js";
1
+ import { a as toCamelCase, c as listSubCommands, d as resolveSubcommandWithAlias, f as isLazyCommand, l as resolveLazyCommand, m as resolveSubCommandMeta, n as getAllAliases, o as toKebabCase, r as getExtractedFields, s as listSubCommandNamesWithAliases, t as extractFields } from "./schema-extractor-Dqe7_kyQ.js";
2
+ import { n as emptyLogs, r as mergeLogs, t as createLogCollector } from "./log-collector-DK32-73m.js";
3
3
  import { styleText } from "node:util";
4
4
  import stringWidth from "string-width";
5
5
 
@@ -1848,28 +1848,61 @@ const BUILTIN_FLAGS = new Set([
1848
1848
  "--version"
1849
1849
  ]);
1850
1850
  /**
1851
- * Find the first positional argument in argv, properly skipping global flag values.
1852
- * Without globalExtracted, falls back to the first non-flag token.
1853
- */
1854
- function findFirstPositional(argv, globalExtracted) {
1855
- if (!globalExtracted) return argv.find((arg) => !arg.startsWith("-"));
1856
- const lookup = buildGlobalFlagLookup(globalExtracted);
1851
+ * Find the index of the first positional argument in argv, properly skipping
1852
+ * global flag values. Returns -1 when no positional is present.
1853
+ *
1854
+ * Mirrors `scanForSubcommand`'s conservative stop conditions: the scan stops
1855
+ * (returning -1) on a `--` terminator, a builtin flag (`--help`/`--version`),
1856
+ * an unknown long flag, or an unknown/combined short flag. Past such tokens we
1857
+ * can't tell a flag *value* from a positional, so continuing would misclassify
1858
+ * e.g. `--help plugin` or `--unknown value` and wrongly trip plugin dispatch.
1859
+ *
1860
+ * Without globalExtracted, no flag is global, so any leading flag halts the
1861
+ * scan and a positional is only found when it precedes every flag.
1862
+ */
1863
+ function findFirstPositionalIndex(argv, globalExtracted) {
1864
+ const lookup = globalExtracted ? buildGlobalFlagLookup(globalExtracted) : {
1865
+ aliasMap: /* @__PURE__ */ new Map(),
1866
+ booleanFlags: /* @__PURE__ */ new Set(),
1867
+ flagNames: /* @__PURE__ */ new Set(),
1868
+ cliNames: /* @__PURE__ */ new Set(),
1869
+ aliases: /* @__PURE__ */ new Set(),
1870
+ negationMap: /* @__PURE__ */ new Map(),
1871
+ customNegatedFields: /* @__PURE__ */ new Set()
1872
+ };
1857
1873
  for (let i = 0; i < argv.length; i++) {
1858
1874
  const arg = argv[i];
1859
- if (!arg.startsWith("-")) return arg;
1860
- if (arg === "--") return void 0;
1875
+ if (!arg.startsWith("-")) return i;
1876
+ if (arg === "--" || BUILTIN_FLAGS.has(arg)) return -1;
1861
1877
  if (arg.startsWith("--")) {
1862
- const { resolvedName, isNegated, isGlobal } = resolveGlobalLongOption(arg, lookup);
1863
- if (isGlobal && shouldConsumeValue(arg, resolvedName, isNegated, argv[i + 1], lookup.booleanFlags)) i++;
1864
- continue;
1878
+ const { resolvedName, isNegated, isGlobal, isSuppressedNegation } = resolveGlobalLongOption(arg, lookup);
1879
+ if (isGlobal) {
1880
+ if (shouldConsumeValue(arg, resolvedName, isNegated, argv[i + 1], lookup.booleanFlags)) i++;
1881
+ continue;
1882
+ }
1883
+ if (isSuppressedNegation) continue;
1884
+ return -1;
1865
1885
  }
1866
- if (arg.length === 2) {
1867
- const ch = arg[1];
1868
- if (lookup.aliases.has(ch)) {
1869
- if (shouldConsumeValue(arg, lookup.aliasMap.get(ch) ?? ch, false, argv[i + 1], lookup.booleanFlags)) i++;
1886
+ const withoutDash = arg.includes("=") ? arg.slice(1, arg.indexOf("=")) : arg.slice(1);
1887
+ if (withoutDash.length === 1) {
1888
+ const resolvedName = lookup.aliasMap.get(withoutDash) ?? withoutDash;
1889
+ if (lookup.aliases.has(withoutDash) || lookup.flagNames.has(resolvedName)) {
1890
+ if (shouldConsumeValue(arg, resolvedName, false, argv[i + 1], lookup.booleanFlags)) i++;
1891
+ continue;
1870
1892
  }
1871
1893
  }
1894
+ return -1;
1872
1895
  }
1896
+ return -1;
1897
+ }
1898
+ /**
1899
+ * Find the first positional argument in argv, properly skipping global flag
1900
+ * values. Thin wrapper over {@link findFirstPositionalIndex} — see that
1901
+ * function for the scan and stop conditions. Returns `undefined` when none.
1902
+ */
1903
+ function findFirstPositional(argv, globalExtracted) {
1904
+ const index = findFirstPositionalIndex(argv, globalExtracted);
1905
+ return index >= 0 ? argv[index] : void 0;
1873
1906
  }
1874
1907
 
1875
1908
  //#endregion
@@ -2331,6 +2364,25 @@ async function runMain(command, options = {}) {
2331
2364
  effectiveOptions = rest;
2332
2365
  }
2333
2366
  const globalExtracted = extractAndValidateGlobal(effectiveOptions);
2367
+ if (effectiveOptions.onUnknownSubcommand && !isInternalSubcommandInvocation(command, argv, globalExtractedForBypass)) {
2368
+ const knownSubCommands = listSubCommandNamesWithAliases(command);
2369
+ if (knownSubCommands.size > 0) {
2370
+ const positionalIndex = findFirstPositionalIndex(argv, globalExtracted);
2371
+ const name = positionalIndex >= 0 ? argv[positionalIndex] : void 0;
2372
+ if (name && !knownSubCommands.has(name)) {
2373
+ const forwardArgs = argv.slice(positionalIndex + 1);
2374
+ const exitCode = await effectiveOptions.onUnknownSubcommand({
2375
+ commandPath: [],
2376
+ name,
2377
+ args: forwardArgs
2378
+ });
2379
+ if (typeof exitCode === "number") {
2380
+ await flushStandardStreams();
2381
+ return process.exit(exitCode);
2382
+ }
2383
+ }
2384
+ }
2385
+ }
2334
2386
  if (effectiveOptions.setup) try {
2335
2387
  await effectiveOptions.setup({});
2336
2388
  } catch (e) {
@@ -2348,6 +2400,7 @@ async function runMain(command, options = {}) {
2348
2400
  logger: effectiveOptions.logger,
2349
2401
  globalArgs: effectiveOptions.globalArgs,
2350
2402
  prompt: effectiveOptions.prompt,
2403
+ onUnknownSubcommand: effectiveOptions.onUnknownSubcommand,
2351
2404
  _globalExtracted: globalExtracted,
2352
2405
  _globalCleanup: effectiveOptions.cleanup,
2353
2406
  _context: {
@@ -2364,11 +2417,22 @@ async function runMain(command, options = {}) {
2364
2417
  await effectiveOptions.cleanup(cleanupCtx);
2365
2418
  } catch {}
2366
2419
  }
2367
- if (process.stdout.writableLength > 0) await new Promise((resolve) => process.stdout.once("drain", resolve));
2368
- if (process.stderr.writableLength > 0) await new Promise((resolve) => process.stderr.once("drain", resolve));
2420
+ await flushStandardStreams();
2369
2421
  process.exit(result.exitCode);
2370
2422
  }
2371
2423
  /**
2424
+ * Flush stdout/stderr before exit to prevent truncated output when piped
2425
+ * (pipe writes are buffered asynchronously, so exiting early loses data).
2426
+ *
2427
+ * We await a zero-byte write's callback rather than a `drain` event: `drain`
2428
+ * only fires after a `write()` returned `false` (backpressure), so buffered
2429
+ * writes that never tripped it would hang. The write callback is ordered after
2430
+ * all pending writes, so it resolves once the buffer is flushed.
2431
+ */
2432
+ async function flushStandardStreams() {
2433
+ await Promise.all([process.stdout, process.stderr].map((stream) => stream.writableLength > 0 ? new Promise((resolve) => stream.write("", () => resolve())) : Promise.resolve()));
2434
+ }
2435
+ /**
2372
2436
  * Internal implementation of command running
2373
2437
  */
2374
2438
  async function runCommandInternal(command, argv, options = {}) {
@@ -2392,6 +2456,43 @@ async function runCommandInternal(command, argv, options = {}) {
2392
2456
  ...options._parsedGlobalArgs,
2393
2457
  ...parseResult.rawGlobalArgs
2394
2458
  };
2459
+ const nestedCommandPath = context.commandPath ?? [];
2460
+ if (options.onUnknownSubcommand && nestedCommandPath.length > 0) {
2461
+ const knownSubCommands = listSubCommandNamesWithAliases(command);
2462
+ if (knownSubCommands.size > 0) {
2463
+ const positionalIndex = findFirstPositionalIndex(argv, options._globalExtracted);
2464
+ const name = positionalIndex >= 0 ? argv[positionalIndex] : void 0;
2465
+ if (name && !knownSubCommands.has(name)) {
2466
+ const forwardArgs = argv.slice(positionalIndex + 1);
2467
+ const exitCode = await options.onUnknownSubcommand({
2468
+ commandPath: nestedCommandPath,
2469
+ name,
2470
+ args: forwardArgs
2471
+ });
2472
+ if (typeof exitCode === "number") {
2473
+ collector?.stop();
2474
+ if (options.handleSignals) {
2475
+ if (options._globalCleanup) try {
2476
+ await options._globalCleanup({ error: void 0 });
2477
+ } catch {}
2478
+ await flushStandardStreams();
2479
+ process.exit(exitCode);
2480
+ }
2481
+ return exitCode === 0 ? {
2482
+ success: true,
2483
+ result: void 0,
2484
+ exitCode: 0,
2485
+ logs: getCurrentLogs()
2486
+ } : {
2487
+ success: false,
2488
+ error: /* @__PURE__ */ new Error(`Plugin "${[...nestedCommandPath, name].join(" ")}" exited with code ${exitCode}`),
2489
+ exitCode,
2490
+ logs: getCurrentLogs()
2491
+ };
2492
+ }
2493
+ }
2494
+ }
2495
+ }
2395
2496
  if (parseResult.helpRequested || parseResult.helpAllRequested) {
2396
2497
  let hasUnknownSubcommand = false;
2397
2498
  const subCmdNames = listSubCommands(command);
@@ -2604,4 +2705,4 @@ function extractAndValidateGlobal(options) {
2604
2705
 
2605
2706
  //#endregion
2606
2707
  export { renderMarkdown as C, styles as D, setColorEnabled as E, symbols as O, renderInline as S, logger as T, DuplicateFieldError as _, parseArgv as a, ReservedAliasError as b, validateCommand as c, validateDuplicateFields as d, validateDuplicateNegations as f, DuplicateAliasError as g, CaseVariantCollisionError as h, formatValidationErrors as i, createDualCaseProxy as k, validateCrossSchemaCollisions as l, validateReservedAliases as m, runMain as n, formatCommandValidationErrors as o, validatePositionalConfig as p, runner_exports as r, validateCaseVariantCollisions as s, runCommand as t, validateDuplicateAliases as u, DuplicateNegationError as v, isColorEnabled as w, generateHelp as x, PositionalConfigError as y };
2607
- //# sourceMappingURL=runner-BmSEiD9A.js.map
2708
+ //# sourceMappingURL=runner-D43SkHt5.js.map