// src/lib/packageManagerRuntime.ts
import { spawnSync } from "child_process";
import fs from "fs";
import chalk from "chalk";
var DISPLAY_NAMES = {
  bun: "Bun",
  npm: "npm",
  pnpm: "pnpm",
  yarn: "Yarn"
};
var MAC_INSTALL_COMMANDS = {
  bun: "brew install oven-sh/bun/bun",
  npm: "brew install node",
  pnpm: "brew install pnpm",
  yarn: "brew install yarn"
};
function currentPlatform() {
  if (process.platform === "darwin" || process.platform === "linux" || process.platform === "win32") {
    return process.platform;
  }
  return "unknown";
}
function askYesNo(question) {
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
    return false;
  }
  process.stdout.write(question);
  const buffer = Buffer.alloc(1024);
  const bytesRead = fs.readSync(process.stdin.fd, buffer, 0, buffer.length, null);
  const answer = buffer.toString("utf8", 0, bytesRead).trim().toLowerCase();
  return answer === "y" || answer === "yes";
}
function isCommandInstalled(command) {
  const result = spawnSync(command, ["--version"], {
    encoding: "utf8",
    shell: false,
    stdio: "ignore"
  });
  return !result.error && result.status === 0;
}
function isPackageManagerInstalled(pm) {
  return isCommandInstalled(pm);
}
function getPackageManagerInstallPlan(pm, platform = currentPlatform()) {
  const displayName = DISPLAY_NAMES[pm];
  if (platform === "darwin") {
    const command = MAC_INSTALL_COMMANDS[pm];
    return {
      command,
      manualInstructions: [
        `Install ${displayName} with: ${command}`
      ],
      packageManager: pm,
      platform,
      supported: true
    };
  }
  if (platform === "linux") {
    return {
      manualInstructions: [
        `Automatic installation for ${displayName} is not implemented on Linux yet.`,
        `Install ${displayName} manually and re-run the command.`
      ],
      packageManager: pm,
      platform,
      supported: false
    };
  }
  if (platform === "win32") {
    return {
      manualInstructions: [
        `Automatic installation for ${displayName} is not implemented on Windows yet.`,
        `Install ${displayName} manually and re-run the command.`
      ],
      packageManager: pm,
      platform,
      supported: false
    };
  }
  return {
    manualInstructions: [
      `Automatic installation for ${displayName} is not implemented on ${platform} yet.`,
      `Install ${displayName} manually and re-run the command.`
    ],
    packageManager: pm,
    platform,
    supported: false
  };
}
function printManualInstructions(plan, context) {
  console.error(chalk.yellow(`${DISPLAY_NAMES[plan.packageManager]} is required for "${context.operation}".`));
  for (const line of plan.manualInstructions) {
    console.error(chalk.gray(`  ${line}`));
  }
}
function installWithHomebrew(pm, cwd) {
  const command = MAC_INSTALL_COMMANDS[pm];
  const result = spawnSync("brew", command.replace("brew ", "").split(" "), {
    cwd,
    encoding: "utf8",
    shell: false,
    stdio: "inherit"
  });
  return result.status === 0;
}
function ensurePackageManagerInstalled(pm, context) {
  if (isPackageManagerInstalled(pm)) return true;
  const plan = getPackageManagerInstallPlan(pm, context.platform ?? currentPlatform());
  const displayName = DISPLAY_NAMES[pm];
  console.error(chalk.yellow(`${context.operation} requires ${displayName}, but it is not installed.`));
  if (!plan.supported) {
    printManualInstructions(plan, context);
    return false;
  }
  if (!isCommandInstalled("brew")) {
    console.error(chalk.yellow("Homebrew is not installed, so automatic installation is unavailable."));
    console.error(chalk.gray("  Install Homebrew from https://brew.sh and then run:"));
    console.error(chalk.gray(`  ${plan.command}`));
    return false;
  }
  const confirmed = askYesNo(chalk.cyan(`Install ${displayName} with Homebrew now? [y/N] `));
  if (!confirmed) {
    console.error(chalk.gray(`Skipping install. Run "${plan.command}" manually and then retry.`));
    return false;
  }
  console.error(chalk.cyan(`Installing ${displayName} via Homebrew...
`));
  if (!installWithHomebrew(pm, context.cwd)) {
    console.error(chalk.red(`Homebrew failed to install ${displayName}.`));
    console.error(chalk.gray(`Run "${plan.command}" manually and then retry.`));
    return false;
  }
  if (!isPackageManagerInstalled(pm)) {
    console.error(chalk.red(`${displayName} still does not appear to be installed after Homebrew completed.`));
    console.error(chalk.gray(`Run "${plan.command}" manually and then retry.`));
    return false;
  }
  console.error(chalk.green(`${displayName} installed successfully.`));
  return true;
}
function failureResult() {
  return {
    output: ["", ""],
    pid: 0,
    signal: null,
    status: 1,
    stderr: "",
    stdout: ""
  };
}
function spawnPackageManagerSync(pm, args, options) {
  if (!ensurePackageManagerInstalled(pm, options.context)) {
    return failureResult();
  }
  return spawnSync(pm, args, { encoding: "utf8", ...options });
}

