{"version":3,"file":"errors-BjJnpXkK.mjs","names":[],"sources":["../src/cli/shared/errors.ts"],"sourcesContent":["import { styles } from \"./logger\";\nimport type { Jsonifiable } from \"type-fest\";\n\n/**\n * Options for creating a CLI error\n */\ninterface CLIErrorOptions {\n  /** Stable machine-readable failure code, such as `WORKSPACE_NOT_FOUND`. */\n  code: string;\n  message: string;\n  details?: string;\n  suggestion?: string;\n  command?: string;\n  next?: CLIErrorNextAction;\n  context?: Readonly<Record<string, Jsonifiable | undefined>>;\n  cause?: unknown;\n}\n\nexport type CLIErrorNextAction = {\n  /** Executable name, such as `tailor`. */\n  command: string;\n  /** Arguments passed directly to the executable. */\n  args: readonly string[];\n};\n\n/**\n * CLI error interface with formatted output\n */\nexport interface CLIError extends Error {\n  readonly code: string;\n  readonly details?: string;\n  readonly suggestion?: string;\n  readonly command?: string;\n  readonly next?: CLIErrorNextAction;\n  readonly context?: Readonly<Record<string, Jsonifiable | undefined>>;\n  format(): string;\n}\n\ntype CLIErrorInternal = Error & {\n  code: string;\n  details?: string;\n  suggestion?: string;\n  command?: string;\n  next?: CLIErrorNextAction;\n  context?: Readonly<Record<string, Jsonifiable | undefined>>;\n  format(): string;\n};\n\nfunction shellQuote(value: string): string {\n  if (process.platform === \"win32\") {\n    if (/^[A-Za-z0-9_./:=@+\\\\-]+$/.test(value)) return value;\n    return `\"${value.replaceAll('\"', '\\\\\"')}\"`;\n  }\n  if (/^[A-Za-z0-9_./:=@+-]+$/.test(value)) return value;\n  return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n\nfunction needsArgvRendering(argv: readonly string[]): boolean {\n  // cmd.exe/PowerShell expand %, $, and ! even inside double quotes, so no\n  // quoting can keep such values literal on Windows.\n  return process.platform === \"win32\" && argv.some((value) => /[%$!]/.test(value));\n}\n\n/**\n * Render an argv array as a copyable command line for the current platform's shell\n * @param {readonly string[]} argv - Executable name followed by its arguments\n * @returns {string} A shell-quoted command line, or an `argv [...]` JSON rendering when the platform shell cannot keep a value literal\n */\nexport function formatCopyableCommand(argv: readonly string[]): string {\n  if (needsArgvRendering(argv)) {\n    return `argv ${JSON.stringify(argv)}`;\n  }\n  return argv.map(shellQuote).join(\" \");\n}\n\n/**\n * Format an executable and argv as a shell-safe user-facing command.\n * @param next - Executable and arguments to format\n * @returns Shell command, or an argv representation when shell quoting is unsafe\n */\nexport function formatNextAction(next: CLIErrorNextAction): string {\n  const argv = [next.command, ...next.args];\n  const rendered = formatCopyableCommand(argv);\n  return needsArgvRendering(argv) ? `with ${rendered}` : `\\`${rendered}\\``;\n}\n\n/**\n * Format CLI error for output\n * @param error - CLIError instance to format\n * @returns Formatted error message\n */\nfunction formatError(error: CLIError): string {\n  const parts: string[] = [\n    styles.error(`Error${error.code ? ` [${error.code}]` : \"\"}: ${error.message}`),\n  ];\n\n  if (error.details) {\n    parts.push(`\\n  ${styles.dim(\"Details:\")} ${error.details.split(\"\\n\").join(\"\\n  \")}`);\n  }\n\n  if (error.suggestion) {\n    parts.push(`\\n  ${styles.info(\"Suggestion:\")} ${error.suggestion.split(\"\\n\").join(\"\\n  \")}`);\n  }\n\n  if (error.command) {\n    parts.push(\n      `\\n  ${styles.dim(\"Help:\")} Run \\`tailor ${error.command} --help\\` for usage information.`,\n    );\n  }\n\n  if (error.next) {\n    parts.push(`\\n  ${styles.info(\"Next:\")} Run ${formatNextAction(error.next)}.`);\n  }\n\n  return parts.join(\"\");\n}\n\n/**\n * Create a CLI error with formatted output\n * @param options - Options to construct a CLIError\n * @returns Constructed CLIError instance\n */\nexport function CLIError(options: CLIErrorOptions): CLIError {\n  const error = new Error(\n    options.message,\n    options.cause === undefined ? undefined : { cause: options.cause },\n  ) as CLIErrorInternal;\n  error.name = \"CLIError\";\n  error.code = options.code;\n  error.details = options.details;\n  error.suggestion = options.suggestion;\n  error.command = options.command;\n  error.next = options.next;\n  error.context = options.context;\n  error.format = () => formatError(error);\n  return error;\n}\n\n/**\n * Type guard to check if an error is a CLIError\n * @param error - Error to check\n * @returns True if the error is a CLIError\n */\nexport function isCLIError(error: unknown): error is CLIError {\n  return error instanceof Error && error.name === \"CLIError\";\n}\n\n/**\n * Summarize a failure as plain text for reports that carry a single error string.\n * CLI errors contribute their details and suggestion so the remediation survives.\n * @param error - Failure to summarize\n * @returns Message followed by any details and suggestion, one per line\n */\nexport function errorSummary(error: unknown): string {\n  if (isCLIError(error)) {\n    return [error.message, error.details, error.suggestion].filter(Boolean).join(\"\\n\");\n  }\n  return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Create an error for an SDK invariant violation that no user action can fix.\n * The result is a plain Error, so JSON output reports it as `UNEXPECTED_ERROR`\n * and crash reporting treats it like any other unexpected failure.\n * @param message - Description of the violated invariant\n * @param options - Standard Error options, such as `cause`\n * @returns Plain Error instance\n */\nexport function internalError(message: string, options?: ErrorOptions): Error {\n  return new Error(message, options);\n}\n\n/**\n * Convert a caught value into an Error, keeping Error instances as-is\n * @param value - Caught value\n * @returns The value itself when it is an Error, otherwise an Error of its string form with the value as `cause`\n */\nexport function toError(value: unknown): Error {\n  return value instanceof Error ? value : new Error(String(value), { cause: value });\n}\n\nconst MISSING_NAMED_EXPORT_PATTERN = /does not provide an export named '(?!default')([^']+)'/;\n\n/**\n * Suggest `import type` when importing user code fails on a missing named\n * export. The CLI strips types from each file in isolation, so a type-only\n * export does not exist at runtime and a plain import of it fails to link.\n * @param error - Error thrown while importing user modules\n * @returns Suggestion text, or undefined when the error is not that failure\n */\nexport function typeOnlyImportHint(error: unknown): string | undefined {\n  if (!(error instanceof SyntaxError)) return undefined;\n  const name = MISSING_NAMED_EXPORT_PATTERN.exec(error.message)?.[1];\n  if (!name) return undefined;\n  return (\n    `If '${name}' is a type, import it with \\`import type\\` (or the inline \\`type\\` modifier). ` +\n    \"The CLI runs TypeScript by stripping types from each file in isolation, so type-only exports do not exist at runtime. \" +\n    'Set \"verbatimModuleSyntax\": true in tsconfig.json to catch this at typecheck.'\n  );\n}\n"],"mappings":"0CAgDA,SAAS,WAAW,EAAuB,CAMzC,OALI,QAAQ,WAAa,QACnB,2BAA2B,KAAK,CAAK,EAAU,EAC5C,IAAI,EAAM,WAAW,IAAK,KAAK,EAAE,GAEtC,yBAAyB,KAAK,CAAK,EAAU,EAC1C,IAAI,EAAM,WAAW,IAAK,OAAO,EAAE,EAC5C,CAEA,SAAS,mBAAmB,EAAkC,CAG5D,OAAO,QAAQ,WAAa,SAAW,EAAK,KAAM,GAAU,QAAQ,KAAK,CAAK,CAAC,CACjF,CAOA,SAAgB,sBAAsB,EAAiC,CAIrE,OAHI,mBAAmB,CAAI,EAClB,QAAQ,KAAK,UAAU,CAAI,IAE7B,EAAK,IAAI,UAAU,CAAC,CAAC,KAAK,GAAG,CACtC,CAOA,SAAgB,iBAAiB,EAAkC,CACjE,IAAM,EAAO,CAAC,EAAK,QAAS,GAAG,EAAK,IAAI,EAClC,EAAW,sBAAsB,CAAI,EAC3C,OAAO,mBAAmB,CAAI,EAAI,QAAQ,IAAa,KAAK,EAAS,GACvE,CAOA,SAAS,YAAY,EAAyB,CAC5C,IAAM,EAAkB,CACtB,EAAO,MAAM,QAAQ,EAAM,KAAO,KAAK,EAAM,KAAK,GAAK,GAAG,IAAI,EAAM,SAAS,CAC/E,EAoBA,OAlBI,EAAM,SACR,EAAM,KAAK,OAAO,EAAO,IAAI,UAAU,EAAE,GAAG,EAAM,QAAQ,MAAM;CAAI,CAAC,CAAC,KAAK;GAAM,GAAG,EAGlF,EAAM,YACR,EAAM,KAAK,OAAO,EAAO,KAAK,aAAa,EAAE,GAAG,EAAM,WAAW,MAAM;CAAI,CAAC,CAAC,KAAK;GAAM,GAAG,EAGzF,EAAM,SACR,EAAM,KACJ,OAAO,EAAO,IAAI,OAAO,EAAE,gBAAgB,EAAM,QAAQ,iCAC3D,EAGE,EAAM,MACR,EAAM,KAAK,OAAO,EAAO,KAAK,OAAO,EAAE,OAAO,iBAAiB,EAAM,IAAI,EAAE,EAAE,EAGxE,EAAM,KAAK,EAAE,CACtB,CAOA,SAAgB,SAAS,EAAoC,CAC3D,IAAM,EAAY,MAChB,EAAQ,QACR,EAAQ,QAAU,IAAA,GAAY,IAAA,GAAY,CAAE,MAAO,EAAQ,KAAM,CACnE,EASA,MARA,GAAM,KAAO,WACb,EAAM,KAAO,EAAQ,KACrB,EAAM,QAAU,EAAQ,QACxB,EAAM,WAAa,EAAQ,WAC3B,EAAM,QAAU,EAAQ,QACxB,EAAM,KAAO,EAAQ,KACrB,EAAM,QAAU,EAAQ,QACxB,EAAM,WAAe,YAAY,CAAK,EAC/B,CACT,CAOA,SAAgB,WAAW,EAAmC,CAC5D,OAAO,aAAiB,OAAS,EAAM,OAAS,UAClD,CAQA,SAAgB,aAAa,EAAwB,CAInD,OAHI,WAAW,CAAK,EACX,CAAC,EAAM,QAAS,EAAM,QAAS,EAAM,UAAU,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK;CAAI,EAE5E,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAC9D,CAUA,SAAgB,cAAc,EAAiB,EAA+B,CAC5E,OAAW,MAAM,EAAS,CAAO,CACnC,CAOA,SAAgB,QAAQ,EAAuB,CAC7C,OAAO,aAAiB,MAAQ,EAAY,MAAM,OAAO,CAAK,EAAG,CAAE,MAAO,CAAM,CAAC,CACnF,CAEA,MAAM,EAA+B,yDASrC,SAAgB,mBAAmB,EAAoC,CACrE,GAAI,EAAE,aAAiB,aAAc,OACrC,IAAM,EAAO,EAA6B,KAAK,EAAM,OAAO,CAAC,GAAG,GAC3D,KACL,MACE,OAAO,EAAK,mRAIhB"}