// src/lib/checkResult.ts
import chalk from "chalk";
var checkResult = (name, result, level = "error", exitOnFail = false) => {
  if (result) {
    const exiting = exitOnFail ? "[Exiting Process]" : "[Continuing]";
    const chalkFunc = level === "error" ? chalk.red : chalk.yellow;
    console[level](chalkFunc(`${name} had ${result} failures ${exiting}`));
    if (exitOnFail) {
      process.exit(result);
    }
  }
};

// src/lib/claudeMdTemplate.ts
import {
  readdirSync,
  readFileSync,
  statSync
} from "fs";
import { createRequire } from "module";
import PATH from "path";
var require2 = createRequire(import.meta.url);
var packageRoot = PATH.dirname(require2.resolve("@xylabs/toolchain/package.json"));
var templatesDir = PATH.resolve(packageRoot, "templates", "claude");
function applyPackageManager(content, pm) {
  const xyCommand = pm === "npm" ? "npm exec -- xy" : pm === "bun" ? "bun run xy" : `${pm} xy`;
  const addCommand = pm === "npm" ? "npm install" : pm === "bun" ? "bun add" : `${pm} add`;
  return content.replaceAll("yarn xy", xyCommand).replaceAll("pnpm xy", xyCommand).replaceAll("yarn add", addCommand).replaceAll("pnpm add", addCommand);
}
var XYLABS_RULES_PREFIX = "xylabs-";
var XYLABS_COMMANDS_PREFIX = "xy-";
var LEGACY_COMMANDS_PREFIX = "xylabs-";
var XYLABS_SKILLS_PREFIX = "xylabs-";
var claudeMdRuleTemplates = () => {
  const rulesDir = PATH.resolve(templatesDir, "rules");
  const files = readdirSync(rulesDir).filter((f) => f.startsWith(XYLABS_RULES_PREFIX) && f.endsWith(".md"));
  const result = {};
  for (const file of files) {
    result[file] = readFileSync(PATH.resolve(rulesDir, file), "utf8");
  }
  return result;
};
var claudeCommandTemplates = () => {
  const commandsDir = PATH.resolve(templatesDir, "commands");
  const files = readdirSync(commandsDir).filter((f) => f.startsWith(XYLABS_COMMANDS_PREFIX) && f.endsWith(".md"));
  const result = {};
  for (const file of files) {
    result[file] = readFileSync(PATH.resolve(commandsDir, file), "utf8");
  }
  return result;
};
var claudeSkillTemplates = () => {
  const skillsDir = PATH.resolve(templatesDir, "skills");
  const dirs = readdirSync(skillsDir).filter(
    (f) => f.startsWith(XYLABS_SKILLS_PREFIX) && statSync(PATH.resolve(skillsDir, f)).isDirectory()
  );
  const result = {};
  for (const dir of dirs) {
    const dirPath = PATH.resolve(skillsDir, dir);
    const files = readdirSync(dirPath, { recursive: true, encoding: "utf8" });
    result[dir] = {};
    for (const file of files) {
      if (statSync(PATH.resolve(dirPath, file)).isFile()) {
        result[dir][file] = readFileSync(PATH.resolve(dirPath, file), "utf8");
      }
    }
  }
  return result;
};
var claudeMdProjectTemplate = () => readFileSync(PATH.resolve(templatesDir, "CLAUDE-project.md"), "utf8");
var claudeMdLocalTemplate = () => readFileSync(PATH.resolve(templatesDir, "CLAUDE-local.md"), "utf8");

// src/lib/concurrency.ts
import { AsyncLocalStorage } from "async_hooks";
var outputStorage = new AsyncLocalStorage();
var captureInstalled = false;
function installOutputCapture() {
  if (captureInstalled) return;
  captureInstalled = true;
  const originalStdoutWrite = process.stdout.write.bind(process.stdout);
  const originalStderrWrite = process.stderr.write.bind(process.stderr);
  function intercept(original) {
    return function(chunk, ...args) {
      const buffer = outputStorage.getStore();
      if (buffer) {
        buffer.push(typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk));
        return true;
      }
      return original(chunk, ...args);
    };
  }
  process.stdout.write = intercept(originalStdoutWrite);
  process.stderr.write = intercept(originalStderrWrite);
}
async function runWithConcurrency(items, concurrency, fn) {
  let next = 0;
  async function worker() {
    while (next < items.length) {
      const i = next++;
      await fn(items[i]);
    }
  }
  await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()));
}

// src/lib/createBuildConfig.ts
import { readFileSync as readFileSync2 } from "fs";

// src/lib/defaultBuildConfig.ts
var defaultBuildConfig = {
  compilerOptions: {
    rootDir: "src",
    rootDirs: ["package.json"]
  },
  exclude: [
    "**/build",
    "**/dist",
    "**/node_modules",
    "**/*.spec.*",
    "**/*.spec",
    "**/*.stories.*",
    "**/*.example.*",
    "**/spec/*",
    "**/stories/*"
  ],
  include: ["src"]
};

// src/lib/createBuildConfig.ts
var getGeneralTypescriptConfig = (location) => {
  let generalConfig;
  try {
    generalConfig = readFileSync2(`${location}/tsconfig.json`, { encoding: "utf8" });
  } catch {
    return false;
  }
  return JSON.parse(generalConfig);
};
var createBuildConfig = (location, module, target, outDirSuffix) => {
  const generalConfigObject = getGeneralTypescriptConfig(location);
  if (generalConfigObject === false) {
    return void 0;
  }
  return {
    ...generalConfigObject,
    compilerOptions: {
      ...defaultBuildConfig.compilerOptions,
      ...generalConfigObject.compilerOptions,
      module,
      outDir: `./${generalConfigObject.compilerOptions?.outDir ?? "dist"}/${outDirSuffix}`,
      target
    },
    exclude: [...generalConfigObject.exclude ?? [], ...defaultBuildConfig.exclude],
    include: [...generalConfigObject.include ?? [], ...defaultBuildConfig.include]
  };
};

// src/lib/deleteGlob.ts
import fs from "fs";
import { glob } from "glob";
var deleteGlob = (globPath) => {
  const files = glob.sync(globPath);
  for (const file of files) {
    fs.rmSync(file, { recursive: true, force: true });
  }
};

// src/lib/dependencies/detectDuplicateDependencies.ts
import { execSync } from "child_process";

