"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var solution_builder_exports = {};
__export(solution_builder_exports, {
  createSolutionBuilderContext: () => createSolutionBuilderContext
});
module.exports = __toCommonJS(solution_builder_exports);
var import_node_fs = require("node:fs");
var import_node_path = require("node:path");
var import_typescript = require("typescript");
var import_error = require("../error.js");
var import_context = require("./context.js");
/**
 * @license
 * Copyright 2022-2026 Greg Lauckhart <greg@lauckhart.com>
 * SPDX-License-Identifier: Apache-2.0
 */
const BUILD_DIAGNOSTICS = false;
async function createSolutionBuilderContext(workspace, graph) {
  let diagnostics;
  const host = (0, import_typescript.createSolutionBuilderHost)();
  host.reportDiagnostic = (diagnostic) => (diagnostics ??= []).push(diagnostic);
  let context;
  function currentContext() {
    if (context === void 0) {
      throw new Error("Build context accessed with no context");
    }
    return context;
  }
  instrumentHostWithInterceptors(host, currentContext, graph);
  const builder = (0, import_typescript.createSolutionBuilder)(host, [workspace.resolve("tsconfig.json")], {});
  import_context.TypescriptContext.diagnose(diagnostics);
  return {
    async build(pkg, path, refreshCallback, _emit) {
      context = {
        refreshCallback
      };
      if (path === "src" && pkg.isLibrary && pkg.supportsEsm && pkg.supportsCjs) {
        const esmDeclIdentifier = new RegExp(
          `^(${pkg.resolve("dist").replace(/[\\/]/g, "[\\/]")}[\\/](?:.*))esm([\\/].*(?:\\.d\\.ts|\\.d\\.ts\\.map))$`
        );
        context.fileWrite = (writeFile, filename, contents, writeBom) => {
          const match = filename.match(esmDeclIdentifier);
          if (!match) {
            return;
          }
          writeFile(`${match[1]}cjs${match[2]}`, contents, writeBom);
        };
      }
      try {
        const status = builder.build(pkg.resolve((0, import_node_path.join)(path, "tsconfig.json")));
        import_context.TypescriptContext.diagnose(diagnostics);
        switch (status) {
          case void 0:
          case import_typescript.ExitStatus.Success:
            break;
          case import_typescript.ExitStatus.InvalidProject_OutputsSkipped:
            throw new import_error.BuildError(
              `Typescript does not think ${path} is part of the project, this is probably a build tooling error`
            );
          case import_typescript.ExitStatus.ProjectReferenceCycle_OutputsSkipped:
            throw new import_error.BuildError(
              `Typescript identified a cyclical project reference in ${path}, please check package dependencies`
            );
          default:
            throw new import_error.InternalBuildError(`Build error ${import_typescript.ExitStatus[status]} without diagnostics`);
        }
      } finally {
        context = void 0;
      }
    }
  };
}
function instrumentHostWithInterceptors(host, currentContext, graph) {
  const moduleIdentifier = graph ? new RegExp(`^(${graph.nodes.map((node) => node.pkg.path).join("|")})[\\/]dist[\\/](?:esm|cjs)/(.*).d.ts$`) : void 0;
  const writeFile = host.writeFile ?? import_typescript.sys.writeFile;
  host.writeFile = (path, data, writeBom) => {
    const context = currentContext();
    context.refreshCallback();
    writeFile(path, data, writeBom);
    context.fileWrite?.(writeFile, path, data, writeBom);
  };
  let resolveModuleNameLiterals;
  const resolveModuleNameLiteralsInterceptor = (...args) => {
    currentContext().refreshCallback();
    const result = resolveModuleNameLiterals(...args);
    if (!BUILD_DIAGNOSTICS) {
      return result;
    }
    for (const entry of result) {
      const filename = entry.resolvedModule?.resolvedFileName;
      const match = moduleIdentifier && filename?.match(moduleIdentifier);
      if (match) {
        const sourceFilename = `${match[1]}/src/${match[2]}.ts`;
        if ((0, import_node_fs.existsSync)(sourceFilename)) {
          console.warn(".d.ts reference", sourceFilename);
        }
      }
    }
    return result;
  };
  const createProgram = host.createProgram;
  host.createProgram = (...args) => {
    const compilerHost = args[2];
    if (compilerHost && compilerHost.resolveModuleNameLiterals !== resolveModuleNameLiteralsInterceptor) {
      resolveModuleNameLiterals = compilerHost.resolveModuleNameLiterals;
      compilerHost.resolveModuleNameLiterals = resolveModuleNameLiteralsInterceptor;
    }
    const result = createProgram(...args);
    const getCompilerOptions = result.getCompilerOptions;
    result.getCompilerOptions = (...args2) => {
      currentContext().refreshCallback();
      return getCompilerOptions(...args2);
    };
    return result;
  };
}
//# sourceMappingURL=solution-builder.js.map
