"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/core/config/index.ts
var index_exports = {};
__export(index_exports, {
  Command: () => Command,
  Help: () => Help,
  args: () => args,
  cmd: () => cmd,
  configPath: () => configPath,
  defined: () => defined,
  option: () => option,
  resolveConfig: () => resolveConfig,
  scope: () => scope,
  strictScope: () => strictScope,
  toArray: () => toArray,
  toggleable: () => toggleable,
  valuable: () => valuable,
  withConfigUtils: () => withConfigUtils
});
module.exports = __toCommonJS(index_exports);
var import_promises = require("node:fs/promises");
var import_node_path = require("node:path");
var import_commander = require("commander");
var import_lodash = require("lodash");
var import_chalk = require("chalk");
var import_js_yaml = require("js-yaml");
var import_ts_dedent = require("ts-dedent");
function toArray(value, previous) {
  value = [].concat(value);
  if (previous) {
    previous = [].concat(previous);
    return [.../* @__PURE__ */ new Set([...previous, ...value])];
  }
  return value;
}
function cmd(command) {
  const cmdName = command.name();
  let ancestorCmdNames = "";
  for (let ancestorCmd = command.parent; ancestorCmd; ancestorCmd = ancestorCmd.parent) {
    ancestorCmdNames = ancestorCmd.name() + " " + ancestorCmdNames;
  }
  return ancestorCmdNames + cmdName;
}
function args(command) {
  let args2;
  while (command) {
    args2 = command.rawArgs || args2;
    command = command.parent;
  }
  return args2 || [];
}
var deprecatedArg = (reason) => (0, import_chalk.yellow)("\nDEPRECATED:\n" + reason);
var scope = (scopeName) => (config) => {
  const path = scopeName.split(".");
  let current = config;
  for (const part of path) {
    if (current && typeof current === "object" && part in current) {
      current = current[part];
    }
  }
  return current || config;
};
var strictScope = (scopeName) => (config) => {
  const path = scopeName.split(".");
  let current = config;
  for (const part of path) {
    if (current && typeof current === "object" && part in current) {
      current = current[part];
    } else {
      const error = new TypeError(`Scope ${scopeName} doesn't exist in config`);
      error.code = "ScopeException";
      throw error;
    }
  }
  return current;
};
var defined = (option2, ...scopes) => {
  for (const scope2 of scopes) {
    if (option2 in scope2) {
      return scope2[option2];
    }
  }
  return null;
};
var valuable = (...values) => values.some((value) => value !== null && value !== void 0);
var toggleable = (field, args2, config) => {
  const result = (0, import_lodash.isObject)(config[field]) ? { ...config[field] } : { enabled: false };
  result.enabled = // eslint-disable-next-line no-nested-ternary
  field in args2 ? Boolean(args2[field]) : (0, import_lodash.isObject)(config[field]) ? defined("enabled", config[field], { enabled: true }) : defined(field, config, { [field]: false });
  return result;
};
var OptionSource = /* @__PURE__ */ Symbol("OptionSource");
function option(o) {
  if (o.deprecated) {
    o.desc += deprecatedArg(o.deprecated);
  }
  const result = new import_commander.Option(o.flags, o.desc);
  result[OptionSource] = o;
  if ("default" in o) {
    result.default(o.default);
  }
  if ("defaultInfo" in o) {
    result.defaultInfo = o.defaultInfo;
  }
  if (o.choices) {
    result.choices(o.choices);
  }
  if (o.parser) {
    result.argParser(o.parser);
  }
  if (o.env) {
    result.env(o.env);
  }
  if ("required" in o) {
    result.makeOptionMandatory(true);
  }
  if ("hidden" in o) {
    result.hideHelp(o.hidden);
  }
  return result;
}
var configPath = /* @__PURE__ */ Symbol("configPath");
function withConfigUtils(path, config) {
  return Object.setPrototypeOf(
    { ...config },
    {
      resolve: (subpath) => {
        if (path === null) {
          return (0, import_node_path.resolve)(subpath);
        }
        return (0, import_node_path.resolve)((0, import_node_path.dirname)(path), subpath);
      },
      [configPath]: path === null ? path : (0, import_node_path.resolve)(path)
    }
  );
}
async function resolveConfig(path, {
  defaults,
  fallback,
  filter = import_lodash.identity
} = {}) {
  try {
    const content = await (0, import_promises.readFile)(path, "utf8") || "{}";
    const data = (0, import_js_yaml.load)(content);
    return withConfigUtils(path, (0, import_lodash.merge)({}, defaults, filter(data)));
  } catch (error) {
    switch (error.code) {
      case "YAMLException":
        throw new Error(`Failed to parse ${path}: ${error.message}`);
      case "ScopeException":
      case "ENOENT":
        if (fallback) {
          return withConfigUtils(null, fallback);
        } else {
          throw error;
        }
      default:
        throw error;
    }
  }
}
var Help = class extends import_commander.Help {
  constructor() {
    super(...arguments);
    this.showGlobalOptions = true;
  }
  visibleOptions(command) {
    const options = super.visibleOptions(command);
    const flags = /* @__PURE__ */ new Set(["-h, --help", "--version"]);
    return options.filter((option2) => !flags.has(option2.flags));
  }
  visibleGlobalOptions(command) {
    const options = this.visibleOptions(command);
    const helpOption = command.createOption(command._helpLongFlag, command._helpDescription);
    const globalOptions = super.visibleGlobalOptions(command);
    const flags = options.reduce((acc, option2) => {
      acc.add(option2.flags);
      return acc;
    }, /* @__PURE__ */ new Set());
    const filtered = globalOptions.filter((option2) => !flags.has(option2.flags)).sort((_, b) => b.flags === "--version" ? -1 : 0);
    return filtered.concat(helpOption);
  }
  commandUsage(command) {
    const usage = super.commandUsage(command);
    return (0, import_ts_dedent.dedent)(usage.replace(/{{PROGRAM}}/g, cmd(command)));
  }
  commandDescription(command) {
    const desc = super.commandDescription(command);
    return (0, import_ts_dedent.dedent)(desc.replace(/{{PROGRAM}}/g, cmd(command)));
  }
  optionDescription(option2) {
    const extraInfo = [];
    if (option2.argChoices) {
      extraInfo.push(
        `(choices: ${option2.argChoices.map((choice) => JSON.stringify(choice)).join(", ")})`
      );
    }
    if ((option2.defaultValue !== void 0 || option2.defaultInfo !== void 0) && !option2.isBoolean()) {
      const value = option2.defaultValueDescription || JSON.stringify(option2.defaultValue || option2.defaultInfo);
      extraInfo.push(`(default: ${value})`);
    }
    if (extraInfo.length > 0) {
      return (0, import_ts_dedent.dedent)(option2.description) + `

${(0, import_chalk.cyan)(extraInfo.join(" "))}


`;
    }
    return (0, import_ts_dedent.dedent)(option2.description) + "\n\n\n";
  }
  // Ugly method - copypasted from commander source
  wrap(str, width, indent, minColumnWidth = 40) {
    const columnWidth = width - indent;
    if (columnWidth < minColumnWidth) {
      return str;
    }
    const leadingStr = str.slice(0, indent);
    const columnText = str.slice(indent).replace("\r\n", "\n");
    const indentString = " ".repeat(indent);
    const zeroWidthSpace = "\u200B";
    const breaks = `\\s${zeroWidthSpace}`;
    const regex = new RegExp(
      `
|.{1,${columnWidth - 1}}([${breaks}]|$)|[^${breaks}]+?([${breaks}]|$)`,
      "g"
    );
    const lines = columnText.match(regex) || [];
    return leadingStr + lines.map((line, i) => {
      if (line === "\n") {
        return "";
      }
      return (i > 0 ? indentString : "") + line.trimEnd();
    }).join("\n");
  }
};
var Command = class extends import_commander.Command {
  constructor() {
    super(...arguments);
    this.parent = null;
    this._helpLongFlag = "--help";
    this._helpShortFlag = "-h";
    this._helpDescription = "Display help for command";
    this._helpCommandDescription = "Display help for command";
  }
  missingMandatoryOptionValue(option2) {
    const rawArgs = args(this);
    if (rawArgs.includes(this._helpLongFlag) || rawArgs.includes(this._helpShortFlag)) {
      return;
    }
    super.missingMandatoryOptionValue(option2);
  }
  error(error) {
    throw error;
  }
  addOption(o) {
    super.addOption(o);
    const camelcase = camelCaseOption(o);
    if (camelcase) {
      super.addOption(camelcase);
    }
    if (o.isBoolean()) {
      super.addOption(negatedOption(o));
    }
    if (o.description) {
      o.description = o.description.replace(/{{PROGRAM}}/g, cmd(this));
    }
    return this;
  }
  createHelp() {
    return new Help();
  }
};
function camelCaseOption(o) {
  const original = o[OptionSource];
  const flags = original.flags.replace(/(^|\s+|,)-\w+\s*($|,?\s*)/g, "").replace(/([^-])-([a-z])/g, (_, $1, $2) => $1 + $2.toUpperCase());
  if (original.flags.includes(flags)) {
    return null;
  }
  const camelcase = {
    ...original,
    flags,
    desc: "auto camelcase",
    deprecated: 'Use "kebab case" variant of this option.',
    hidden: true
  };
  delete camelcase.default;
  delete camelcase.defaultInfo;
  return option(camelcase);
}
function negatedOption(o) {
  const original = o[OptionSource];
  const flags = original.flags.replace(/(^|\s+|,)-\w+\s*($|,?\s*)/g, "").replace(/--/g, "--no-");
  const negated = {
    ...original,
    flags,
    desc: "auto negation",
    hidden: true
  };
  delete negated.default;
  delete negated.defaultInfo;
  delete negated.deprecated;
  return option(negated);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  Command,
  Help,
  args,
  cmd,
  configPath,
  defined,
  option,
  resolveConfig,
  scope,
  strictScope,
  toArray,
  toggleable,
  valuable,
  withConfigUtils
});
//# sourceMappingURL=index.js.map
