// 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/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/fillTemplate.ts
function fillTemplate(template, data) {
  return template.replaceAll(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] ?? "");
}

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

// src/lib/generateReadmeFiles.ts
import { execFile } from "child_process";
import FS, { readFileSync as readFileSync2 } from "fs";
import {
  mkdir,
  readFile,
  writeFile
} from "fs/promises";
import { createRequire } from "module";
import PATH2 from "path";
import { createInterface } from "readline";
import { promisify } from "util";
import chalk from "chalk";
var execFileAsync = promisify(execFile);
var require2 = createRequire(import.meta.url);
var packageRoot = PATH2.dirname(require2.resolve("@xylabs/toolchain/package.json"));
var readmeTemplatesDir = PATH2.resolve(packageRoot, "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 = PATH2.join(packageLocation, ".temp-typedoc");
  try {
    if (!FS.existsSync(tempDir)) {
      FS.mkdirSync(tempDir, { recursive: true });
    }
    const typedocConfig = {
      disableSources: true,
      entryPointStrategy: "expand",
      entryPoints: entryPoints.map((ep) => PATH2.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 = PATH2.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 = PATH2.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(PATH2.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(PATH2.join(dir, item.name), level + 1);
    }
  } catch {
  }
  return content;
}
function askConfirmation(question) {
  const rl = createInterface({ 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 = readFileSync2(PATH2.resolve(readmeTemplatesDir, "README.template.md"), "utf8");
var DEFAULT_README_BODY = readFileSync2(PATH2.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 ?? PATH2.join(cwd, ".xy", "README.template.md");
}
async function loadOrCreateTemplate(resolvedTemplatePath) {
  try {
    const template = await readFile(resolvedTemplatePath, "utf8");
    return { created: false, template };
  } catch {
    console.log(chalk.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 = PATH2.dirname(resolvedTemplatePath);
  await mkdir(xyDir, { recursive: true });
  await writeFile(resolvedTemplatePath, template);
  console.log(chalk.green(`Created template: ${resolvedTemplatePath}`));
  const bodyPath = PATH2.join(xyDir, "README.body.md");
  await writeFile(bodyPath, DEFAULT_README_BODY);
  console.log(chalk.green(`Created body template: ${bodyPath}`));
}
async function resolveBody(location, defaultBody) {
  const localBodyPath = PATH2.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 = PATH2.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(PATH2.join(location, "README.md"), readmeContent);
    if (verbose) console.log(chalk.green(`  ${name}`));
    return true;
  } catch (ex) {
    const error = ex;
    console.warn(chalk.yellow(`  Skipped ${location}: ${error.message}`));
    return false;
  }
}
async function loadDefaultBody(resolvedTemplatePath) {
  const xyBodyPath = PATH2.join(PATH2.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(chalk.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(chalk.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(chalk.blue(`Generated ${workspaces.length} README(s) in ${ms.toFixed(0)}ms`));
  return failed ? 1 : 0;
}

// src/lib/loadConfig.ts
import chalk2 from "chalk";
import { cosmiconfig } from "cosmiconfig";
import { TypeScriptLoader } from "cosmiconfig-typescript-loader";
import deepmerge from "deepmerge";
var config;
var rootConfigPath;
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(chalk2.green(`Loaded config from ${configFilePath}`));
      if (config.verbose) {
        console.log(chalk2.gray(`${JSON.stringify(config, null, 2)}`));
      }
    }
  }
  return deepmerge(config, params ?? {});
};

// src/actions/readme-gen.ts
async function readmeGen({
  jobs,
  pkg,
  templatePath,
  typedoc,
  verbose
}) {
  const config2 = await loadConfig();
  return await generateReadmeFiles({
    jobs,
    logoLinkUrl: config2.readme?.logoLinkUrl,
    logoUrl: config2.readme?.logoUrl,
    pkg,
    templatePath,
    typedoc,
    verbose
  });
}
export {
  readmeGen
};
//# sourceMappingURL=readme-gen.mjs.map