// src/actions/package/compile/compile.ts
import { cwd as cwd4 } from "process";
import chalk6 from "chalk";

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

// src/actions/package/compile/packageCompileTsup.ts
import chalk5 from "chalk";
import { build, defineConfig } from "tsup";

// src/actions/package/compile/inputs.ts
import chalk2 from "chalk";
import { glob } from "glob";
var getAllInputs = (srcDir, verbose = false) => {
  return [...glob.sync(`${srcDir}/**/*.ts`, { posix: true }).map((file) => {
    const result = file.slice(Math.max(0, srcDir.length + 1));
    if (verbose) {
      console.log(chalk2.gray(`getAllInputs: ${JSON.stringify(result, null, 2)}`));
    }
    return result;
  }), ...glob.sync(`${srcDir}/**/*.tsx`, { posix: true }).map((file) => {
    const result = file.slice(Math.max(0, srcDir.length + 1));
    if (verbose) {
      console.log(chalk2.gray(`getAllInputs: ${JSON.stringify(result, null, 2)}`));
    }
    return result;
  })];
};

// src/actions/package/compile/buildEntries.ts
var isSpecOrStory = (entry) => {
  return entry.includes(".spec.") || entry.includes(".stories.") || entry.startsWith("spec/") || entry.includes("/spec/") || entry.startsWith("stories/") || entry.includes("/stories/") || entry === "spec.ts" || entry.endsWith("/spec.ts") || entry === "stories.ts" || entry.endsWith("/stories.ts");
};
var buildEntries = (srcDir, entryMode = "single", options, excludeSpecAndStories = true, verbose = false) => {
  let entries;
  switch (entryMode) {
    case "platform": {
      entries = ["index-node.ts", "index-browser.ts"];
      break;
    }
    case "all": {
      entries = (excludeSpecAndStories ? getAllInputs(srcDir).filter((entry) => !isSpecOrStory(entry)) : getAllInputs(srcDir)).filter((entry) => !entry.endsWith(".d.ts"));
      break;
    }
    case "custom": {
      entries = [];
      break;
    }
    default: {
      entries = ["index.ts"];
      break;
    }
  }
  if (typeof options !== "boolean" && Array.isArray(options?.entry)) {
    entries.push(...options.entry);
  }
  if (verbose) console.log(`buildEntries [${entryMode}] ${entries.length}`);
  return entries;
};

// src/actions/package/compile/deepMerge.ts
function deepMerge(target, source) {
  if (!source || typeof source !== "object") return target;
  for (const key of Object.keys(source)) {
    const sourceVal = source[key];
    if (typeof sourceVal === "object" && sourceVal !== null && !Array.isArray(sourceVal)) {
      if (!target[key] || typeof target[key] !== "object") {
        target[key] = {};
      }
      deepMerge(target[key], sourceVal);
    } else {
      target[key] = sourceVal;
    }
  }
  return target;
}
function deepMergeObjects(objects) {
  const result = {};
  for (const obj of objects) {
    deepMerge(result, obj);
  }
  return result;
}

// src/actions/package/compile/packageCompileTsc.ts
import { cwd as cwd2 } from "process";
import chalk3 from "chalk";
import { createProgramFromConfig } from "tsc-prog";
import ts, {
  DiagnosticCategory,
  formatDiagnosticsWithColorAndContext,
  getPreEmitDiagnostics,
  sys
} from "typescript";

// src/actions/package/compile/getCompilerOptions.ts
import { cwd } from "process";
import deepmerge2 from "deepmerge";
import { getTsconfig } from "get-tsconfig";
var getCompilerOptions = (options = {}, fileName = "tsconfig.json") => {
  const resolvedTsConfigCompilerOptions = getTsconfig(cwd(), fileName)?.config?.compilerOptions ?? {};
  return deepmerge2(resolvedTsConfigCompilerOptions, options);
};