// src/lib/packageManagerRuntime.ts
import { spawnSync } from "child_process";
import fs2 from "fs";
import chalk2 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 = fs2.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(chalk2.yellow(`${DISPLAY_NAMES[plan.packageManager]} is required for "${context.operation}".`));
  for (const line of plan.manualInstructions) {
    console.error(chalk2.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(chalk2.yellow(`${context.operation} requires ${displayName}, but it is not installed.`));
  if (!plan.supported) {
    printManualInstructions(plan, context);
    return false;
  }
  if (!isCommandInstalled("brew")) {
    console.error(chalk2.yellow("Homebrew is not installed, so automatic installation is unavailable."));
    console.error(chalk2.gray("  Install Homebrew from https://brew.sh and then run:"));
    console.error(chalk2.gray(`  ${plan.command}`));
    return false;
  }
  const confirmed = askYesNo(chalk2.cyan(`Install ${displayName} with Homebrew now? [y/N] `));
  if (!confirmed) {
    console.error(chalk2.gray(`Skipping install. Run "${plan.command}" manually and then retry.`));
    return false;
  }
  console.error(chalk2.cyan(`Installing ${displayName} via Homebrew...
`));
  if (!installWithHomebrew(pm, context.cwd)) {
    console.error(chalk2.red(`Homebrew failed to install ${displayName}.`));
    console.error(chalk2.gray(`Run "${plan.command}" manually and then retry.`));
    return false;
  }
  if (!isPackageManagerInstalled(pm)) {
    console.error(chalk2.red(`${displayName} still does not appear to be installed after Homebrew completed.`));
    console.error(chalk2.gray(`Run "${plan.command}" manually and then retry.`));
    return false;
  }
  console.error(chalk2.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 as readFileSync3 } from "fs";
import PATH2 from "path";
import { globSync } from "glob";
function readJsonFile(path2) {
  if (!existsSync(path2)) return void 0;
  try {
    return JSON.parse(readFileSync3(path2, "utf8"));
  } catch {
    return void 0;
  }
}
function readRootPackageJson(cwd = process.cwd()) {
  return readJsonFile(PATH2.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/yarn/isYarnVersionOrGreater.ts
var isYarnVersionOrGreater = (major, minor, patch) => {
  const result = spawnPackageManagerSync("yarn", ["-v"], {
    context: { operation: "Check installed Yarn version" },
    encoding: "utf8",
    shell: true
  });
  const version = result.stdout.toString().replaceAll("\n", "");
  const versionNumbers = version.split(".").map((ver) => Number.parseInt(ver));
  const majorDelta = versionNumbers[0] - major;
  const minorDelta = versionNumbers[1] - (minor ?? versionNumbers[1]);
  const patchDelta = versionNumbers[2] - (patch ?? versionNumbers[2]);
  const majorOk = majorDelta >= 0;
  const minorOk = majorDelta > 0 || minorDelta >= 0;
  const patchOk = majorDelta > 0 || minorDelta > 0 || patchDelta >= 0;
  return [majorOk && minorOk && patchOk, version];
};

// src/lib/yarn/workspace/yarnWorkspaces.ts
var yarnWorkspaces = () => {
  const result = spawnPackageManagerSync("yarn", ["workspaces", "list", "--json", "--recursive"], {
    context: { operation: "List Yarn workspaces" },
    encoding: "utf8"
  });
  if (result.error) {
    throw result.error;
  }
  return result.stdout.toString().split("\n").slice(0, -1).map((item) => {
    return JSON.parse(item);
  });
};

// src/lib/yarn/workspace/yarnWorkspace.ts
var yarnWorkspace = (pkg) => {
  const workspace = yarnWorkspaces().find(({ name }) => name === pkg);
  if (!workspace) throw new Error(`Workspace ${pkg} not found`);
  return workspace;
};

// src/lib/processEx.ts
import chalk3 from "chalk";

// src/lib/withError.ts
var withError = (ex, closure, predicate = (ex2) => !!ex2.name && !!ex2.message) => {
  return predicate(ex) ? closure(ex) : void 0;
};

// src/lib/withErrnoException.ts
var withErrnoException = (ex, closure) => {
  return withError(ex, closure, (ex2) => ex2.errno !== void 0);
};

// src/lib/processEx.ts
var processEx = (ex) => {
  const error = typeof ex === "string" ? new Error(ex) : ex;
  const exitCode = withErrnoException(error, (error2) => {
    if (error2.code === "ENOENT") {
      console.error(chalk3.red(`'${error2.path}' not found.`));
    } else {
      console.error(chalk3.red(`Errno: ${error2.code}`));
    }
    return error2.errno ?? -1;
  }) ?? withError(error, (error2) => {
    console.error(chalk3.red(`${error2.name}: ${error2.message}`));
    return -1;
  }) ?? (() => {
    console.error(chalk3.red(`Unexpected Error: ${JSON.stringify(ex, null, 2)}`));
    return -1;
  })();
  process.exit(process.exitCode ?? exitCode);
};

// src/lib/safeExit.ts
var safeExit = (func, exitOnFail = true) => {
  try {
    const result = func();
    if (result && exitOnFail) {
      process.exit(result);
    }
    return result;
  } catch (ex) {
    return processEx(ex);
  }
};
var safeExitAsync = async (func, exitOnFail = true) => {
  try {
    const result = await func();
    if (result && exitOnFail) {
      process.exit(result);
    }
    return result;
  } catch (ex) {
    return processEx(ex);
  }
};

// src/lib/dependencies/DuplicateDetector.ts
import { EOL } from "os";
import chalk4 from "chalk";

// src/lib/jsonFormatters.ts
var multiLineToJSONArray = (output) => {
  const withCommas = output.replaceAll("\r\n", "").replaceAll("\n", ",");
  const cleanCollection = withCommas.slice(0, Math.max(0, withCommas.length - 1));
  const collection = `[${cleanCollection}]`;
  return JSON.parse(collection);
};

// src/lib/dependencies/DuplicateDetector.ts
var trimVirtualMeta = (value) => {
  const virtualParts = value.split("virtual:");
  if (virtualParts.length > 1) {
    const hashParts = virtualParts[1].split("#");
    return virtualParts[0] + hashParts[1];
  } else {
    return value;
  }
};
var trimObjectDependencyVirtualMeta = (obj) => {
  const resultObj = {};
  for (const [key, value] of Object.entries(obj)) {
    resultObj[trimVirtualMeta(key)] = {
      descriptor: trimVirtualMeta(value.descriptor),
      locator: trimVirtualMeta(value.locator)
    };
  }
  return resultObj;
};
var trimDependencyVirtualMeta = (dependencies) => {
  return dependencies.map((dependency) => {
    return { children: trimObjectDependencyVirtualMeta(dependency.children), value: trimVirtualMeta(dependency.value) };
  });
};
function extractPnpmVersions(data, depName) {
  const versions = /* @__PURE__ */ new Set();
  function walk(obj) {
    if (Array.isArray(obj)) {
      for (const item of obj) walk(item);
    } else if (obj && typeof obj === "object") {
      const record = obj;
      if (typeof record.version === "string" && typeof record.from === "string" && record.from === depName) {
        versions.add(record.version);
      }
      for (const val of Object.values(record)) walk(val);
    }
  }
  walk(data);
  return [...versions];
}
var DuplicateDetector = class {
  dependency;
  duplicateVersions;
  constructor(output, dependency) {
    this.dependency = dependency;
    this.duplicateVersions = this.parseVersions(output, dependency);
  }
  detect() {
    if (this.duplicateVersions.length > 1) {
      console.log(chalk4.yellow(`${EOL}Duplicates found for: ${this.dependency}`));
      const duplicateVersions = this.duplicateVersions.join(`${EOL}  `);
      console.log(chalk4.grey(`  ${duplicateVersions}`, EOL));
      return 1;
    } else {
      console.log(`${this.dependency} - OK`);
      return 0;
    }
  }
  parseVersions(output, dependency) {
    try {
      const parsed = JSON.parse(output);
      if (Array.isArray(parsed)) {
        return extractPnpmVersions(parsed, dependency);
      }
    } catch {
    }
    try {
      const entries = trimDependencyVirtualMeta(multiLineToJSONArray(output));
      const versions = /* @__PURE__ */ new Set();
      for (const entry of entries) {
        for (const key of Object.keys(entry.children)) {
          const version = key.includes("@virtual:") ? void 0 : key;
          if (version) versions.add(version);
        }
      }
      return [...versions];
    } catch {
      console.warn(chalk4.yellow(`Could not parse dependency output for ${dependency}`));
      return [];
    }
  }
};

// src/lib/dependencies/detectDuplicateDependencies.ts
var detectDuplicateDependencies = (depsFromPackageJSON, DefaultDependencies) => {
  let exitCode = 0;
  const dependencies = depsFromPackageJSON?.length ? depsFromPackageJSON : DefaultDependencies;
  return safeExit(() => {
    if (dependencies) {
      for (const dependency of dependencies) {
        let output;
        try {
          const pm = getPackageManager();
          const cmd = `${pm.command} why ${dependency} --json`;
          output = execSync(cmd, { maxBuffer: 64 * 1024 * 1024 }).toString();
        } catch (e) {
          console.error(`Error running dependency check: ${String(e)}`);
          exitCode = 1;
          continue;
        }
        if (output) {
          exitCode = new DuplicateDetector(output, dependency).detect();
        } else {
          console.log(`${dependency} - N/A`);
          if (depsFromPackageJSON) {
            exitCode = 1;
            console.log(`\u{1F6A8} Library ${dependency} was requested in package.json but not found`);
          }
        }
      }
      return exitCode;
    } else {
      console.log("\u{1F6A8} No dependencies where passed");
      return exitCode;
    }
  });
};

// src/lib/dependencies/workspaceCycles.ts
import { readFileSync as readFileSync4 } from "fs";
import PATH3 from "path";
import chalk5 from "chalk";
function detectWorkspaceCycles(workspaces) {
  const workspaceNames = new Set(workspaces.map((ws) => ws.name));
  const graph = /* @__PURE__ */ new Map();
  for (const ws of workspaces) {
    const pkgPath = PATH3.join(ws.location, "package.json");
    const pkg = JSON.parse(readFileSync4(pkgPath, "utf8"));
    const deps = pkg.dependencies ?? {};
    const devDeps = pkg.devDependencies ?? {};
    const edges = [];
    for (const dep of Object.keys(deps)) {
      if (workspaceNames.has(dep)) edges.push({ name: dep, type: "dep" });
    }
    for (const dep of Object.keys(devDeps)) {
      if (workspaceNames.has(dep)) edges.push({ name: dep, type: "devDep" });
    }
    graph.set(ws.name, edges);
  }
  const WHITE = 0;
  const GRAY = 1;
  const BLACK = 2;
  const color = /* @__PURE__ */ new Map();
  const cycles = [];
  const path2 = [];
  const onPath = /* @__PURE__ */ new Set();
  for (const name of workspaceNames) color.set(name, WHITE);
  function dfs(u, incomingEdgeType) {
    color.set(u, GRAY);
    onPath.add(u);
    path2.push({ name: u, edgeType: incomingEdgeType });
    for (const edge of graph.get(u) ?? []) {
      const v = edge.name;
      if (onPath.has(v)) {
        const cycleEdges = [];
        const startIdx = path2.findIndex((p) => p.name === v);
        for (let i = startIdx; i < path2.length - 1; i++) {
          const nextEdgeType = path2[i + 1].edgeType ?? "dep";
          cycleEdges.push({
            from: path2[i].name,
            to: path2[i + 1].name,
            type: nextEdgeType
          });
        }
        cycleEdges.push({
          from: u,
          to: v,
          type: edge.type
        });
        cycles.push(cycleEdges);
      } else if (color.get(v) === WHITE) {
        dfs(v, edge.type);
      }
    }
    path2.pop();
    onPath.delete(u);
    color.set(u, BLACK);
  }
  for (const name of workspaceNames) {
    if (color.get(name) === WHITE) dfs(name);
  }
  return cycles;
}
function printWorkspaceCycles(cycles) {
  for (const cycle of cycles) {
    console.error(chalk5.red("  Workspace dependency cycle:"));
    for (const edge of cycle) {
      const edgeLabel = edge.type === "devDep" ? chalk5.yellow("devDep") : chalk5.cyan("dep");
      console.error(`    ${chalk5.white(edge.from)} --(${edgeLabel})--> ${chalk5.white(edge.to)}`);
    }
  }
}

// src/lib/deprecationMigrate.ts
import {
  existsSync as existsSync3,
  readFileSync as readFileSync5,
  writeFileSync
} from "fs";
import PATH4 from "path";
import { createInterface } from "readline";
import chalk6 from "chalk";
var DEPRECATED_PACKAGES = [
  "@xylabs/ts-scripts-common",
  "@xylabs/ts-scripts-yarn3",
  "@xylabs/ts-scripts-pnpm",
  "@xylabs/ts-scripts-react-yarn3"
];
function findProjectRoot() {
  return process.env.INIT_CWD ?? process.cwd();
}
function askYesNo2(question) {
  const rl = createInterface({ input: process.stdin, output: process.stderr });
  return new Promise((resolve) => {
    rl.question(question, (answer) => {
      rl.close();
      resolve(answer.trim().toLowerCase().startsWith("y"));
    });
  });
}
function replaceAllOldPackagesInFile(filePath) {
  if (!existsSync3(filePath)) return false;
  let content = readFileSync5(filePath, "utf8");
  let changed = false;
  for (const oldPkg of DEPRECATED_PACKAGES) {
    if (content.includes(oldPkg)) {
      content = content.replaceAll(oldPkg, "@xylabs/toolchain");
      changed = true;
    }
  }
  if (changed) {
    writeFileSync(filePath, content, "utf8");
  }
  return changed;
}
function migratePackageJson(pkgPath, label) {
  if (!existsSync3(pkgPath)) return false;
  const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
  let changed = false;
  for (const field of ["dependencies", "devDependencies", "peerDependencies"]) {
    for (const oldPkg of DEPRECATED_PACKAGES) {
      if (pkg[field]?.[oldPkg]) {
        const ver = pkg[field][oldPkg];
        delete pkg[field][oldPkg];
        if (!pkg[field]["@xylabs/toolchain"]) {
          pkg[field]["@xylabs/toolchain"] = ver;
        }
        changed = true;
      }
    }
  }
  if (changed) {
    writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
`, "utf8");
    console.warn(chalk6.green(`  \u2713 Updated ${label}`));
  }
  return changed;
}
async function migrateWorkspaces(root) {
  const { globSync: globSync2 } = await import("glob");
  const packageJsonFiles = globSync2("**/package.json", {
    cwd: root,
    ignore: ["node_modules/**", "**/node_modules/**", "dist/**", "**/dist/**"]
  });
  for (const relPath of packageJsonFiles) {
    if (relPath === "package.json") continue;
    const dir = PATH4.dirname(relPath);
    migratePackageJson(PATH4.join(root, relPath), relPath);
    const xyConfigPath = PATH4.join(root, dir, "xy.config.ts");
    if (replaceAllOldPackagesInFile(xyConfigPath)) {
      console.warn(chalk6.green(`  \u2713 Updated ${dir}/xy.config.ts`));
    }
  }
}
function printManualInstructions2() {
  console.warn(chalk6.gray("  Skipped. To migrate manually:\n"));
  console.warn(chalk6.gray("    1. Replace all @xylabs/ts-scripts-* deps with @xylabs/toolchain in package.json"));
  console.warn(chalk6.gray("    2. Update imports in xy.config.ts files"));
  console.warn(chalk6.gray("    3. Run your package manager install\n"));
}
async function deprecationMigrate(oldPackage) {
  const root = findProjectRoot();
  const pkgPath = PATH4.join(root, "package.json");
  if (!existsSync3(pkgPath)) return;
  const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
  const hasOldDep = DEPRECATED_PACKAGES.some((dep) => pkg.dependencies?.[dep] || pkg.devDependencies?.[dep]);
  if (!hasOldDep) return;
  console.warn(chalk6.yellow(`
\u26A0  ${oldPackage} is deprecated. Use @xylabs/toolchain instead.
`));
  const shouldMigrate = await askYesNo2(chalk6.cyan("  Auto-migrate to @xylabs/toolchain? [y/N] "));
  if (!shouldMigrate) {
    printManualInstructions2();
    return;
  }
  migratePackageJson(pkgPath, "package.json");
  if (replaceAllOldPackagesInFile(PATH4.join(root, "xy.config.ts"))) {
    console.warn(chalk6.green("  \u2713 Updated xy.config.ts"));
  }
  await migrateWorkspaces(root);
  const pm = detectPackageManager();
  console.warn(chalk6.cyan(`
  Running ${pm} install...
`));
  const result = spawnPackageManagerSync(pm, ["install"], {
    context: { cwd: root, operation: `Run ${pm} install after toolchain migration` },
    cwd: root,
    encoding: "utf8",
    stdio: "inherit"
  });
  if (result.status === 0) {
    console.warn(chalk6.green("  \u2713 Migration complete. Re-run your command.\n"));
  } else {
    console.warn(chalk6.red(`  Install failed (exit ${result.status}). Run "${pm} install" manually.
`));
  }
  process.exit(result.status ?? 1);
}

// src/lib/file/constants.ts
var WINDOWS_NEWLINE_REGEX = /\r\n/g;
var CROSS_PLATFORM_NEWLINE = "\n";

// src/lib/file/fileLines.ts
import {
  existsSync as existsSync4,
  readFileSync as readFileSync6,
  writeFileSync as writeFileSync2
} from "fs";

// src/lib/string/empty.ts
var empty = (value) => value?.trim().length === 0;
var notEmpty = (value) => !empty(value);

// src/lib/string/union.ts
var union = (a, b) => /* @__PURE__ */ new Set([...new Set(a), ...new Set(b)]);

// src/lib/file/ReadFileSyncOptions.ts
var defaultReadFileSyncOptions = { encoding: "utf8" };

// src/lib/file/fileLines.ts
var readLines = (uri, options = defaultReadFileSyncOptions) => existsSync4(uri) ? readFileSync6(uri, options).replace(WINDOWS_NEWLINE_REGEX, CROSS_PLATFORM_NEWLINE).split(CROSS_PLATFORM_NEWLINE) : [];
var readNonEmptyLines = (uri, options = defaultReadFileSyncOptions) => readLines(uri, options).filter(notEmpty);
var writeLines = (uri, lines, options = defaultReadFileSyncOptions) => {
  const existing = existsSync4(uri) ? readFileSync6(uri, options) : void 0;
  const desired = lines.join(CROSS_PLATFORM_NEWLINE);
  if (existing !== desired) writeFileSync2(uri, desired, options);
};

// src/lib/file/tryReadFileSync.ts
import { existsSync as existsSync5, readFileSync as readFileSync7 } from "fs";
var tryReadFileSync = (uri, options = defaultReadFileSyncOptions) => {
  return existsSync5(uri) ? readFileSync7(uri, options) : void 0;
};

// src/lib/fillTemplate.ts
function fillTemplate(template, data) {
  return template.replaceAll(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] ?? "");
}

// src/lib/generateIgnoreFiles.ts
import chalk7 from "chalk";

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

// src/lib/generateIgnoreFiles.ts
var localeCompare = (a, b) => a.localeCompare(b);
var mergeEntries = (a, b) => [...union(a, b)].toSorted(localeCompare);
var generateIgnoreFiles = (filename, pkg) => {
  console.log(chalk7.green(`Generate ${filename} Files`));
  const cwd = INIT_CWD();
  const pm = getPackageManager();
  const singleWorkspace = pkg ? pm.findWorkspace(pkg) : void 0;
  const workspaces = singleWorkspace ? [singleWorkspace] : pm.listWorkspaces();
  const readEntries = (location) => readNonEmptyLines(`${location}/${filename}`);
  const writeEntries = (location, entries) => writeLines(`${location}/${filename}`, entries);
  const results = workspaces.map(({ location, name }) => {
    try {
      writeEntries(location, mergeEntries(readEntries(cwd), readEntries(location)));
      return 0;
    } catch (ex) {
      const error = ex;
      console.error(`Generate ${filename} Files [${name}] [${error.message}]`);
      return 1;
    }
  });
  const succeeded = results.every((result) => result === 0);
  return succeeded ? 0 : 1;
};

// src/lib/generateReadmeFiles.ts
import { execFile } from "child_process";
import FS, { readFileSync as readFileSync8 } from "fs";
import {
  mkdir,
  readFile,
  writeFile
} from "fs/promises";
import { createRequire as createRequire2 } from "module";
import PATH5 from "path";
import { createInterface as createInterface2 } from "readline";
import { promisify } from "util";
import chalk8 from "chalk";
var execFileAsync = promisify(execFile);
var require3 = createRequire2(import.meta.url);
var packageRoot2 = PATH5.dirname(require3.resolve("@xylabs/toolchain/package.json"));
var readmeTemplatesDir = PATH5.resolve(packageRoot2, "templates", "readme");
function fillReadmeTemplate(template, data) {
  const additionalData = { ...data, safeName: data.name.replaceAll("/", "__").replaceAll("@", "") };
  return fillTemplate(template, additionalData);
}
async function generateTypedoc(packageLocation, entryPoints) {
  const tempDir = PATH5.join(packageLocation, ".temp-typedoc");
  try {
    if (!FS.existsSync(tempDir)) {
      FS.mkdirSync(tempDir, { recursive: true });
    }
    const typedocConfig = {
      disableSources: true,
      entryPointStrategy: "expand",
      entryPoints: entryPoints.map((ep) => PATH5.resolve(packageLocation, ep)),
      excludeExternals: true,
      excludeInternal: true,
      excludePrivate: true,
      githubPages: false,
      hideBreadcrumbs: true,
      hideGenerator: true,
      hidePageTitle: true,
      out: tempDir,
      plugin: ["typedoc-plugin-markdown"],
      readme: "none",
      skipErrorChecking: true,
      sort: ["source-order"],
      theme: "markdown",
      useCodeBlocks: true
    };
    const typedocJsonPath = PATH5.join(tempDir, "typedoc.json");
    FS.writeFileSync(typedocJsonPath, JSON.stringify(typedocConfig, null, 2));
    try {
      await execFileAsync("npx", ["typedoc", "--options", typedocJsonPath], { cwd: process.cwd() });
    } catch {
      return "";
    }
    return consolidateMarkdown(tempDir);
  } catch {
    return "";
  } finally {
    try {
      FS.rmSync(tempDir, { force: true, recursive: true });
    } catch {
    }
  }
}
function consolidateMarkdown(tempDir) {
  let consolidated = "## Reference\n\n";
  const mainReadmePath = PATH5.join(tempDir, "README.md");
  if (FS.existsSync(mainReadmePath)) {
    const mainContent = FS.readFileSync(mainReadmePath, "utf8").replace(/^---(.|\n)*?---\n/, "").replace(/^# .+\n/, "").replaceAll(/\]\((.+?)\.md\)/g, "](#$1)");
    consolidated += mainContent + "\n\n";
  }
  consolidated += processDirectory(tempDir);
  return consolidated.replaceAll(/\n\n\n+/g, "\n\n").replaceAll(/^#### /gm, "### ").replaceAll(/^##### /gm, "#### ").replaceAll(/^###### /gm, "##### ");
}
function processDirectory(dir, level = 0) {
  const indent = "  ".repeat(level);
  let content = "";
  try {
    const items = FS.readdirSync(dir, { withFileTypes: true });
    for (const item of items) {
      if (item.isDirectory()) continue;
      if (item.name === "README.md" || !item.name.endsWith(".md")) continue;
      const fileContent = FS.readFileSync(PATH5.join(dir, item.name), "utf8").replace(/^---(.|\n)*?---\n/, "");
      const moduleName = item.name.replace(".md", "");
      content += `

${indent}### <a id="${moduleName}"></a>${moduleName}

`;
      content += fileContent.replace(/^# .+\n/, "").replaceAll(/\]\((.+?)\.md\)/g, "](#$1)");
    }
    for (const item of items) {
      if (!item.isDirectory()) continue;
      if (item.name === "spec" || item.name.includes(".spec")) continue;
      content += `

${indent}### ${item.name}
`;
      content += processDirectory(PATH5.join(dir, item.name), level + 1);
    }
  } catch {
  }
  return content;
}
function askConfirmation(question) {
  const rl = createInterface2({ input: process.stdin, output: process.stdout });
  return new Promise((resolve) => {
    rl.question(question, (answer) => {
      rl.close();
      resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
    });
  });
}
var DEFAULT_README_TEMPLATE = readFileSync8(PATH5.resolve(readmeTemplatesDir, "README.template.md"), "utf8");
var DEFAULT_README_BODY = readFileSync8(PATH5.resolve(readmeTemplatesDir, "README.body.md"), "utf8");
function applyLogoConfig(template, logoUrl, logoLinkUrl) {
  let result = template;
  if (logoUrl) {
    result = result.replace(/\[logo]: .+/, `[logo]: ${logoUrl}`);
    if (logoLinkUrl) {
      result = result.replace(/\[!\[logo]\[]][^)]*\)/, `[![logo][]](${logoLinkUrl})`);
    }
  } else {
    result = result.replace(/\[!\[logo]\[]][^\n]*\n*/, "");
    result = result.replace(/\[logo]: [^\n]*\n?/, "");
  }
  return result;
}
function resolveTemplatePath(templatePath) {
  const cwd = INIT_CWD();
  return templatePath ?? PATH5.join(cwd, ".xy", "README.template.md");
}
async function loadOrCreateTemplate(resolvedTemplatePath) {
  try {
    const template = await readFile(resolvedTemplatePath, "utf8");
    return { created: false, template };
  } catch {
    console.log(chalk8.yellow(`Template not found: ${resolvedTemplatePath}`));
    const shouldCreate = await askConfirmation("Would you like to create a stock template? (y/N) ");
    if (!shouldCreate) {
      throw new Error("Template creation declined");
    }
    const template = DEFAULT_README_TEMPLATE;
    await scaffoldTemplate(resolvedTemplatePath, template);
    return { created: true, template };
  }
}
async function scaffoldTemplate(resolvedTemplatePath, template) {
  const xyDir = PATH5.dirname(resolvedTemplatePath);
  await mkdir(xyDir, { recursive: true });
  await writeFile(resolvedTemplatePath, template);
  console.log(chalk8.green(`Created template: ${resolvedTemplatePath}`));
  const bodyPath = PATH5.join(xyDir, "README.body.md");
  await writeFile(bodyPath, DEFAULT_README_BODY);
  console.log(chalk8.green(`Created body template: ${bodyPath}`));
}
async function resolveBody(location, defaultBody) {
  const localBodyPath = PATH5.join(location, "README.body.md");
  try {
    return await readFile(localBodyPath, "utf8");
  } catch {
    return defaultBody;
  }
}
async function generateReadmeForWorkspace(location, name, template, defaultBody, typedoc, verbose, pm) {
  try {
    const pkgJsonPath = PATH5.join(location, "package.json");
    const pkgJson = JSON.parse(await readFile(pkgJsonPath, "utf8"));
    const body = await resolveBody(location, defaultBody);
    const typedocContent = typedoc ? await generateTypedoc(location, ["src/index*.ts"]) : "";
    const readmeContent = fillReadmeTemplate(template, {
      ...pkgJson,
      body,
      pm,
      typedoc: typedocContent
    });
    await writeFile(PATH5.join(location, "README.md"), readmeContent);
    if (verbose) console.log(chalk8.green(`  ${name}`));
    return true;
  } catch (ex) {
    const error = ex;
    console.warn(chalk8.yellow(`  Skipped ${location}: ${error.message}`));
    return false;
  }
}
async function loadDefaultBody(resolvedTemplatePath) {
  const xyBodyPath = PATH5.join(PATH5.dirname(resolvedTemplatePath), "README.body.md");
  try {
    return await readFile(xyBodyPath, "utf8");
  } catch {
    return DEFAULT_README_BODY;
  }
}
function flushResults(results) {
  let failed = false;
  for (const { output, success } of results) {
    for (const line of output) {
      process.stdout.write(line);
    }
    if (!success) failed = true;
  }
  return failed;
}
async function generateReadmeFiles({
  jobs,
  logoLinkUrl,
  logoUrl,
  pkg,
  templatePath,
  typedoc = false,
  verbose = false
}) {
  console.log(chalk8.green("Generate README Files"));
  const resolvedTemplatePath = resolveTemplatePath(templatePath);
  let template;
  let templateCreated;
  try {
    ({ template, created: templateCreated } = await loadOrCreateTemplate(resolvedTemplatePath));
  } catch {
    return 1;
  }
  template = applyLogoConfig(template, logoUrl, logoLinkUrl);
  if (templateCreated) {
    console.log(chalk8.green("Generating README files for all packages..."));
  }
  const defaultBody = await loadDefaultBody(resolvedTemplatePath);
  const pmName = detectPackageManager();
  const pm = getPackageManager();
  const singleWorkspace = pkg && !templateCreated ? pm.findWorkspace(pkg) : void 0;
  const workspaces = singleWorkspace ? [singleWorkspace] : pm.listWorkspaces();
  const concurrency = jobs;
  const results = Array.from({ length: workspaces.length }, () => ({ output: [], success: true }));
  installOutputCapture();
  const start = performance.now();
  await runWithConcurrency(
    workspaces.map((ws, i) => ({ i, ws })),
    concurrency,
    async ({ i, ws }) => {
      const output = [];
      await outputStorage.run(output, async () => {
        const success = await generateReadmeForWorkspace(ws.location, ws.name, template, defaultBody, typedoc, verbose, pmName);
        results[i] = { output, success };
      });
    }
  );
  const failed = flushResults(results);
  const ms = performance.now() - start;
  console.log(chalk8.blue(`Generated ${workspaces.length} README(s) in ${ms.toFixed(0)}ms`));
  return failed ? 1 : 0;
}

// src/lib/gitConfig.ts
import { execFileSync } from "child_process";
function getGitConfig(key) {
  try {
    const value = execFileSync("git", ["config", "--get", key], {
      encoding: "utf8",
      stdio: ["ignore", "pipe", "ignore"]
    }).trim();
    return value.length > 0 ? value : void 0;
  } catch {
    return void 0;
  }
}
function getGitConfigBool(key) {
  try {
    const value = execFileSync("git", ["config", "--bool", "--get", key], {
      encoding: "utf8",
      stdio: ["ignore", "pipe", "ignore"]
    }).trim();
    if (value === "true") return true;
    if (value === "false") return false;
    return void 0;
  } catch {
    return void 0;
  }
}
function setGitConfig(key, value) {
  execFileSync("git", ["config", key, value], { stdio: "inherit" });
}

// src/lib/gitignoreTemplate.ts
import { readFileSync as readFileSync9 } from "fs";
import { createRequire as createRequire3 } from "module";
import PATH6 from "path";
var require4 = createRequire3(import.meta.url);
var packageRoot3 = PATH6.dirname(require4.resolve("@xylabs/toolchain/package.json"));
var templatesDir2 = PATH6.resolve(packageRoot3, "templates", "gitignore");
var gitignoreTemplate = () => readFileSync9(PATH6.resolve(templatesDir2, "template.gitignore"), "utf8");

// 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/loadConfig.ts
import chalk9 from "chalk";
import { cosmiconfig } from "cosmiconfig";
import { TypeScriptLoader } from "cosmiconfig-typescript-loader";
import deepmerge from "deepmerge";
var config;
var rootConfigPath;
var workspaceConfigCache = /* @__PURE__ */ new Map();
var deprecationWarned = /* @__PURE__ */ new Set();
function createExplorer() {
  return cosmiconfig("xy", { cache: true, loaders: { ".ts": TypeScriptLoader() } });
}
var loadConfig = async (params) => {
  if (config === void 0) {
    const cosmicConfigResult = await createExplorer().search();
    config = cosmicConfigResult?.config ?? {};
    rootConfigPath = cosmicConfigResult?.filepath;
    const configFilePath = cosmicConfigResult?.filepath;
    if (configFilePath !== void 0) {
      console.log(chalk9.green(`Loaded config from ${configFilePath}`));
      if (config.verbose) {
        console.log(chalk9.gray(`${JSON.stringify(config, null, 2)}`));
      }
    }
  }
  return deepmerge(config, params ?? {});
};
async function loadWorkspaceConfig(workspaceDir) {
  const cached = workspaceConfigCache.get(workspaceDir);
  if (cached !== void 0) return cached;
  const result = await createExplorer().search(workspaceDir);
  if (!result || result.filepath === rootConfigPath) {
    workspaceConfigCache.set(workspaceDir, {});
    return {};
  }
  const wsConfig = result.config ?? {};
  workspaceConfigCache.set(workspaceDir, wsConfig);
  return wsConfig;
}
var DEPRECATED_COMMAND_FIELDS = /* @__PURE__ */ new Set(["deplint", "publint"]);
function resolveCommandField(cfg, commandName, configPath) {
  const commands = cfg.commands;
  const fromCommands = commands?.[commandName];
  const fromTopLevel = cfg[commandName];
  if (fromCommands !== void 0 && typeof fromCommands === "object") {
    return fromCommands;
  }
  if (fromTopLevel !== void 0 && typeof fromTopLevel === "object" && DEPRECATED_COMMAND_FIELDS.has(commandName)) {
    const key = `${configPath ?? "unknown"}:${commandName}`;
    if (!deprecationWarned.has(key)) {
      deprecationWarned.add(key);
      console.warn(chalk9.yellow(
        `[xy] Deprecated: top-level "${commandName}" in ${configPath ?? "xy.config"} \u2014 move to "commands.${commandName}"`
      ));
    }
    return fromTopLevel;
  }
  return {};
}
async function loadWorkspaceCommandConfig(workspaceDir, commandName) {
  const root = await loadConfig();
  const rootCmd = resolveCommandField(root, commandName, rootConfigPath);
  const wsConfig = await loadWorkspaceConfig(workspaceDir);
  const wsConfigPath = workspaceConfigCache.has(workspaceDir) ? workspaceDir : void 0;
  const wsCmd = resolveCommandField(wsConfig, commandName, wsConfigPath);
  return deepmerge(rootCmd, wsCmd);
}

// src/lib/packageName.ts
import { readFileSync as readFileSync10 } from "fs";
import path from "path";
function packageName() {
  if (process.env.npm_package_name) {
    return process.env.npm_package_name;
  }
  try {
    const pkgPath = path.join(INIT_CWD(), "package.json");
    const pkg = JSON.parse(readFileSync10(pkgPath, "utf8"));
    return pkg.name;
  } catch {
    return void 0;
  }
}

// src/lib/parsedPackageJSON.ts
import { readFileSync as readFileSync11 } from "fs";
var parsedPackageJSON = (path2) => {
  const pathToPackageJSON = path2 ?? process.env.npm_package_json ?? "";
  const packageJSON = readFileSync11(pathToPackageJSON).toString();
  return JSON.parse(packageJSON);
};

// src/lib/repoTemplates.ts
import { readdirSync as readdirSync2, readFileSync as readFileSync12 } from "fs";
import { createRequire as createRequire4 } from "module";
import PATH7 from "path";
var require5 = createRequire4(import.meta.url);
var packageRoot4 = PATH7.dirname(require5.resolve("@xylabs/toolchain/package.json"));
var repoTemplatesDir = PATH7.resolve(packageRoot4, "templates", "repo");
function collectFiles(dir, prefix) {
  const results = [];
  for (const entry of readdirSync2(dir, { withFileTypes: true })) {
    const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
    if (entry.isDirectory()) {
      results.push(...collectFiles(PATH7.resolve(dir, entry.name), rel));
    } else {
      results.push({
        content: readFileSync12(PATH7.resolve(dir, entry.name), "utf8"),
        relativePath: rel
      });
    }
  }
  return results;
}
function loadRepoTemplateFiles(template, section) {
  const dir = PATH7.resolve(repoTemplatesDir, template, section);
  return collectFiles(dir, "");
}
function listRepoTemplates() {
  return readdirSync2(repoTemplatesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
}

// src/lib/runInstall.ts
import chalk10 from "chalk";
function runInstall(cwd) {
  const pm = detectPackageManager();
  console.log(chalk10.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(chalk10.yellow(`${pm} install failed`));
    return false;
  }
  console.log(chalk10.green("Dependencies installed"));
  return true;
}

// src/lib/runSteps.ts
import { spawnSync as spawnSync2 } from "child_process";
import { existsSync as existsSync6 } from "fs";
import chalk11 from "chalk";
var packageManagers = /* @__PURE__ */ new Set(["bun", "npm", "pnpm", "yarn"]);
var runSteps = (name, steps, exitOnFail = true, messages) => {
  return safeExit(() => {
    const pkgName = packageName();
    console.log(chalk11.green(`${name} [${pkgName}]`));
    let totalStatus = 0;
    for (const [i, [command, args, config2]] of steps.entries()) {
      if (messages?.[i]) {
        console.log(chalk11.gray(messages?.[i]));
      }
      const argList = Array.isArray(args) ? args : args.split(" ");
      if (command === "node" && !existsSync6(argList[0])) {
        throw new Error(`File not found [${argList[0]}]`);
      }
      if (packageManagers.has(command) && !ensurePackageManagerInstalled(command, { operation: `${name}: ${command} ${Array.isArray(args) ? args.join(" ") : args}`.trim() })) {
        checkResult(name, 1, "error", exitOnFail);
        totalStatus += 1;
        continue;
      }
      const status = spawnSync2(command, Array.isArray(args) ? args : args.split(" "), {
        ...config2,
        encoding: "utf8",
        // Merge per-step env on top so callers can supply overrides
        // (e.g. NODE_OPTIONS=--max-old-space-size=...); process.env still
        // seeds the common case so FORCE_COLOR etc. survive.
        env: {
          FORCE_COLOR: "3",
          ...process.env,
          ...config2?.env
        },
        shell: true,
        stdio: "inherit"
      }).status ?? 0;
      checkResult(name, status, "error", exitOnFail);
      totalStatus += status ?? 0;
    }
    return totalStatus;
  }, !!exitOnFail);
};

// src/lib/runStepsAsync.ts
import { spawn } from "child_process";
import { existsSync as existsSync7 } from "fs";
import chalk12 from "chalk";
var packageManagers2 = /* @__PURE__ */ new Set(["bun", "npm", "pnpm", "yarn"]);
var runStepAsync = (name, step, exitOnFail = true, message) => {
  return new Promise((resolve) => {
    const [command, args, config2] = step;
    if (message) {
      console.log(chalk12.gray(message));
    }
    const argList = Array.isArray(args) ? args : args.split(" ");
    if (command === "node" && !existsSync7(argList[0])) {
      throw new Error(`File not found [${argList[0]}]`);
    }
    if (packageManagers2.has(command) && !ensurePackageManagerInstalled(command, { operation: `${name}: ${command} ${Array.isArray(args) ? args.join(" ") : args}`.trim() })) {
      checkResult(name, 1, "error", exitOnFail);
      resolve(1);
      return;
    }
    spawn(command, Array.isArray(args) ? args : args.split(" "), {
      ...config2,
      env: { FORCE_COLOR: "3", ...process.env },
      shell: true,
      stdio: "inherit"
    }).on("close", (code) => {
      if (code) {
        console.error(
          chalk12.red(
            `Command Exited With Non-Zero Result [${chalk12.gray(code)}] | ${chalk12.yellow(command)} ${chalk12.white(
              Array.isArray(args) ? args.join(" ") : args
            )}`
          )
        );
        checkResult(name, code, "error", exitOnFail);
        resolve(code);
      } else {
        resolve(0);
      }
    });
  });
};
var runStepsAsync = async (name, steps, exitOnFail = true, messages) => {
  return await safeExitAsync(async () => {
    const pkgName = packageName();
    console.log(chalk12.green(`${name} [${pkgName}]`));
    let result = 0;
    for (const [i, step] of steps.entries()) {
      result += await runStepAsync(name, step, exitOnFail, messages?.[i]);
    }
    return result;
  });
};

// src/lib/runXy.ts
var runXy = (command) => {
  const pm = getPackageManager();
  return runSteps(
    `XY [${command}]`,
    [pm.runXy([command, ...process.argv.filter((value, index) => index > 1 ? value : void 0)])]
  );
};

// src/lib/runXyWithWarning.ts
import chalk13 from "chalk";
var runXyWithWarning = (command) => {
  const pm = getPackageManager();
  const commandString = `${pm.command} ${command}`;
  const commandXyString = `${pm.command} xy ${command}`;
  console.warn(chalk13.yellow(`WARNING: [${chalk13.white(commandString)}] is deprecated for XY Labs Scripts.`));
  console.warn(chalk13.gray(`Did you mean [${chalk13.magenta(commandXyString)}]?`));
  return 1;
};

// src/lib/tryRunLocalScript.ts
import { readFileSync as readFileSync13 } from "fs";
import PATH8 from "path";
import chalk14 from "chalk";
function tryRunLocalScript(commandName) {
  if (process.env.XY_LOCAL_SCRIPT === "1") return void 0;
  const rootPkgPath = PATH8.resolve(process.cwd(), "package.json");
  let rootPkg;
  try {
    rootPkg = JSON.parse(readFileSync13(rootPkgPath, "utf8"));
  } catch {
    return void 0;
  }
  if (!rootPkg.scripts?.[commandName]) return void 0;
  const extraArgs = process.argv.slice(process.argv.indexOf(commandName) + 1);
  console.log(chalk14.blue(`Delegating "${commandName}" to local script`));
  const pm = getPackageManager();
  const result = spawnPackageManagerSync(pm.name, ["run", commandName, ...extraArgs], {
    cwd: process.cwd(),
    context: { operation: `Run local "${commandName}" script with ${pm.command}` },
    encoding: "utf8",
    env: {
      FORCE_COLOR: "3",
      ...process.env,
      XY_LOCAL_SCRIPT: "1"
    },
    shell: true,
    stdio: "inherit"
  });
  return result.status ?? 1;
}

// src/lib/updo/applyUpdates.ts
import { readFileSync as readFileSync14, writeFileSync as writeFileSync3 } from "fs";
import PATH9 from "path";
import chalk15 from "chalk";
function applyUpdates(cwd, workspaces, updates) {
  const updateMap = new Map(updates.map((u) => [u.name, u]));
  let modified = 0;
  for (const ws of workspaces) {
    const pkgPath = PATH9.resolve(cwd, ws.location, "package.json");
    let content;
    try {
      content = readFileSync14(pkgPath, "utf8");
    } catch {
      continue;
    }
    const pkg = JSON.parse(content);
    let changed = false;
    for (const depField of ["dependencies", "devDependencies", "peerDependencies"]) {
      const deps = pkg[depField];
      if (!deps) continue;
      for (const [name, currentRange] of Object.entries(deps)) {
        const update = updateMap.get(name);
        if (!update) continue;
        const prefix = /^([~^]|>=?|<=?)/.exec(currentRange)?.[0] ?? "~";
        const newRange = `${prefix}${update.targetVersion}`;
        if (deps[name] !== newRange) {
          deps[name] = newRange;
          changed = true;
        }
      }
    }
    if (changed) {
      writeFileSync3(pkgPath, `${JSON.stringify(pkg, null, 2)}
`);
      modified++;
      console.log(chalk15.gray(`  Updated ${ws.name}`));
    }
  }
  return modified;
}

// src/lib/updo/collectWorkspaceDeps.ts
import { readFileSync as readFileSync15 } from "fs";
import PATH10 from "path";
var DEP_FIELDS = ["dependencies", "devDependencies", "peerDependencies"];
function collectWorkspaceDeps(cwd, workspaces, workspaceNames) {
  const depMap = /* @__PURE__ */ new Map();
  for (const ws of workspaces) {
    const pkgPath = PATH10.resolve(cwd, ws.location, "package.json");
    let pkg;
    try {
      pkg = JSON.parse(readFileSync15(pkgPath, "utf8"));
    } catch {
      continue;
    }
    for (const depField of DEP_FIELDS) {
      const deps = pkg[depField];
      if (!deps) continue;
      for (const [name, range] of Object.entries(deps)) {
        if (workspaceNames.has(name)) continue;
        if (range.startsWith("workspace:")) continue;
        const existing = depMap.get(name);
        if (existing) {
          if (!existing.workspaces.includes(ws.name)) {
            existing.workspaces.push(ws.name);
          }
          if (!existing.depTypes.includes(depField)) {
            existing.depTypes.push(depField);
          }
          if (!existing.ranges.includes(range)) {
            existing.ranges.push(range);
          }
        } else {
          depMap.set(name, {
            depTypes: [depField],
            name,
            ranges: [range],
            workspaces: [ws.name]
          });
        }
      }
    }
  }
  return depMap;
}

// src/lib/updo/fetchRegistryInfo.ts
var REGISTRY_BASE = "https://registry.npmjs.org";
async function fetchRegistryInfo(packageName2) {
  try {
    const url = `${REGISTRY_BASE}/${encodeURIComponent(packageName2)}`;
    const res = await fetch(url, { headers: { Accept: "application/vnd.npm.install-v1+json" } });
    if (!res.ok) {
      return { distTags: {}, versions: [] };
    }
    const data = await res.json();
    return {
      distTags: data["dist-tags"] ?? {},
      versions: Object.keys(data.versions ?? {})
    };
  } catch {
    return { distTags: {}, versions: [] };
  }
}
async function fetchAllRegistryInfo(packageNames, concurrency = 16) {
  const results = /* @__PURE__ */ new Map();
  let completed = 0;
  const total = packageNames.length;
  await runWithConcurrency(packageNames, concurrency, async (name) => {
    results.set(name, await fetchRegistryInfo(name));
    completed++;
    if (completed % 25 === 0 || completed === total) {
      process.stderr.write(`\r  Fetched ${completed}/${total} packages...`);
    }
  });
  if (total > 0) {
    process.stderr.write("\n");
  }
  return results;
}

// src/lib/updo/interactiveSelect.ts
import {
  createPrompt,
  ExitPromptError,
  isDownKey,
  isEnterKey,
  isSpaceKey,
  isUpKey,
  useKeypress,
  useRef,
  useState
} from "@inquirer/core";
import chalk16 from "chalk";
import semver from "semver";
function versionColor(version, current) {
  if (!version || !current) return chalk16.gray;
  if (version === current) return chalk16.gray;
  const diff = semver.diff(current, version);
  if (diff === "major" || diff === "premajor") return chalk16.red;
  if (diff === "minor" || diff === "preminor") return chalk16.yellow;
  return chalk16.green;
}
function pad(raw, colored, width) {
  return colored + " ".repeat(Math.max(0, width - raw.length));
}
function dot(selected) {
  return selected ? chalk16.green("\u25CF") : chalk16.dim("\u25CB");
}
function renderHeader(w) {
  const header = [
    "  ",
    chalk16.bold("Package".padEnd(w.name)),
    chalk16.bold("Current".padEnd(w.current)),
    chalk16.bold("  Wanted".padEnd(w.wanted + 2)),
    chalk16.bold("  Latest".padEnd(w.latest + 2)),
    chalk16.bold("  Next/RC".padEnd(w.next + 2))
  ].join("  ");
  const totalWidth = w.name + w.current + w.wanted + w.latest + w.next + 24;
  return `${header}
${chalk16.gray("\u2500".repeat(totalWidth))}`;
}
function renderRow(dep, selection, active, w) {
  const pointer = active ? chalk16.cyan("\u276F") : " ";
  const rawName = dep.name;
  const name = active ? chalk16.white(rawName) : chalk16.gray(rawName);
  const rawCurrent = dep.current ?? "-";
  const current = chalk16.gray(rawCurrent);
  const rawWanted = dep.wanted ?? "-";
  const wantedColorFn = dep.wanted ? versionColor(dep.wanted, dep.current) : chalk16.gray;
  const wantedDot = dep.wanted ? dot(selection === 0) : " ";
  const wanted = `${wantedDot} ${pad(rawWanted, wantedColorFn(rawWanted), w.wanted)}`;
  const rawLatest = dep.latest ?? "-";
  const latestColorFn = dep.latest ? versionColor(dep.latest, dep.current) : chalk16.gray;
  const latestDot = dep.latest ? dot(selection === 1) : " ";
  const latest = `${latestDot} ${pad(rawLatest, latestColorFn(rawLatest), w.latest)}`;
  const rawNext = dep.next ?? "-";
  const nextColorFn = dep.next ? versionColor(dep.next, dep.current) : chalk16.gray;
  const nextDot = dep.next ? dot(selection === 2) : " ";
  const next = `${nextDot} ${pad(rawNext, nextColorFn(rawNext), w.next)}`;
  return `${pointer} ${pad(rawName, name, w.name)}  ${pad(rawCurrent, current, w.current)}  ${wanted}  ${latest}  ${next}`;
}
function getAvailableSelections(dep) {
  const available = [-1];
  if (dep.wanted) available.push(0);
  if (dep.latest && dep.latest !== dep.wanted) available.push(1);
  if (dep.next) available.push(2);
  return available;
}
function getTargetVersion(dep, selection) {
  if (selection === 0) return dep.wanted;
  if (selection === 1) return dep.latest;
  if (selection === 2) return dep.next;
  return void 0;
}
function computeWidths(rows) {
  let name = 7;
  let current = 7;
  let wanted = 6;
  let latest = 6;
  let next = 7;
  for (const dep of rows) {
    name = Math.max(name, dep.name.length);
    current = Math.max(current, (dep.current ?? "-").length);
    wanted = Math.max(wanted, (dep.wanted ?? "-").length);
    latest = Math.max(latest, (dep.latest ?? "-").length);
    next = Math.max(next, (dep.next ?? "-").length);
  }
  return {
    current,
    latest,
    name,
    next,
    wanted
  };
}
function renderPage(rows, cursor, selections, w, pageSize) {
  const total = rows.length;
  let start = 0;
  if (total > pageSize) {
    start = Math.max(0, Math.min(cursor - Math.floor(pageSize / 2), total - pageSize));
  }
  const end = Math.min(start + pageSize, total);
  const lines = [];
  for (let i = start; i < end; i++) {
    lines.push(renderRow(rows[i], selections[i], i === cursor, w));
  }
  if (total > pageSize) {
    if (start > 0) lines.unshift(chalk16.dim("  \u2191 more"));
    if (end < total) lines.push(chalk16.dim("  \u2193 more"));
  }
  return lines.join("\n");
}
var updoPrompt = createPrompt((config2, done) => {
  const { rows } = config2;
  const [cursor, setCursor] = useState(0);
  const [tick, setTick] = useState(0);
  const availableSelections = useRef(rows.map((r) => getAvailableSelections(r)));
  const selections = useRef(rows.map(() => -1));
  const widths = useRef(computeWidths(rows));
  useKeypress((key) => {
    if (key.name === "escape" || key.ctrl && key.name === "c") {
      done([]);
      return;
    }
    if (isEnterKey(key)) {
      const results = [];
      for (const [i, dep] of rows.entries()) {
        const version = getTargetVersion(dep, selections.current[i]);
        if (version) {
          results.push({
            depTypes: dep.depTypes,
            name: dep.name,
            targetVersion: version,
            workspaces: dep.workspaces
          });
        }
      }
      done(results);
      return;
    }
    if (isUpKey(key)) {
      setCursor(Math.max(0, cursor - 1));
    } else if (isDownKey(key)) {
      setCursor(Math.min(rows.length - 1, cursor + 1));
    } else if (isSpaceKey(key)) {
      const available = availableSelections.current[cursor];
      const currentSel = selections.current[cursor];
      const currentIdx = available.indexOf(currentSel);
      const nextIdx = (currentIdx + 1) % available.length;
      selections.current[cursor] = available[nextIdx];
      setTick(tick + 1);
    }
  });
  const w = widths.current;
  const header = renderHeader(w);
  const page = renderPage(rows, cursor, selections.current, w, 20);
  const selectedCount = selections.current.filter((s) => s >= 0).length;
  const status = chalk16.gray(`  ${selectedCount} selected  \u2191/\u2193 navigate  space cycle version  enter confirm`);
  return `${header}
${page}
${status}`;
});
async function interactiveSelect(deps) {
  const updatable = deps.filter((d) => d.updateAvailable);
  if (updatable.length === 0) {
    console.log(chalk16.green("\nAll packages are up to date!"));
    return [];
  }
  if (!process.stdout.isTTY) {
    console.log(chalk16.yellow("Non-interactive environment detected, skipping selection."));
    return [];
  }
  try {
    return await updoPrompt({ rows: updatable });
  } catch (error) {
    if (error instanceof ExitPromptError) {
      return [];
    }
    throw error;
  }
}

// src/lib/updo/renderTable.ts
import chalk17 from "chalk";
import semver2 from "semver";
function versionColor2(version, current) {
  if (!version || !current) return chalk17.gray(version ?? "-");
  if (version === current) return chalk17.gray(version);
  const diff = semver2.diff(current, version);
  if (diff === "major" || diff === "premajor") return chalk17.red(version);
  if (diff === "minor" || diff === "preminor") return chalk17.yellow(version);
  return chalk17.green(version);
}
var columns = [
  {
    color: (_v, dep) => dep.updateAvailable ? chalk17.white(dep.name) : chalk17.gray(dep.name),
    header: "Package",
    value: (dep) => dep.name
  },
  {
    color: (_v, dep) => chalk17.gray(dep.current ?? "-"),
    header: "Current",
    value: (dep) => dep.current ?? "-"
  },
  {
    color: (_v, dep) => versionColor2(dep.wanted, dep.current),
    header: "Wanted",
    value: (dep) => dep.wanted ?? "-"
  },
  {
    color: (_v, dep) => versionColor2(dep.latest, dep.current),
    header: "Latest",
    value: (dep) => dep.latest ?? "-"
  },
  {
    color: (_v, dep) => versionColor2(dep.next, dep.current),
    header: "Next/RC",
    value: (dep) => dep.next ?? "-"
  },
  {
    color: (_v, dep) => chalk17.gray(dep.depTypes.join(", ")),
    header: "Type",
    value: (dep) => dep.depTypes.join(", ")
  }
];
function renderTable(deps) {
  const updatable = deps.filter((d) => d.updateAvailable);
  if (updatable.length === 0) {
    console.log(chalk17.green("\nAll packages are up to date!"));
    return;
  }
  const widths = columns.map((col) => {
    let maxData = 0;
    for (const dep of updatable) {
      maxData = Math.max(maxData, col.value(dep).length);
    }
    return Math.max(col.header.length, maxData);
  });
  const header = columns.map((col, i) => chalk17.bold(col.header.padEnd(widths[i]))).join("  ");
  console.log(`
${header}`);
  let totalWidth = -2;
  for (const w of widths) {
    totalWidth += w + 2;
  }
  console.log(chalk17.gray("\u2500".repeat(totalWidth)));
  for (const dep of updatable) {
    const row = columns.map((col, i) => {
      const raw = col.value(dep);
      const colored = col.color(raw, dep);
      const padding = widths[i] - raw.length;
      return colored + " ".repeat(Math.max(0, padding));
    }).join("  ");
    console.log(row);
  }
  console.log();
}

// src/lib/updo/resolveVersions.ts
import semver3 from "semver";
function computeWanted(info, ranges) {
  const intersected = ranges.join(" ");
  return semver3.maxSatisfying(info.versions, intersected) ?? void 0;
}
function computePrerelease(info, latest) {
  if (!info) return void 0;
  let best;
  for (const tag of ["next", "rc", "beta"]) {
    const v = info.distTags[tag];
    if (!v) continue;
    if (!best || semver3.gt(v, best)) best = v;
  }
  if (!best) return void 0;
  if (latest && !semver3.gt(best, latest)) return void 0;
  return best;
}
function hasNewerVersion(version, current) {
  return version !== void 0 && semver3.gt(version, current);
}
function isUpdateAvailable(current, wanted, latest, next) {
  if (!current) return false;
  return hasNewerVersion(wanted, current) || hasNewerVersion(latest, current) || hasNewerVersion(next, current);
}
function resolveVersions(deps, registry, installedVersions) {
  const resolved = [];
  for (const [name, dep] of deps) {
    const info = registry.get(name);
    const current = installedVersions.get(name);
    const wanted = info ? computeWanted(info, dep.ranges) : void 0;
    const latest = info?.distTags.latest;
    const next = computePrerelease(info, latest);
    const updateAvailable = isUpdateAvailable(current, wanted, latest, next);
    resolved.push({
      current,
      declaredRange: dep.ranges.length === 1 ? dep.ranges[0] : dep.ranges.join(" | "),
      depTypes: dep.depTypes,
      latest,
      name,
      next,
      updateAvailable,
      wanted: wanted && current && wanted !== current ? wanted : void 0,
      workspaces: dep.workspaces
    });
  }
  return resolved.toSorted((a, b) => {
    if (a.updateAvailable !== b.updateAvailable) return a.updateAvailable ? -1 : 1;
    return a.name.localeCompare(b.name);
  });
}

// src/lib/updo/runUpdo.ts
import chalk18 from "chalk";
async function runUpdo(pm, _options = {}) {
  const cwd = INIT_CWD();
  const workspaces = pm.listWorkspaces();
  const workspaceNames = new Set(workspaces.map((ws) => ws.name));
  console.log(chalk18.gray("Scanning workspace dependencies..."));
  const declaredDeps = collectWorkspaceDeps(cwd, workspaces, workspaceNames);
  console.log(chalk18.gray(`  Found ${declaredDeps.size} unique dependencies across ${workspaces.length} workspaces`));
  console.log(chalk18.gray("Fetching registry info..."));
  const registryInfo = await fetchAllRegistryInfo([...declaredDeps.keys()]);
  console.log(chalk18.gray("Reading installed versions..."));
  const installedVersions = pm.listInstalledVersions();
  const resolved = resolveVersions(declaredDeps, registryInfo, installedVersions);
  const updates = await interactiveSelect(resolved);
  if (updates.length === 0) {
    console.log(chalk18.gray("No updates selected."));
    return 0;
  }
  console.log(chalk18.gray(`
Applying ${updates.length} updates...`));
  const modified = applyUpdates(cwd, workspaces, updates);
  console.log(chalk18.gray(`  Modified ${modified} package.json files`));
  console.log(chalk18.gray("Installing updated dependencies..."));
  return runSteps("Updo", [
    pm.install(),
    pm.dedupe()
  ], true);
}
export {
  CROSS_PLATFORM_NEWLINE,
  DEFAULT_README_BODY,
  DEFAULT_README_TEMPLATE,
  DuplicateDetector,
  INIT_CWD,
  LEGACY_COMMANDS_PREFIX,
  WINDOWS_NEWLINE_REGEX,
  XYLABS_COMMANDS_PREFIX,
  XYLABS_RULES_PREFIX,
  XYLABS_SKILLS_PREFIX,
  applyLogoConfig,
  applyPackageManager,
  applyUpdates,
  checkResult,
  claudeCommandTemplates,
  claudeMdLocalTemplate,
  claudeMdProjectTemplate,
  claudeMdRuleTemplates,
  claudeSkillTemplates,
  collectWorkspaceDeps,
  createBuildConfig,
  defaultBuildConfig,
  defaultReadFileSyncOptions,
  deleteGlob,
  deprecationMigrate,
  detectDuplicateDependencies,
  detectWorkspaceCycles,
  empty,
  ensurePackageManagerInstalled,
  fetchAllRegistryInfo,
  fetchRegistryInfo,
  fillTemplate,
  generateIgnoreFiles,
  generateReadmeFiles,
  getGitConfig,
  getGitConfigBool,
  getPackageManagerInstallPlan,
  gitignoreTemplate,
  installOutputCapture,
  interactiveSelect,
  isPackageManagerInstalled,
  isYarnVersionOrGreater,
  latestVersions,
  listRepoTemplates,
  loadConfig,
  loadRepoTemplateFiles,
  loadWorkspaceCommandConfig,
  multiLineToJSONArray,
  notEmpty,
  outputStorage,
  packageName,
  parsedPackageJSON,
  printWorkspaceCycles,
  processEx,
  readLines,
  readNonEmptyLines,
  renderTable,
  resolveTemplatePath,
  resolveVersions,
  runInstall,
  runStepAsync,
  runSteps,
  runStepsAsync,
  runUpdo,
  runWithConcurrency,
  runXy,
  runXyWithWarning,
  safeExit,
  safeExitAsync,
  scaffoldTemplate,
  setGitConfig,
  spawnPackageManagerSync,
  tryReadFileSync,
  tryRunLocalScript,
  union,
  withErrnoException,
  withError,
  writeLines,
  yarnWorkspace,
  yarnWorkspaces
};
//# sourceMappingURL=index.mjs.map