// src/pm/workspaces.ts
import { existsSync, readFileSync } from "fs";
import PATH from "path";
import { globSync } from "glob";
function readJsonFile(path) {
  if (!existsSync(path)) return void 0;
  try {
    return JSON.parse(readFileSync(path, "utf8"));
  } catch {
    return void 0;
  }
}
function readRootPackageJson(cwd = process.cwd()) {
  return readJsonFile(PATH.resolve(cwd, "package.json"));
}
function detectPackageManagerFromPackageJson(cwd = process.cwd()) {
  const packageManager = readRootPackageJson(cwd)?.packageManager;
  if (!packageManager) return void 0;
  return packageManager.split("@")[0];
}

// src/pm/detectPackageManager.ts
import { existsSync as existsSync2 } from "fs";
var knownPackageManagers = /* @__PURE__ */ new Set(["bun", "npm", "pnpm", "yarn"]);
function detectPackageManager() {
  const packageManager = detectPackageManagerFromPackageJson();
  if (packageManager && knownPackageManagers.has(packageManager)) {
    return packageManager;
  }
  if (existsSync2("pnpm-lock.yaml") || existsSync2("pnpm-workspace.yaml")) return "pnpm";
  if (existsSync2("bun.lock") || existsSync2("bun.lockb")) return "bun";
  if (existsSync2("yarn.lock") || existsSync2(".yarnrc.yml")) return "yarn";
  if (existsSync2("package-lock.json") || existsSync2("npm-shrinkwrap.json")) return "npm";
  return "yarn";
}

// src/pm/registry.ts
var implementations = /* @__PURE__ */ new Map();
function getPackageManager(name) {
  const pmName = name ?? detectPackageManager();
  const pm = implementations.get(pmName);
  if (!pm) {
    throw new Error(
      `No package manager implementation registered for "${pmName}". Ensure registerPackageManager() has been called before getPackageManager().`
    );
  }
  return pm;
}

// src/lib/initCwd.ts
function INIT_CWD() {
  return process.env.INIT_CWD ?? process.cwd();
}

// src/lib/latestVersions.ts
var latestVersions = {
  node: "24.14.1",
  nodeLtsCodename: "Krypton",
  npm: "11.11.0",
  pnpm: "10.33.0",
  yarn: "4.13.0"
};

// src/lib/runInstall.ts
import chalk2 from "chalk";
function runInstall(cwd) {
  const pm = detectPackageManager();
  console.log(chalk2.gray(`Running ${pm} install...`));
  const result = spawnPackageManagerSync(pm, ["install"], {
    context: { cwd, operation: `Run ${pm} install` },
    cwd,
    encoding: "utf8",
    stdio: "inherit"
  });
  if (result.status !== 0) {
    console.warn(chalk2.yellow(`${pm} install failed`));
    return false;
  }
  console.log(chalk2.green("Dependencies installed"));
  return true;
}