// src/actions/package/compile/packageCompileTsc.ts
var packageCompileTsc = (platform, entries, srcDir = "src", outDir = "dist", compilerOptionsParam, verbose = false) => {
  const pkg = cwd2();
  if (verbose) {
    console.log(chalk3.cyan(`Validating code START: ${entries.length} files to ${outDir} from ${srcDir}`));
  }
  const configFilePath = ts.findConfigFile(
    pkg,
    (fileName) => ts.sys.fileExists(fileName),
    "tsconfig.json"
  );
  if (configFilePath === void 0) {
    throw new Error("Could not find tsconfig.json");
  }
  const compilerOptions = {
    ...getCompilerOptions({
      removeComments: false,
      skipDefaultLibCheck: true,
      skipLibCheck: true,
      sourceMap: false
    }),
    ...compilerOptionsParam,
    outDir: `${outDir}/${platform}`,
    emitDeclarationOnly: true,
    noEmit: false
  };
  console.log(chalk3.cyan(`Validating Files: ${entries.length}`));
  if (verbose) {
    for (const entry of entries) {
      console.log(chalk3.grey(`Validating: ${entry}`));
    }
  }
  try {
    if (entries.length > 0) {
      const program = createProgramFromConfig({
        configFilePath,
        basePath: pkg,
        compilerOptions,
        files: entries.map((entry) => `${srcDir}/${entry}`),
        include: [`${srcDir}/**/*.*`]
      });
      const diagnostics = getPreEmitDiagnostics(program);
      if (diagnostics.length > 0) {
        const formattedDiagnostics = formatDiagnosticsWithColorAndContext(
          diagnostics,
          {
            getCanonicalFileName: (fileName) => fileName,
            getCurrentDirectory: () => srcDir,
            getNewLine: () => sys.newLine
          }
        );
        console.error(formattedDiagnostics);
      }
      const nonEmitPatterns = [".stories.", "/stories/", "/stories.", ".spec.", "/spec/", "/spec.", ".example."];
      program.emit(void 0, (fileName, text, writeByteOrderMark) => {
        if (nonEmitPatterns.some((pattern) => fileName.includes(pattern))) {
          return;
        }
        ts.sys.writeFile(fileName, text, writeByteOrderMark);
      });
      return diagnostics.reduce((acc, diag) => acc + (diag.category === DiagnosticCategory.Error ? 1 : 0), 0);
    }
    return 0;
  } finally {
    if (verbose) {
      console.log(chalk3.cyan(`Validating code FINISH: ${entries.length} files to ${outDir} from ${srcDir}`));
    }
  }
};

// src/actions/package/compile/packageCompileTscTypes.ts
import path from "path";
import { cwd as cwd3 } from "process";
import chalk4 from "chalk";
import { rollup } from "rollup";
import dts from "rollup-plugin-dts";
import nodeExternals from "rollup-plugin-node-externals";
var ignoredWarningCodes = /* @__PURE__ */ new Set(["EMPTY_BUNDLE", "UNRESOLVED_IMPORT"]);
async function bundleDts(inputPath, outputPath, platform, options, verbose = false) {
  const pkg = cwd3();
  const tsconfigPath = path.resolve(pkg, "tsconfig.json");
  const nodePlugIns = platform === "node" ? [nodeExternals()] : [];
  try {
    const bundle = await rollup({
      input: inputPath,
      plugins: [dts({
        ...options,
        tsconfig: tsconfigPath,
        compilerOptions: {
          emitDeclarationOnly: true,
          noEmit: false,
          declarationMap: true
        }
      }), ...nodePlugIns],
      onwarn(warning, warn) {
        if (ignoredWarningCodes.has(warning.code ?? "")) {
          return;
        }
        console.warn(chalk4.yellow(`[${warning.code}] ${warning.message}`));
        console.warn(chalk4.gray(inputPath));
        warn(warning);
      }
    });
    await bundle.write({
      file: outputPath,
      format: "es"
    });
  } catch (ex) {
    const error = ex;
    console.warn(chalk4.red(error));
    console.warn(chalk4.gray(inputPath));
  }
  if (verbose) {
    console.log(`Bundled declarations written to ${outputPath}`);
  }
}
var packageCompileTscTypes = async (entries, outDir, platform, srcDir = "build", verbose = false) => {
  if (verbose) {
    console.log(chalk4.cyan(`Compiling Types START [${platform}]: ${entries.length} files to ${outDir} from ${srcDir}`));
    console.log(`Entries: ${entries.join(", ")}`);
  }
  const pkg = cwd3();
  const srcRoot = `${pkg}/${srcDir}/${platform}`;
  const entryNameToTypeName = (entry) => {
    const splitEntryName = entry.split(".");
    const newEntryExtension = "d." + splitEntryName.at(-1);
    return [...splitEntryName.slice(0, -1), newEntryExtension].join(".");
  };
  const compilerOptions = getCompilerOptions({
    removeComments: false,
    skipDefaultLibCheck: true,
    skipLibCheck: true,
    declarationMap: true,
    emitDeclarationOnly: true,
    noEmit: true
  });
  const entryNames = entries.map((entry) => entry.split(`${srcDir}/`).at(-1) ?? entry);
  await Promise.all(entryNames.map(async (entryName) => {
    const entryTypeName = entryNameToTypeName(entryName);
    await bundleDts(`${srcRoot}/${entryTypeName}`, `${outDir}/${entryTypeName}`, platform, { compilerOptions }, verbose);
  }));
  if (verbose) {
    console.log(chalk4.cyan(`Compiling Types FINISH: ${entries.length} files to ${outDir} from ${srcDir}`));
  }
  return 0;
};

