/**
 * @license
 * Copyright 2022-2026 Greg Lauckhart <greg@lauckhart.com>
 * SPDX-License-Identifier: Apache-2.0
 */
import { spawn } from "node:child_process";
import { cp } from "node:fs/promises";
import { join, resolve } from "path";
import { isDirectory } from "../../util/file.js";
import { Package } from "../../util/package.js";
import { BuildError } from "../error.js";
function tsgoBin(_workspace) {
  return Package.tools.findPackage("@typescript/native-preview").resolve("bin/tsgo.js");
}
function createTsgoContext(workspace) {
  const bin = tsgoBin(workspace);
  return {
    async build(pkg, path, _refreshCallback, _emit) {
      const args = [bin, "--project", pkg.resolve(join(path, "tsconfig.json"))];
      await new Promise((resolve2, reject) => {
        const tsgo = spawn(process.execPath, args, { stdio: "inherit" });
        tsgo.on("exit", (code, signal) => {
          switch (code) {
            case 0:
              resolve2();
              break;
            case 1:
            // Diagnostics present, outputs generated
            case 2:
            // Diagnostics present, outputs skipped
            case 3:
            // Project invalid
            case 4:
            // Reference cycle
            case 5:
              reject(new BuildError());
              break;
            case null:
              reject(new BuildError(`tsgo exited with signal ${signal}`));
              break;
            default:
              reject(new BuildError(`tsgo exited with code ${code}`));
              break;
          }
        });
      });
      if (path !== "test") {
        await copyDeclarationsToCjs(pkg);
      }
    }
  };
}
async function copyDeclarationsToCjs(pkg) {
  await cp(pkg.resolve("dist/esm"), pkg.resolve("dist/cjs"), {
    recursive: true,
    filter(src) {
      if (isDirectory(src)) {
        return true;
      }
      return src.endsWith(".d.ts") || src.endsWith(".d.ts.map");
    }
  });
}
async function tsgoSolutionBuild(workspace, tsconfigPath) {
  const bin = tsgoBin(workspace);
  const args = [bin, "-b", tsconfigPath];
  const workspacePath = workspace.path;
  const { code, stdout } = await new Promise((resolve2, reject) => {
    const chunks = Array();
    const tsgo = spawn(process.execPath, args, { stdio: ["ignore", "pipe", "inherit"] });
    tsgo.stdout.on("data", (chunk) => chunks.push(chunk));
    tsgo.on("error", reject);
    tsgo.on("exit", (code2, signal) => {
      if (code2 === null) {
        reject(new BuildError(`tsgo exited with signal ${signal}`));
        return;
      }
      resolve2({ code: code2, stdout: Buffer.concat(chunks).toString("utf-8") });
    });
  });
  if (code >= 3) {
    throw new BuildError(stdout || `tsgo -b exited with code ${code}`);
  }
  const errorsByPackage = /* @__PURE__ */ new Map();
  if (code !== 0 && stdout) {
    for (const line of stdout.split("\n")) {
      const match = line.match(/^(.+?)\(\d+,\d+\):/);
      if (!match) {
        continue;
      }
      const filePath = resolve(match[1]);
      const relative = filePath.startsWith(workspacePath + "/") ? filePath.slice(workspacePath.length + 1) : void 0;
      if (relative === void 0) {
        continue;
      }
      const parts = relative.split("/");
      if (parts.length < 3) {
        continue;
      }
      const pkgDir = `${parts[0]}/${parts[1]}`;
      const pkgPath = join(workspacePath, pkgDir);
      const existing = errorsByPackage.get(pkgPath);
      errorsByPackage.set(pkgPath, existing ? `${existing}
${line}` : line);
    }
  }
  return { ok: code === 0, outputsSkipped: code === 2, errorsByPackage, rawOutput: stdout };
}
export {
  copyDeclarationsToCjs,
  createTsgoContext,
  tsgoSolutionBuild
};
//# sourceMappingURL=tsgo.js.map