// src/actions/package-lint-deps.ts
import { readFileSync as readFileSync2, writeFileSync } from "fs";
import PATH2 from "path";
import chalk3 from "chalk";
import semver from "semver";
function readWorkspacePackageJson(cwd, location) {
  const pkgPath = PATH2.resolve(cwd, location, "package.json");
  try {
    return JSON.parse(readFileSync2(pkgPath, "utf8"));
  } catch {
    return void 0;
  }
}
function writeWorkspacePackageJson(cwd, location, pkg) {
  const pkgPath = PATH2.resolve(cwd, location, "package.json");
  writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
`, "utf8");
}
function buildWorkspaceVersionMap(cwd, workspaces) {
  const map = /* @__PURE__ */ new Map();
  for (const { location, name } of workspaces) {
    if (location === ".") continue;
    const pkg = readWorkspacePackageJson(cwd, location);
    if (!pkg) continue;
    const version = pkg.version;
    if (version) map.set(name, version);
  }
  return map;
}
function expectedPeerRange(devDepVersion, targetVersion) {
  const parsed = semver.parse(targetVersion);
  if (!parsed) return `~${targetVersion}`;
  if (devDepVersion === "workspace:^") {
    return `^${parsed.major}`;
  }
  return `~${parsed.major}.${parsed.minor}`;
}
function checkVersionConsistency(cwd, rootPkg, workspaces) {
  const result = {
    errors: [],
    fixable: [],
    warnings: []
  };
  if (rootPkg.version !== void 0) {
    result.fixable.push('Root package.json should not have a "version" field in a monorepo');
  }
  const versions = /* @__PURE__ */ new Map();
  for (const { location, name } of workspaces) {
    if (location === ".") continue;
    const pkg = readWorkspacePackageJson(cwd, location);
    if (!pkg) continue;
    const version = pkg.version;
    if (version) {
      versions.set(name, version);
    } else {
      result.errors.push(`${name} (${location}) is missing a "version" field`);
    }
  }
  const uniqueVersions = new Set(versions.values());
  if (uniqueVersions.size > 1) {
    const versionList = [...uniqueVersions].toSorted(semver.rcompare);
    for (const [name, version] of versions) {
      if (version !== versionList[0]) {
        result.fixable.push(`${name} has version ${version} (expected ${versionList[0]})`);
      }
    }
  }
  return result;
}
function fixVersionConsistency(cwd, rootPkg, writeRootPackageJson2, workspaces) {
  if (rootPkg.version !== void 0) {
    delete rootPkg.version;
    writeRootPackageJson2(cwd, rootPkg);
    console.log(chalk3.green('  \u2714 Fixed: removed "version" from root package.json'));
  }
  const versions = [];
  for (const { location } of workspaces) {
    if (location === ".") continue;
    const pkg = readWorkspacePackageJson(cwd, location);
    if (!pkg) continue;
    const version = pkg.version;
    if (version && semver.valid(version)) {
      versions.push(version);
    }
  }
  if (versions.length === 0) return;
  const highest = versions.toSorted(semver.rcompare)[0];
  for (const { location, name } of workspaces) {
    if (location === ".") continue;
    const pkg = readWorkspacePackageJson(cwd, location);
    if (!pkg) continue;
    if (pkg.version !== highest) {
      pkg.version = highest;
      writeWorkspacePackageJson(cwd, location, pkg);
      console.log(chalk3.green(`  \u2714 Fixed: set version to ${highest} in ${name} (${location})`));
    }
  }
}
function expectedDepVersion(targetVersion) {
  const parsed = semver.parse(targetVersion);
  if (!parsed) return `~${targetVersion}`;
  return `~${targetVersion}`;
}
function checkInternalDepVersions(cwd, workspaces) {
  const result = {
    errors: [],
    fixable: [],
    warnings: []
  };
  const workspaceVersions = buildWorkspaceVersionMap(cwd, workspaces);
  for (const { location, name } of workspaces) {
    const pkg = readWorkspacePackageJson(cwd, location);
    if (!pkg) continue;
    for (const depField of ["dependencies", "devDependencies"]) {
      const deps = pkg[depField];
      if (!deps) continue;
      for (const [dep, version] of Object.entries(deps)) {
        const targetVersion = workspaceVersions.get(dep);
        if (!targetVersion) continue;
        const expected = expectedDepVersion(targetVersion);
        if (version.startsWith("workspace:")) {
          result.fixable.push(
            `${name} (${location}) ${depField}.${dep} is "${version}" \u2014 should be "${expected}" (not workspace: protocol)`
          );
        } else if (version !== expected) {
          result.fixable.push(
            `${name} (${location}) ${depField}.${dep} is "${version}" \u2014 should be "${expected}"`
          );
        }
      }
    }
  }
  return result;
}
function fixInternalDepVersions(cwd, workspaces) {
  const workspaceVersions = buildWorkspaceVersionMap(cwd, workspaces);
  for (const { location, name } of workspaces) {
    const pkg = readWorkspacePackageJson(cwd, location);
    if (!pkg) continue;
    let modified = false;
    for (const depField of ["dependencies", "devDependencies"]) {
      const deps = pkg[depField];
      if (!deps) continue;
      for (const [dep, version] of Object.entries(deps)) {
        const targetVersion = workspaceVersions.get(dep);
        if (!targetVersion) continue;
        const expected = expectedDepVersion(targetVersion);
        if (version !== expected) {
          deps[dep] = expected;
          console.log(chalk3.green(`  \u2714 Fixed: set ${depField}.${dep} to "${expected}" in ${name} (${location})`));
          modified = true;
        }
      }
    }
    if (modified) {
      writeWorkspacePackageJson(cwd, location, pkg);
    }
  }
}
function checkWorkspaceProtocol(cwd, workspaces) {
  const result = {
    errors: [],
    fixable: [],
    warnings: []
  };
  const workspaceNames = new Set(workspaces.map((w) => w.name));
  for (const { location, name } of workspaces) {
    const pkg = readWorkspacePackageJson(cwd, location);
    if (!pkg) continue;
    for (const depField of ["dependencies", "devDependencies"]) {
      const deps = pkg[depField];
      if (!deps) continue;
      for (const [dep, version] of Object.entries(deps)) {
        if (!workspaceNames.has(dep)) continue;
        if (!version.startsWith("workspace:")) {
          result.fixable.push(
            `${name} (${location}) ${depField}.${dep} is "${version}" \u2014 should use workspace: protocol`
          );
        }
      }
    }
  }
  return result;
}
function fixWorkspaceProtocol(cwd, workspaces) {
  const workspaceNames = new Set(workspaces.map((w) => w.name));
  for (const { location, name } of workspaces) {
    const pkg = readWorkspacePackageJson(cwd, location);
    if (!pkg) continue;
    let modified = false;
    for (const depField of ["dependencies", "devDependencies"]) {
      const deps = pkg[depField];
      if (!deps) continue;
      for (const [dep, version] of Object.entries(deps)) {
        if (!workspaceNames.has(dep)) continue;
        if (!version.startsWith("workspace:")) {
          deps[dep] = "workspace:~";
          console.log(chalk3.green(`  \u2714 Fixed: set ${depField}.${dep} to "workspace:~" in ${name} (${location})`));
          modified = true;
        }
      }
    }
    if (modified) {
      writeWorkspacePackageJson(cwd, location, pkg);
    }
  }
}
function checkInternalPeerVersions(cwd, workspaces) {
  const result = {
    errors: [],
    fixable: [],
    warnings: []
  };
  const workspaceVersions = buildWorkspaceVersionMap(cwd, workspaces);
  for (const { location, name } of workspaces) {
    const pkg = readWorkspacePackageJson(cwd, location);
    if (!pkg) continue;
    const peerDeps = pkg.peerDependencies;
    if (!peerDeps) continue;
    const devDeps = pkg.devDependencies;
    for (const [dep, version] of Object.entries(peerDeps)) {
      const targetVersion = workspaceVersions.get(dep);
      if (!targetVersion) continue;
      if (version.startsWith("workspace:")) {
        const expected2 = expectedPeerRange(devDeps?.[dep], targetVersion);
        result.fixable.push(
          `${name} (${location}) peerDependencies.${dep} uses workspace: protocol \u2014 should be "${expected2}"`
        );
        continue;
      }
      const expected = expectedPeerRange(devDeps?.[dep], targetVersion);
      if (version !== expected && !semver.satisfies(targetVersion, version)) {
        result.fixable.push(
          `${name} (${location}) peerDependencies.${dep} is "${version}" \u2014 current version ${targetVersion} is not satisfied; expected "${expected}"`
        );
      }
    }
  }
  return result;
}
function fixInternalPeerVersions(cwd, workspaces) {
  const workspaceVersions = buildWorkspaceVersionMap(cwd, workspaces);
  for (const { location, name } of workspaces) {
    const pkg = readWorkspacePackageJson(cwd, location);
    if (!pkg) continue;
    const peerDeps = pkg.peerDependencies;
    if (!peerDeps) continue;
    const devDeps = pkg.devDependencies;
    let modified = false;
    for (const [dep, version] of Object.entries(peerDeps)) {
      const targetVersion = workspaceVersions.get(dep);
      if (!targetVersion) continue;
      const expected = expectedPeerRange(devDeps?.[dep], targetVersion);
      if (version !== expected) {
        peerDeps[dep] = expected;
        console.log(chalk3.green(`  \u2714 Fixed: set peerDependencies.${dep} to "${expected}" in ${name} (${location})`));
        modified = true;
      }
    }
    if (modified) {
      writeWorkspacePackageJson(cwd, location, pkg);
    }
  }
}

// src/actions/package-lint.ts
import {
  existsSync as existsSync3,
  readFileSync as readFileSync3,
  writeFileSync as writeFileSync2
} from "fs";
import PATH3 from "path";
import chalk4 from "chalk";
import picomatch from "picomatch";
import semver2 from "semver";
function emptyResult() {
  return {
    errors: [],
    fixable: [],
    warnings: []
  };
}
function readRootPackageJson2(cwd) {
  const raw = readFileSync3(PATH3.resolve(cwd, "package.json"), "utf8");
  return JSON.parse(raw);
}
function writeRootPackageJson(cwd, pkg) {
  const path = PATH3.resolve(cwd, "package.json");
  writeFileSync2(path, `${JSON.stringify(pkg, null, 2)}
`, "utf8");
}
function readPnpmWorkspaceGlobs(cwd) {
  const wsPath = PATH3.resolve(cwd, "pnpm-workspace.yaml");
  if (!existsSync3(wsPath)) return void 0;
  const raw = readFileSync3(wsPath, "utf8");
  const globs = [];
  let inPackages = false;
  for (const line of raw.split("\n")) {
    if (/^packages\s*:/.test(line)) {
      inPackages = true;
      continue;
    }
    if (inPackages) {
      const match = /^\s+-\s+['"]?([^'"]+)['"]?\s*$/.exec(line);
      if (match) {
        globs.push(match[1]);
      } else if (/^\S/.test(line) && line.trim() !== "") {
        break;
      }
    }
  }
  return globs.length > 0 ? globs : void 0;
}
function isMonorepo(pkg, cwd) {
  const workspaces = pkg.workspaces;
  if (Array.isArray(workspaces) && workspaces.length > 0) return true;
  return readPnpmWorkspaceGlobs(cwd) !== void 0;
}
function checkPackagesFolder(workspaces) {
  const result = emptyResult();
  for (const { location, name } of workspaces) {
    if (location === ".") continue;
    if (!location.startsWith("packages/") && !location.startsWith("packages\\")) {
      result.errors.push(`${name} (${location}) is not inside a packages/ folder`);
    }
  }
  return result;
}
function checkRootPrivate(pkg) {
  const result = emptyResult();
  if (!pkg.private) {
    result.fixable.push("Root package.json must be private to prevent accidental publishing");
  }
  return result;
}
function fixRootPrivate(cwd, pkg) {
  pkg.private = true;
  writeRootPackageJson(cwd, pkg);
  console.log(chalk4.green('  \u2714 Fixed: set "private": true in root package.json'));
}
function checkNoPublishConfigOnPrivate(pkg) {
  const result = emptyResult();
  if (pkg.private && pkg.publishConfig) {
    result.fixable.push("Root package.json has publishConfig but is private \u2014 publishConfig is unnecessary");
  }
  return result;
}
function fixNoPublishConfigOnPrivate(cwd, pkg) {
  delete pkg.publishConfig;
  writeRootPackageJson(cwd, pkg);
  console.log(chalk4.green("  \u2714 Fixed: removed publishConfig from private root package.json"));
}
function checkNoPackageManagerInWorkspaces(cwd, workspaces) {
  const result = emptyResult();
  for (const { location, name } of workspaces) {
    if (location === ".") continue;
    const pkgPath = PATH3.resolve(cwd, location, "package.json");
    try {
      const raw = readFileSync3(pkgPath, "utf8");
      const pkg = JSON.parse(raw);
      if (pkg.packageManager) {
        result.fixable.push(`${name} (${location}) has a packageManager field \u2014 only the root should define this`);
      }
    } catch {
    }
  }
  return result;
}
function fixNoPackageManagerInWorkspaces(cwd, _pkg, workspaces) {
  for (const { location } of workspaces) {
    if (location === ".") continue;
    const pkgPath = PATH3.resolve(cwd, location, "package.json");
    try {
      const raw = readFileSync3(pkgPath, "utf8");
      const pkg = JSON.parse(raw);
      if (pkg.packageManager) {
        delete pkg.packageManager;
        writeFileSync2(pkgPath, `${JSON.stringify(pkg, null, 2)}
`, "utf8");
        console.log(chalk4.green(`  \u2714 Fixed: removed packageManager from ${location}/package.json`));
      }
    } catch {
    }
  }
}
function checkWorkspacesFieldPlacement(cwd, pm, workspaces) {
  const result = emptyResult();
  for (const { location, name } of workspaces) {
    if (pm === "pnpm" ? true : location !== ".") {
      const pkgPath = PATH3.resolve(cwd, location, "package.json");
      try {
        const pkg = JSON.parse(readFileSync3(pkgPath, "utf8"));
        if (pkg.workspaces) {
          const label = location === "." ? "Root" : `${name} (${location})`;
          const reason = pm === "pnpm" ? "pnpm uses pnpm-workspace.yaml instead" : "only the root should define workspaces";
          result.fixable.push(`${label} has a workspaces field \u2014 ${reason}`);
        }
      } catch {
      }
    }
  }
  return result;
}
function fixWorkspacesFieldPlacement(cwd, pm, workspaces) {
  for (const { location } of workspaces) {
    if (pm === "pnpm" ? true : location !== ".") {
      const pkgPath = PATH3.resolve(cwd, location, "package.json");
      try {
        const pkg = JSON.parse(readFileSync3(pkgPath, "utf8"));
        if (pkg.workspaces) {
          delete pkg.workspaces;
          writeFileSync2(pkgPath, `${JSON.stringify(pkg, null, 2)}
`, "utf8");
          const label = location === "." ? "root" : location;
          console.log(chalk4.green(`  \u2714 Fixed: removed workspaces from ${label}/package.json`));
        }
      } catch {
      }
    }
  }
}
function checkWorkspaceGlobCoverage(pkg, cwd, pm, workspaces) {
  const result = emptyResult();
  const globs = pm === "pnpm" ? readPnpmWorkspaceGlobs(cwd) ?? [] : Array.isArray(pkg.workspaces) ? pkg.workspaces : [];
  if (globs.length === 0) {
    const source = pm === "pnpm" ? "pnpm-workspace.yaml" : "root package.json workspaces";
    result.errors.push(`No workspace globs found in ${source}`);
    return result;
  }
  const matchers = globs.map((glob) => picomatch(glob));
  const isMatch = (location) => matchers.some((m) => m(location));
  for (const { location, name } of workspaces) {
    if (location === ".") continue;
    if (!isMatch(location)) {
      const source = pm === "pnpm" ? "pnpm-workspace.yaml" : "root package.json workspaces";
      result.errors.push(`${name} (${location}) is not matched by any glob in ${source}`);
    }
  }
  return result;
}
function logResults(label, result, fix) {
  let errors = 0;
  let fixed = 0;
  for (const error of result.errors) {
    console.log(chalk4.red(`  \u2717 ${error}`));
    errors++;
  }
  for (const fixable of result.fixable) {
    if (fix) {
      fixed++;
    } else {
      console.log(chalk4.red(`  \u2717 ${fixable} (fixable)`));
      errors++;
    }
  }
  for (const warning of result.warnings) {
    console.log(chalk4.yellow(`  \u26A0 ${warning}`));
  }
  if (errors === 0 && fixed === 0 && result.warnings.length === 0) {
    console.log(chalk4.green(`  \u2713 ${label}`));
  }
  return { errors, fixed };
}
function runChecks(entries, cwd, pkg, fix) {
  let totalErrors = 0;
  let totalFixed = 0;
  for (const entry of entries) {
    const result = entry.check();
    const log = logResults(entry.label, result, fix);
    if (fix && entry.fix && result.fixable.length > 0) {
      entry.fix(cwd, pkg);
    }
    totalErrors += log.errors;
    totalFixed += log.fixed;
  }
  return { errors: totalErrors, fixed: totalFixed };
}
function checkVoltaOnlyInRoot(cwd, workspaces) {
  const result = emptyResult();
  for (const { location, name } of workspaces) {
    if (location === ".") continue;
    const pkgPath = PATH3.resolve(cwd, location, "package.json");
    try {
      const pkg = JSON.parse(readFileSync3(pkgPath, "utf8"));
      if (pkg.volta) {
        result.fixable.push(`${name} (${location}) has a volta field \u2014 only the root should define this`);
      }
    } catch {
    }
  }
  return result;
}
function fixVoltaOnlyInRoot(cwd, _pkg, workspaces) {
  for (const { location } of workspaces) {
    if (location === ".") continue;
    const pkgPath = PATH3.resolve(cwd, location, "package.json");
    try {
      const raw = readFileSync3(pkgPath, "utf8");
      const pkg = JSON.parse(raw);
      if (pkg.volta) {
        delete pkg.volta;
        writeFileSync2(pkgPath, `${JSON.stringify(pkg, null, 2)}
`, "utf8");
        console.log(chalk4.green(`  \u2714 Fixed: removed volta from ${location}/package.json`));
      }
    } catch {
    }
  }
}
function isTerminalPackage(pkg) {
  return pkg.private === true;
}
function checkEnginesOnlyInNonTerminal(cwd, workspaces) {
  const result = emptyResult();
  const rootPkg = JSON.parse(readFileSync3(PATH3.resolve(cwd, "package.json"), "utf8"));
  if (rootPkg.engines) {
    result.fixable.push("Root package.json has engines \u2014 terminal packages should not declare engines (use volta instead)");
  }
  for (const { location, name } of workspaces) {
    if (location === ".") continue;
    const pkgPath = PATH3.resolve(cwd, location, "package.json");
    try {
      const pkg = JSON.parse(readFileSync3(pkgPath, "utf8"));
      if (isTerminalPackage(pkg) && pkg.engines) {
        result.fixable.push(`${name} (${location}) is terminal (private) but has engines \u2014 terminal packages should not declare engines`);
      }
      if (!isTerminalPackage(pkg) && !pkg.engines) {
        result.fixable.push(`${name} (${location}) is a library but has no engines field`);
      }
    } catch {
    }
  }
  return result;
}
function fixEnginesOnlyInNonTerminal(cwd, _pkg, workspaces) {
  const rootPath = PATH3.resolve(cwd, "package.json");
  const rootRaw = readFileSync3(rootPath, "utf8");
  const rootPkg = JSON.parse(rootRaw);
  if (rootPkg.engines) {
    delete rootPkg.engines;
    writeFileSync2(rootPath, `${JSON.stringify(rootPkg, null, 2)}
`, "utf8");
    console.log(chalk4.green("  \u2714 Fixed: removed engines from root package.json"));
  }
  const enginesTemplate = resolveEnginesTemplate(cwd, workspaces);
  for (const { location } of workspaces) {
    if (location === ".") continue;
    const pkgPath = PATH3.resolve(cwd, location, "package.json");
    try {
      const raw = readFileSync3(pkgPath, "utf8");
      const pkg = JSON.parse(raw);
      if (isTerminalPackage(pkg) && pkg.engines) {
        delete pkg.engines;
        writeFileSync2(pkgPath, `${JSON.stringify(pkg, null, 2)}
`, "utf8");
        console.log(chalk4.green(`  \u2714 Fixed: removed engines from ${location}/package.json`));
      }
      if (!isTerminalPackage(pkg) && !pkg.engines && enginesTemplate) {
        pkg.engines = enginesTemplate;
        writeFileSync2(pkgPath, `${JSON.stringify(pkg, null, 2)}
`, "utf8");
        console.log(chalk4.green(`  \u2714 Fixed: added engines to ${location}/package.json`));
      }
    } catch {
    }
  }
}
function resolveEnginesTemplate(cwd, workspaces) {
  for (const { location } of workspaces) {
    if (location === ".") continue;
    try {
      const pkg = JSON.parse(readFileSync3(PATH3.resolve(cwd, location, "package.json"), "utf8"));
      if (!isTerminalPackage(pkg) && pkg.engines) {
        return pkg.engines;
      }
    } catch {
    }
  }
  return void 0;
}
function checkVersionsIncludeLts(cwd, workspaces) {
  const result = emptyResult();
  const toolVersions = {
    node: latestVersions.node,
    npm: latestVersions.npm,
    pnpm: latestVersions.pnpm,
    yarn: latestVersions.yarn
  };
  for (const { location, name } of workspaces) {
    const pkgPath = location === "." ? PATH3.resolve(cwd, "package.json") : PATH3.resolve(cwd, location, "package.json");
    try {
      const pkg = JSON.parse(readFileSync3(pkgPath, "utf8"));
      const label = location === "." ? "root" : `${name} (${location})`;
      const engines = pkg.engines;
      if (engines) {
        for (const [tool, range] of Object.entries(engines)) {
          const latest = toolVersions[tool];
          if (latest && !semver2.satisfies(latest, range)) {
            result.errors.push(
              `${label} engines.${tool} "${range}" does not include latest ${tool === "node" ? "LTS " : ""}version ${latest}`
            );
          }
        }
      }
      const volta = pkg.volta;
      if (volta) {
        for (const [tool, pinnedVersion] of Object.entries(volta)) {
          const latest = toolVersions[tool];
          if (latest && semver2.lt(pinnedVersion, latest)) {
            result.warnings.push(
              `${label} volta.${tool} "${pinnedVersion}" is older than latest ${tool === "node" ? "LTS " : ""}version ${latest}`
            );
          }
        }
      }
    } catch {
    }
  }
  return result;
}
function logSummary(errors, fixed) {
  if (fixed > 0) {
    console.log(chalk4.green(`
  Fixed ${fixed} issue(s)`));
  }
  if (errors > 0) {
    console.log(chalk4.red(`
  ${errors} error(s) found`));
  } else if (fixed === 0) {
    console.log(chalk4.green("\n  All checks passed"));
  }
}
function packageLintMonorepo(fix = false) {
  const cwd = INIT_CWD();
  let pkg;
  try {
    pkg = readRootPackageJson2(cwd);
  } catch {
    console.error(chalk4.red("Could not read package.json"));
    return 1;
  }
  if (!isMonorepo(pkg, cwd)) {
    console.log(chalk4.gray("Not a monorepo \u2014 skipping repo lint checks"));
    return 0;
  }
  console.log(chalk4.green("Repo Lint"));
  const pm = detectPackageManager();
  const workspaces = getPackageManager().listWorkspaces();
  const internalDepCheck = pm === "pnpm" ? {
    check: () => checkWorkspaceProtocol(cwd, workspaces),
    fix: () => fixWorkspaceProtocol(cwd, workspaces),
    label: "Internal deps/devDeps use workspace: protocol"
  } : {
    check: () => checkInternalDepVersions(cwd, workspaces),
    fix: () => fixInternalDepVersions(cwd, workspaces),
    label: "Internal deps/devDeps use correct version ranges"
  };
  const checks = [
    {
      check: () => checkRootPrivate(pkg),
      fix: fixRootPrivate,
      label: "Root package is private"
    },
    {
      check: () => checkNoPublishConfigOnPrivate(pkg),
      fix: fixNoPublishConfigOnPrivate,
      label: "No publishConfig on private root"
    },
    { check: () => checkPackagesFolder(workspaces), label: "All packages are in packages/ folder" },
    {
      check: () => checkWorkspacesFieldPlacement(cwd, pm, workspaces),
      fix: () => fixWorkspacesFieldPlacement(cwd, pm, workspaces),
      label: pm === "pnpm" ? "No workspaces field in package.json (use pnpm-workspace.yaml)" : "Workspaces field only in root package.json"
    },
    {
      check: () => checkWorkspaceGlobCoverage(pkg, cwd, pm, workspaces),
      label: "Workspace globs cover all packages"
    },
    {
      check: () => checkNoPackageManagerInWorkspaces(cwd, workspaces),
      fix: () => fixNoPackageManagerInWorkspaces(cwd, pkg, workspaces),
      label: "No packageManager in workspace packages"
    },
    {
      check: () => checkVoltaOnlyInRoot(cwd, workspaces),
      fix: () => fixVoltaOnlyInRoot(cwd, pkg, workspaces),
      label: "Volta only in root package.json"
    },
    {
      check: () => checkEnginesOnlyInNonTerminal(cwd, workspaces),
      fix: () => fixEnginesOnlyInNonTerminal(cwd, pkg, workspaces),
      label: "Engines only in non-terminal (library) packages"
    },
    {
      check: () => checkVersionsIncludeLts(cwd, workspaces),
      label: "Engine/volta versions include latest LTS"
    },
    {
      check: () => checkVersionConsistency(cwd, pkg, workspaces),
      fix: () => fixVersionConsistency(cwd, pkg, writeRootPackageJson, workspaces),
      label: "Consistent versions across packages"
    },
    internalDepCheck,
    {
      check: () => checkInternalPeerVersions(cwd, workspaces),
      fix: () => fixInternalPeerVersions(cwd, workspaces),
      label: "Internal peerDeps use semver ranges (not workspace: protocol)"
    }
  ];
  const { errors, fixed } = runChecks(checks, cwd, pkg, fix);
  logSummary(errors, fixed);
  if (fix && fixed > 0) runInstall();
  return errors > 0 ? 1 : 0;
}

// src/xy/common/repo/lintCommand.ts
var lintCommand = {
  command: "lint",
  describe: "Check monorepo package structure",
  builder: (yargs) => {
    return yargs.option("fix", {
      default: false,
      description: "Auto-fix fixable issues",
      type: "boolean"
    });
  },
  handler: (argv) => {
    if (argv.verbose) console.log("Repo Lint");
    process.exitCode = packageLintMonorepo(!!argv.fix);
  }
};
export {
  lintCommand
};
//# sourceMappingURL=lintCommand.mjs.map