// src/actions/package/compile/packageCompileTsup.ts
var compileFolder = async (srcDir, entries, buildDir, options, bundleTypes = false, verbose) => {
  const outDir = options?.outDir ?? "dist";
  if (verbose) {
    console.log(`compileFolder [${srcDir}, ${options?.outDir}]`);
  }
  if (entries.length === 0) {
    console.warn(chalk5.yellow(`No entries found in ${srcDir} to compile`));
    return 0;
  }
  if (verbose) {
    console.log(chalk5.gray(`buildDir [${buildDir}]`));
  }
  const validationResult = packageCompileTsc(options?.platform ?? "neutral", entries, srcDir, buildDir, void 0, verbose);
  if (validationResult !== 0) {
    console.error(chalk5.red(`Compile:Validation had ${validationResult} errors`));
    return validationResult;
  }
  const optionsParams = tsupOptions([{
    bundle: true,
    cjsInterop: true,
    clean: false,
    dts: false,
    format: ["esm"],
    outDir,
    silent: true,
    sourcemap: true,
    splitting: false,
    tsconfig: "tsconfig.json",
    ...options,
    entry: entries.map((entry) => `${srcDir}/${entry}`)
  }]);
  const optionsResult = defineConfig(optionsParams);
  const optionsList = (await Promise.all(
    (Array.isArray(optionsResult) ? optionsResult : [optionsResult]).flatMap(async (options2) => {
      const result = typeof options2 === "function" ? await options2({}) : [options2];
      return Array.isArray(result) ? result : [result];
    })
  )).flat();
  if (verbose) {
    console.log(chalk5.cyan(`TSUP:build:start [${srcDir}]`));
    console.log(chalk5.gray(`TSUP:build:options [${JSON.stringify(optionsList, null, 2)}]`));
  }
  await Promise.all(optionsList.map((options2) => build(options2)));
  if (verbose) {
    console.log(chalk5.cyan(`TSUP:build:stop [${srcDir}]`));
  }
  if (bundleTypes) {
    await packageCompileTscTypes(entries, outDir, options?.platform ?? "neutral", buildDir, verbose);
  }
  return 0;
};
var resolvePlatformRecord = (value) => {
  if (value === void 0 || value === true) return { src: {} };
  if (value === false) return {};
  return value;
};
var resolvePlatformEsbuildOptions = (value) => {
  if (typeof value !== "object" || value === null) return {};
  const entry = value.esbuildOptions;
  return entry ?? {};
};
var tsupOptions = (options = []) => {
  const standardLoaders = {
    ".gif": "copy",
    ".html": "copy",
    ".jpg": "copy",
    ".json": "json",
    ".png": "copy",
    ".svg": "text",
    ".webp": "copy"
  };
  const standardOptions = {
    bundle: true,
    format: ["esm"],
    loader: standardLoaders,
    outExtension: ({ format }) => format === "esm" ? { js: ".mjs" } : { js: ".cjs" },
    skipNodeModulesBundle: true,
    sourcemap: true,
    target: "esnext"
  };
  return deepMergeObjects([standardOptions, ...options]);
};
var packageCompileTsup = async (config2) => {
  const compile = config2?.compile;
  const verbose = config2?.verbose ?? false;
  const outDirAsBuildDir = compile?.outDirAsBuildDir ?? true;
  const bundleTypes = compile?.bundleTypes ?? false;
  if (verbose) {
    console.log("Compiling with TSUP");
  }
  const compileForNode = resolvePlatformRecord(compile?.node);
  const compileForBrowser = resolvePlatformRecord(compile?.browser);
  const compileForNeutral = resolvePlatformRecord(compile?.neutral);
  const nodeEsbuild = resolvePlatformEsbuildOptions(compile?.node);
  const browserEsbuild = resolvePlatformEsbuildOptions(compile?.browser);
  const neutralEsbuild = resolvePlatformEsbuildOptions(compile?.neutral);
  const compilePlatform = async (platform, entries, platformEsbuild) => {
    const results = await Promise.all(
      Object.entries(entries).map(async ([srcDir, options]) => {
        const rootOutDir = options.outDir ?? "dist";
        const outDir = `${rootOutDir}/${platform}`;
        const entry = buildEntries(srcDir, compile?.entryMode, options, true, verbose);
        return compileFolder(
          srcDir,
          entry,
          outDirAsBuildDir ? rootOutDir : "build",
          tsupOptions([
            platformEsbuild,
            compile?.tsup?.options ?? {},
            options,
            { platform, outDir }
          ]),
          bundleTypes,
          verbose
        );
      })
    );
    return results.reduce((prev, value) => prev + value, 0);
  };
  const [nodeErrors, browserErrors, neutralErrors] = await Promise.all([
    compilePlatform("node", compileForNode, nodeEsbuild),
    compilePlatform("browser", compileForBrowser, browserEsbuild),
    compilePlatform("neutral", compileForNeutral, neutralEsbuild)
  ]);
  return nodeErrors + browserErrors + neutralErrors;
};

// src/actions/package/compile/compile.ts
var packageCompile = async (inConfig = {}) => {
  const pkg = cwd4();
  console.log(chalk6.green(`Compiling ${pkg}`));
  const config2 = await loadConfig(inConfig);
  return await packageCompileTsup(config2);
};
export {
  packageCompile
};
//# sourceMappingURL=compile.mjs.map