{"version":3,"file":"aimock-cli.cjs","names":["loadConfig","startFromConfig"],"sources":["../src/aimock-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\";\nimport { resolve, basename } from \"node:path\";\nimport { loadConfig, startFromConfig } from \"./config-loader.js\";\nimport { runConvertCli, type ConvertCliDeps } from \"./convert.js\";\n\nconst HELP = `\nUsage: aimock [options]\n       aimock convert <format> <input> [output]\n\nOptions:\n  -c, --config <path>   Path to aimock config JSON file (required)\n  -p, --port <number>   Port override (default: from config or 0)\n  -h, --host <string>   Host override (default: from config or 127.0.0.1)\n      --help            Show this help message\n\nSubcommands:\n  convert               Convert third-party mock configs to aimock format\n                        Run \"aimock convert --help\" for details\n`.trim();\n\nexport interface AimockCliDeps {\n  argv?: string[];\n  log?: (msg: string) => void;\n  logError?: (msg: string) => void;\n  exit?: (code: number) => void;\n  loadConfigFn?: typeof loadConfig;\n  startFromConfigFn?: typeof startFromConfig;\n  onReady?: (ctx: { shutdown: () => void }) => void;\n  convertDeps?: Partial<ConvertCliDeps>;\n}\n\nexport function runAimockCli(deps: AimockCliDeps = {}): void {\n  /* v8 ignore next 6 -- defaults used only when called from CLI entry point */\n  const argv = deps.argv ?? process.argv.slice(2);\n  const log = deps.log ?? console.log.bind(console);\n  const logError = deps.logError ?? console.error.bind(console);\n  const exit = deps.exit ?? process.exit.bind(process);\n  const loadConfigFn = deps.loadConfigFn ?? loadConfig;\n  const startFromConfigFn = deps.startFromConfigFn ?? startFromConfig;\n\n  // Intercept \"convert\" subcommand before parseArgs (which uses strict mode)\n  if (argv[0] === \"convert\") {\n    runConvertCli({\n      argv: argv.slice(1),\n      log,\n      logError,\n      exit,\n      ...deps.convertDeps,\n    });\n    return;\n  }\n\n  let values;\n  try {\n    ({ values } = parseArgs({\n      args: argv,\n      options: {\n        config: { type: \"string\", short: \"c\" },\n        port: { type: \"string\", short: \"p\" },\n        host: { type: \"string\", short: \"h\" },\n        help: { type: \"boolean\", default: false },\n      },\n      strict: true,\n    }));\n  } catch (err) {\n    /* v8 ignore next -- parseArgs always throws Error subclasses */\n    const msg = err instanceof Error ? err.message : String(err);\n    logError(`Error: ${msg}\\n\\n${HELP}`);\n    exit(1);\n    return;\n  }\n\n  if (values.help) {\n    log(HELP);\n    exit(0);\n    return;\n  }\n  if (!values.config) {\n    logError(\"Error: --config is required.\\n\\n\" + HELP);\n    exit(1);\n    return;\n  }\n\n  const configPath = resolve(values.config);\n  let config;\n  try {\n    config = loadConfigFn(configPath);\n  } catch (err) {\n    const msg = err instanceof Error ? err.message : String(err);\n    logError(`Failed to load config from ${configPath}: ${msg}`);\n    exit(1);\n    return;\n  }\n\n  const port = values.port ? Number(values.port) : undefined;\n  if (\n    port !== undefined &&\n    (Number.isNaN(port) || !Number.isInteger(port) || port < 0 || port > 65535)\n  ) {\n    logError(`Error: invalid port \"${values.port}\".\\n\\n${HELP}`);\n    exit(1);\n    return;\n  }\n  const host = values.host;\n\n  async function main() {\n    const { llmock, url } = await startFromConfigFn(config!, { port, host });\n    log(`aimock server listening on ${url}`);\n\n    function shutdown() {\n      log(\"Shutting down...\");\n      process.removeListener(\"SIGINT\", shutdown);\n      process.removeListener(\"SIGTERM\", shutdown);\n      llmock.stop().then(\n        () => exit(0),\n        (err) => {\n          logError(`Shutdown error: ${err instanceof Error ? err.message : String(err)}`);\n          exit(1);\n        },\n      );\n    }\n    process.on(\"SIGINT\", shutdown);\n    process.on(\"SIGTERM\", shutdown);\n\n    if (deps.onReady) {\n      deps.onReady({ shutdown });\n    }\n  }\n\n  main().catch((err) => {\n    logError(err instanceof Error ? err.message : String(err));\n    exit(1);\n  });\n}\n\n// Run when executed as a script (not when imported for testing).\n/* v8 ignore start -- entry-point guard, exercised by integration tests */\nconst scriptName = process.argv[1] ?? \"\";\nconst base = basename(scriptName);\nif (base === \"aimock\" || base === \"aimock-cli.js\" || base === \"aimock-cli.ts\") {\n  runAimockCli();\n}\n/* v8 ignore stop */\n"],"mappings":";;;;;;;;;AAMA,MAAM,OAAO;;;;;;;;;;;;;EAaX,MAAM;AAaR,SAAgB,aAAa,OAAsB,EAAE,EAAQ;;CAE3D,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,MAAM,EAAE;CAC/C,MAAM,MAAM,KAAK,OAAO,QAAQ,IAAI,KAAK,QAAQ;CACjD,MAAM,WAAW,KAAK,YAAY,QAAQ,MAAM,KAAK,QAAQ;CAC7D,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,KAAK,QAAQ;CACpD,MAAM,eAAe,KAAK,gBAAgBA;CAC1C,MAAM,oBAAoB,KAAK,qBAAqBC;AAGpD,KAAI,KAAK,OAAO,WAAW;AACzB,gCAAc;GACZ,MAAM,KAAK,MAAM,EAAE;GACnB;GACA;GACA;GACA,GAAG,KAAK;GACT,CAAC;AACF;;CAGF,IAAI;AACJ,KAAI;AACF,GAAC,CAAE,mCAAqB;GACtB,MAAM;GACN,SAAS;IACP,QAAQ;KAAE,MAAM;KAAU,OAAO;KAAK;IACtC,MAAM;KAAE,MAAM;KAAU,OAAO;KAAK;IACpC,MAAM;KAAE,MAAM;KAAU,OAAO;KAAK;IACpC,MAAM;KAAE,MAAM;KAAW,SAAS;KAAO;IAC1C;GACD,QAAQ;GACT,CAAC;UACK,KAAK;AAGZ,WAAS,UADG,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CACrC,MAAM,OAAO;AACpC,OAAK,EAAE;AACP;;AAGF,KAAI,OAAO,MAAM;AACf,MAAI,KAAK;AACT,OAAK,EAAE;AACP;;AAEF,KAAI,CAAC,OAAO,QAAQ;AAClB,WAAS,qCAAqC,KAAK;AACnD,OAAK,EAAE;AACP;;CAGF,MAAM,oCAAqB,OAAO,OAAO;CACzC,IAAI;AACJ,KAAI;AACF,WAAS,aAAa,WAAW;UAC1B,KAAK;AAEZ,WAAS,8BAA8B,WAAW,IADtC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACA;AAC5D,OAAK,EAAE;AACP;;CAGF,MAAM,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,GAAG;AACjD,KACE,SAAS,WACR,OAAO,MAAM,KAAK,IAAI,CAAC,OAAO,UAAU,KAAK,IAAI,OAAO,KAAK,OAAO,QACrE;AACA,WAAS,wBAAwB,OAAO,KAAK,QAAQ,OAAO;AAC5D,OAAK,EAAE;AACP;;CAEF,MAAM,OAAO,OAAO;CAEpB,eAAe,OAAO;EACpB,MAAM,EAAE,QAAQ,QAAQ,MAAM,kBAAkB,QAAS;GAAE;GAAM;GAAM,CAAC;AACxE,MAAI,8BAA8B,MAAM;EAExC,SAAS,WAAW;AAClB,OAAI,mBAAmB;AACvB,WAAQ,eAAe,UAAU,SAAS;AAC1C,WAAQ,eAAe,WAAW,SAAS;AAC3C,UAAO,MAAM,CAAC,WACN,KAAK,EAAE,GACZ,QAAQ;AACP,aAAS,mBAAmB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAAG;AAC/E,SAAK,EAAE;KAEV;;AAEH,UAAQ,GAAG,UAAU,SAAS;AAC9B,UAAQ,GAAG,WAAW,SAAS;AAE/B,MAAI,KAAK,QACP,MAAK,QAAQ,EAAE,UAAU,CAAC;;AAI9B,OAAM,CAAC,OAAO,QAAQ;AACpB,WAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC1D,OAAK,EAAE;GACP;;AAMJ,MAAM,+BADa,QAAQ,KAAK,MAAM,GACL;AACjC,IAAI,SAAS,YAAY,SAAS,mBAAmB,SAAS,gBAC5D,eAAc"}