{"version":3,"file":"documentation.cjs","names":[],"sources":["../../src/lib/documentation.ts"],"sourcesContent":["import {\n  UnknownOptionConfig,\n  OptionConfigToType,\n  readDefaultValue,\n  LocalizationDictionary,\n  ConfigurationFiles,\n  getEnvKey,\n} from '@cli-forge/parser';\nimport { AnyInternalCLI } from './internal-cli';\nimport { CLI } from './public-api';\n\nexport type Documentation = {\n  name: string;\n  description?: string;\n  epilogue?: string;\n  usage: string;\n  examples: string[];\n  options: Readonly<Record<string, NormalizedOptionConfig>>;\n  positionals: readonly Readonly<NormalizedOptionConfig>[];\n  groupedOptions: Array<{\n    label: string;\n    keys: Array<NormalizedOptionConfig>;\n  }>;\n  subcommands: Documentation[];\n  /**\n   * Describes how configuration is loaded for this command.\n   * Each section is produced by a provider's `describeConfig` method.\n   */\n  configurationSources?: ConfigurationFiles.ConfigurationDocSection[];\n  /**\n   * Localized keys for options and commands. Maps from default key to full localization entry.\n   * Only present if localization is configured.\n   */\n  localizedKeys?: LocalizationDictionary;\n};\n\nfunction resolveEnvKeyForOption(\n  option: UnknownOptionConfig,\n  optionKey: string,\n  envInfo: { prefix?: string; enabled: boolean }\n): string | undefined {\n  const { env } = option;\n\n  if (env === false) return undefined;\n  if (env === undefined && !envInfo.enabled) return undefined;\n\n  if (env === undefined || env === true) {\n    return getEnvKey(envInfo.prefix, optionKey);\n  }\n  if (typeof env === 'string') {\n    return getEnvKey(envInfo.prefix, env);\n  }\n  // Object form\n  if (env.populate === false) return undefined;\n  const envKey = env.key ?? optionKey;\n  const prefix = env.prefix === false ? undefined : envInfo.prefix;\n  return getEnvKey(prefix, envKey);\n}\n\nfunction normalizeOptionConfigForDocumentation<T extends UnknownOptionConfig>(\n  option: T,\n  key: string,\n  envInfo?: { prefix?: string; enabled: boolean }\n) {\n  const { default: declaredDefault, ...rest } = option;\n  let resolvedDefault: OptionConfigToType<T> | string | undefined;\n  if (declaredDefault !== undefined) {\n    const [defaultValue, description] = readDefaultValue(option);\n    resolvedDefault = description ?? defaultValue;\n  }\n  const result: typeof rest & {\n    key: string;\n    default?: OptionConfigToType<T> | string | undefined;\n    resolvedEnvKey?: string;\n    alias?: string[];\n  } = { ...rest, key };\n  // Strip aliases flagged as hidden (either explicitly via `{ hidden: true }`\n  // or auto-generated by the parser) from generated documentation.\n  const hiddenAliases = (option as { hiddenAliases?: string[] }).hiddenAliases;\n  if (hiddenAliases?.length && Array.isArray(result.alias)) {\n    const filtered = result.alias.filter(\n      (alias): alias is string =>\n        typeof alias === 'string' && !hiddenAliases.includes(alias)\n    );\n    if (filtered.length > 0) {\n      result.alias = filtered;\n    } else {\n      delete result.alias;\n    }\n  }\n  if (resolvedDefault !== undefined) {\n    result.default = resolvedDefault;\n  }\n  if (envInfo) {\n    const resolvedEnvKey = resolveEnvKeyForOption(option, key, envInfo);\n    if (resolvedEnvKey !== undefined) {\n      result.resolvedEnvKey = resolvedEnvKey;\n    }\n  }\n  return result;\n}\n\ntype NormalizedOptionConfig<\n  T extends UnknownOptionConfig = UnknownOptionConfig\n> = ReturnType<typeof normalizeOptionConfigForDocumentation<T>>;\n\nexport function generateDocumentation(\n  cli: InternalCLI,\n  commandChain: string[] = []\n) {\n  // Ensure current command's options are built.\n  if (cli.configuration?.builder) {\n    // The cli instance here is typed a bit too well\n    // for the builder function, so we need to cast it to\n    // a more generic form.\n    cli.configuration.builder(cli as unknown as CLI);\n  }\n  const parser = cli.getParser();\n\n  const groupedOptions = cli.getGroupedOptions();\n  const envInfo = parser.getEnvInfo();\n  const options: Record<string, NormalizedOptionConfig> = Object.fromEntries(\n    Object.entries(parser.configuredOptions)\n      .filter(([, c]) => !c.hidden)\n      .map(([k, v]) => [k, normalizeOptionConfigForDocumentation(v, k, envInfo)])\n  );\n  const positionals = parser.configuredPositionals;\n  for (const positional of positionals) {\n    delete options[positional.key];\n  }\n  const subcommands: Documentation[] = [];\n  for (const subcommand of Object.values(cli.getSubcommands())) {\n    if (subcommand.configuration?.hidden !== true) {\n      const clone = subcommand.clone();\n      if (clone.configuration) {\n        clone.configuration.epilogue ??= cli.configuration?.epilogue;\n      }\n      subcommands.push(\n        generateDocumentation(clone, [...commandChain, cli.name])\n      );\n    }\n  }\n\n  Object.values(cli.getSubcommands()).map((cmd) =>\n    generateDocumentation(cmd.clone(), [...commandChain, cli.name])\n  );\n\n  // Get the localization dictionary if configured\n  const dictionary = parser.getLocalizationDictionary();\n  let localizedKeys: LocalizationDictionary | undefined;\n  \n  if (dictionary) {\n    // Filter to only include keys that are actually used in this CLI\n    const usedKeys: LocalizationDictionary = {};\n    let hasUsedKeys = false;\n    \n    for (const key in parser.configuredOptions) {\n      if (dictionary[key]) {\n        usedKeys[key] = dictionary[key];\n        hasUsedKeys = true;\n      }\n    }\n    \n    // Also include command names - track unique commands by instance to avoid duplicates\n    const seenCommands = new Set<AnyInternalCLI>();\n    for (const cmdKey in cli.getSubcommands()) {\n      const cmdInstance = cli.getSubcommands()[cmdKey];\n      if (!seenCommands.has(cmdInstance)) {\n        seenCommands.add(cmdInstance);\n        const defaultName = cmdInstance.name;\n        if (dictionary[defaultName]) {\n          usedKeys[defaultName] = dictionary[defaultName];\n          hasUsedKeys = true;\n        }\n      }\n    }\n    \n    if (hasUsedKeys) {\n      localizedKeys = usedKeys;\n    }\n  }\n\n  const result: Documentation = {\n    name: cli.name,\n    description: cli.configuration?.description,\n    usage: cli.configuration?.usage\n      ? commandChain.length\n        ? [...commandChain, cli.configuration.usage].join(' ')\n        : cli.configuration?.usage\n      : [\n          ...commandChain,\n          cli.name,\n          ...positionals.map((p) => (p.required ? `<${p.key}>` : `[${p.key}]`)),\n        ].join(' '),\n    epilogue: cli.configuration?.epilogue,\n    examples: cli.configuration?.examples ?? [],\n    groupedOptions,\n    options,\n    positionals,\n    subcommands,\n  };\n\n  const configDocs = parser.getConfigurationDocs();\n  if (configDocs.length > 0) {\n    result.configurationSources = configDocs;\n  }\n\n  if (localizedKeys) {\n    result.localizedKeys = localizedKeys;\n  }\n\n  return result;\n}\n"],"mappings":";;;;AAoCA,SAAS,uBACP,QACA,WACA,SACoB;CACpB,MAAM,EAAE,QAAQ;AAEhB,KAAI,QAAQ,MAAO,QAAO,KAAA;AAC1B,KAAI,QAAQ,KAAA,KAAa,CAAC,QAAQ,QAAS,QAAO,KAAA;AAElD,KAAI,QAAQ,KAAA,KAAa,QAAQ,KAC/B,SAAA,GAAA,kBAAA,WAAiB,QAAQ,QAAQ,UAAU;AAE7C,KAAI,OAAO,QAAQ,SACjB,SAAA,GAAA,kBAAA,WAAiB,QAAQ,QAAQ,IAAI;AAGvC,KAAI,IAAI,aAAa,MAAO,QAAO,KAAA;CACnC,MAAM,SAAS,IAAI,OAAO;AAE1B,SAAA,GAAA,kBAAA,WADe,IAAI,WAAW,QAAQ,KAAA,IAAY,QAAQ,QACjC,OAAO;;AAGlC,SAAS,sCACP,QACA,KACA,SACA;CACA,MAAM,EAAE,SAAS,iBAAiB,GAAG,SAAS;CAC9C,IAAI;AACJ,KAAI,oBAAoB,KAAA,GAAW;EACjC,MAAM,CAAC,cAAc,gBAAA,GAAA,kBAAA,kBAAgC,OAAO;AAC5D,oBAAkB,eAAe;;CAEnC,MAAM,SAKF;EAAE,GAAG;EAAM;EAAK;CAGpB,MAAM,gBAAiB,OAAwC;AAC/D,KAAI,eAAe,UAAU,MAAM,QAAQ,OAAO,MAAM,EAAE;EACxD,MAAM,WAAW,OAAO,MAAM,QAC3B,UACC,OAAO,UAAU,YAAY,CAAC,cAAc,SAAS,MAAM,CAC9D;AACD,MAAI,SAAS,SAAS,EACpB,QAAO,QAAQ;MAEf,QAAO,OAAO;;AAGlB,KAAI,oBAAoB,KAAA,EACtB,QAAO,UAAU;AAEnB,KAAI,SAAS;EACX,MAAM,iBAAiB,uBAAuB,QAAQ,KAAK,QAAQ;AACnE,MAAI,mBAAmB,KAAA,EACrB,QAAO,iBAAiB;;AAG5B,QAAO;;AAOT,SAAgB,sBACd,KACA,eAAyB,EAAE,EAC3B;AAEA,KAAI,IAAI,eAAe,QAIrB,KAAI,cAAc,QAAQ,IAAsB;CAElD,MAAM,SAAS,IAAI,WAAW;CAE9B,MAAM,iBAAiB,IAAI,mBAAmB;CAC9C,MAAM,UAAU,OAAO,YAAY;CACnC,MAAM,UAAkD,OAAO,YAC7D,OAAO,QAAQ,OAAO,kBAAkB,CACrC,QAAQ,GAAG,OAAO,CAAC,EAAE,OAAO,CAC5B,KAAK,CAAC,GAAG,OAAO,CAAC,GAAG,sCAAsC,GAAG,GAAG,QAAQ,CAAC,CAAC,CAC9E;CACD,MAAM,cAAc,OAAO;AAC3B,MAAK,MAAM,cAAc,YACvB,QAAO,QAAQ,WAAW;CAE5B,MAAM,cAA+B,EAAE;AACvC,MAAK,MAAM,cAAc,OAAO,OAAO,IAAI,gBAAgB,CAAC,CAC1D,KAAI,WAAW,eAAe,WAAW,MAAM;EAC7C,MAAM,QAAQ,WAAW,OAAO;AAChC,MAAI,MAAM,cACR,OAAM,cAAc,aAAa,IAAI,eAAe;AAEtD,cAAY,KACV,sBAAsB,OAAO,CAAC,GAAG,cAAc,IAAI,KAAK,CAAC,CAC1D;;AAIL,QAAO,OAAO,IAAI,gBAAgB,CAAC,CAAC,KAAK,QACvC,sBAAsB,IAAI,OAAO,EAAE,CAAC,GAAG,cAAc,IAAI,KAAK,CAAC,CAChE;CAGD,MAAM,aAAa,OAAO,2BAA2B;CACrD,IAAI;AAEJ,KAAI,YAAY;EAEd,MAAM,WAAmC,EAAE;EAC3C,IAAI,cAAc;AAElB,OAAK,MAAM,OAAO,OAAO,kBACvB,KAAI,WAAW,MAAM;AACnB,YAAS,OAAO,WAAW;AAC3B,iBAAc;;EAKlB,MAAM,+BAAe,IAAI,KAAqB;AAC9C,OAAK,MAAM,UAAU,IAAI,gBAAgB,EAAE;GACzC,MAAM,cAAc,IAAI,gBAAgB,CAAC;AACzC,OAAI,CAAC,aAAa,IAAI,YAAY,EAAE;AAClC,iBAAa,IAAI,YAAY;IAC7B,MAAM,cAAc,YAAY;AAChC,QAAI,WAAW,cAAc;AAC3B,cAAS,eAAe,WAAW;AACnC,mBAAc;;;;AAKpB,MAAI,YACF,iBAAgB;;CAIpB,MAAM,SAAwB;EAC5B,MAAM,IAAI;EACV,aAAa,IAAI,eAAe;EAChC,OAAO,IAAI,eAAe,QACtB,aAAa,SACX,CAAC,GAAG,cAAc,IAAI,cAAc,MAAM,CAAC,KAAK,IAAI,GACpD,IAAI,eAAe,QACrB;GACE,GAAG;GACH,IAAI;GACJ,GAAG,YAAY,KAAK,MAAO,EAAE,WAAW,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,GAAI;GACtE,CAAC,KAAK,IAAI;EACf,UAAU,IAAI,eAAe;EAC7B,UAAU,IAAI,eAAe,YAAY,EAAE;EAC3C;EACA;EACA;EACA;EACD;CAED,MAAM,aAAa,OAAO,sBAAsB;AAChD,KAAI,WAAW,SAAS,EACtB,QAAO,uBAAuB;AAGhC,KAAI,cACF,QAAO,gBAAgB;AAGzB,QAAO"}