import { findAppRoot } from "./appResolver.js";
import { registerEntityIds } from "../encryption/entityIds.js";
import {
  ensureMikroOrmV7GeneratedCacheCompatibility,
  recoverMikroOrmV7GeneratedCacheFromImportError
} from "./generatedCacheRecovery.js";
import path from "node:path";
import fs from "node:fs";
import { pathToFileURL } from "node:url";
async function compileAndImport(tsPath, allowRecovery = true) {
  const jsPath = tsPath.replace(/\.ts$/, ".mjs");
  const appRoot = path.dirname(path.dirname(path.dirname(tsPath)));
  const tsExists = fs.existsSync(tsPath);
  const jsExists = fs.existsSync(jsPath);
  if (!tsExists) {
    throw new Error(`Generated file not found: ${tsPath}`);
  }
  const needsCompile = !jsExists || fs.statSync(tsPath).mtimeMs > fs.statSync(jsPath).mtimeMs;
  if (needsCompile) {
    const esbuild = await import("esbuild");
    const aliasPlugin = {
      name: "alias-resolver",
      setup(build) {
        build.onResolve({ filter: /^@\// }, (args) => {
          const resolved = path.join(appRoot, args.path.slice(2));
          if (!fs.existsSync(resolved) && fs.existsSync(resolved + ".ts")) {
            return { path: resolved + ".ts" };
          }
          if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory() && fs.existsSync(path.join(resolved, "index.ts"))) {
            return { path: path.join(resolved, "index.ts") };
          }
          return { path: resolved };
        });
      }
    };
    const externalNonJsonPlugin = {
      name: "external-non-json",
      setup(build) {
        build.onResolve({ filter: /^[^./]/ }, (args) => {
          if (/^[a-zA-Z]:/.test(args.path)) {
            return null;
          }
          if (args.path.endsWith(".json")) {
            return null;
          }
          return { path: args.path, external: true };
        });
      }
    };
    await esbuild.build({
      entryPoints: [tsPath],
      outfile: jsPath,
      bundle: true,
      format: "esm",
      platform: "node",
      target: "node18",
      plugins: [aliasPlugin, externalNonJsonPlugin],
      // Allow JSON imports
      loader: { ".json": "json" }
    });
  }
  try {
    const fileUrl = `${pathToFileURL(jsPath).href}?mtime=${fs.statSync(jsPath).mtimeMs}`;
    return await import(fileUrl);
  } catch (error) {
    if (!allowRecovery) {
      throw error;
    }
    const recovered = recoverMikroOrmV7GeneratedCacheFromImportError(appRoot, error);
    if (!recovered.applied) {
      throw error;
    }
    return compileAndImport(tsPath, false);
  }
}
async function loadBootstrapData(appRoot) {
  const resolved = appRoot ? {
    generatedDir: path.join(appRoot, ".mercato", "generated"),
    appDir: appRoot,
    mercatoDir: path.join(appRoot, ".mercato")
  } : findAppRoot();
  if (!resolved) {
    throw new Error(
      'Could not find app root with .mercato/generated directory. Make sure you run this command from within a Next.js app directory, or run "yarn mercato generate" first to create the generated files.'
    );
  }
  const { generatedDir } = resolved;
  ensureMikroOrmV7GeneratedCacheCompatibility(resolved.appDir);
  const entityIdsModule = await compileAndImport(path.join(generatedDir, "entities.ids.generated.ts"));
  registerEntityIds(entityIdsModule.E);
  const [
    modulesModule,
    entitiesModule,
    diModule,
    searchModule,
    commandLoadersModule,
    commandInterceptorsModule,
    workflowsModule
  ] = await Promise.all([
    compileAndImport(path.join(generatedDir, "modules.cli.generated.ts")),
    compileAndImport(path.join(generatedDir, "entities.generated.ts")),
    compileAndImport(path.join(generatedDir, "di.generated.ts")),
    compileAndImport(path.join(generatedDir, "search.generated.ts")).catch(() => ({ searchModuleConfigs: [] })),
    compileAndImport(path.join(generatedDir, "command-loaders.generated.ts")).catch(() => ({ commandLoaderEntries: [] })),
    compileAndImport(path.join(generatedDir, "command-interceptors.generated.ts")).catch(() => ({ commandInterceptorEntries: [] })),
    compileAndImport(path.join(generatedDir, "workflows.generated.ts")).catch(() => ({ allCodeWorkflows: [] }))
  ]);
  return {
    modules: modulesModule.modules,
    entities: entitiesModule.entities,
    diRegistrars: diModule.diRegistrars,
    entityIds: entityIdsModule.E,
    // Search configs are needed by workers for indexing
    searchModuleConfigs: searchModule.searchModuleConfigs ?? [],
    commandLoaderEntries: commandLoadersModule.commandLoaderEntries ?? [],
    // Command interceptors must apply in worker/CLI processes too — the
    // interceptor registry is per-process, so relying on the Next.js runtime's
    // registration silently no-ops every interceptor for queued/CLI commands
    // (#4327).
    commandInterceptorEntries: commandInterceptorsModule.commandInterceptorEntries ?? [],
    // Code workflow definitions are needed by workers to resume code-defined instances
    codeWorkflows: workflowsModule.allCodeWorkflows ?? [],
    // Empty UI-related data - not needed for CLI
    dashboardWidgetEntries: [],
    injectionWidgetEntries: [],
    injectionTables: [],
    interceptorEntries: [],
    componentOverrideEntries: []
  };
}
async function bootstrapFromAppRoot(appRoot) {
  const { createBootstrap, waitForAsyncRegistration } = await import("./factory.js");
  const data = await loadBootstrapData(appRoot);
  const bootstrap = createBootstrap(data);
  bootstrap();
  await waitForAsyncRegistration();
  return data;
}
export {
  bootstrapFromAppRoot,
  loadBootstrapData
};
//# sourceMappingURL=dynamicLoader.js.map
