var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value;
var __spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (__hasOwnProp.call(b, prop))
      __defNormalProp(a, prop, b[prop]);
  if (__getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(b)) {
      if (__propIsEnum.call(b, prop))
        __defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
import {rollupPluginHTML} from "@web/rollup-plugin-html";
import fs from "fs";
import {bold, cyan, green} from "kleur/colors";
import {performance} from "perf_hooks";
import vite from "../vite.js";
import {fileURLToPath} from "url";
import {createVite} from "../create-vite.js";
import {pad} from "../dev/util.js";
import {debug, defaultLogOptions, levels, timerMessage, warn} from "../logger.js";
import {ssr} from "../ssr/index.js";
import {generatePaginateFunction} from "../ssr/paginate.js";
import {createRouteManifest, validateGetStaticPathsModule, validateGetStaticPathsResult} from "../ssr/routing.js";
import {generateRssFunction} from "../ssr/rss.js";
import {generateSitemap} from "../ssr/sitemap.js";
import {kb, profileHTML, profileJS} from "./stats.js";
async function build(config, options = {logging: defaultLogOptions}) {
  const builder = new AstroBuilder(config, options);
  await builder.build();
}
class AstroBuilder {
  constructor(config, options) {
    this.mode = "production";
    this.routeCache = {};
    if (!config.buildOptions.site && config.buildOptions.sitemap !== false) {
      warn(options.logging, "config", `Set "buildOptions.site" to generate correct canonical URLs and sitemap`);
    }
    if (options.mode)
      this.mode = options.mode;
    this.config = config;
    const port = config.devOptions.port;
    this.logging = options.logging;
    this.origin = config.buildOptions.site ? new URL(config.buildOptions.site).origin : `http://localhost:${port}`;
    this.manifest = createRouteManifest({config});
  }
  async build() {
    const {logging, origin} = this;
    const timer = {viteStart: performance.now()};
    const viteConfig = await createVite(__spreadValues({
      mode: this.mode,
      server: {
        hmr: {overlay: false},
        middlewareMode: "ssr"
      }
    }, this.config.vite || {}), {astroConfig: this.config, logging});
    const viteServer = await vite.createServer(viteConfig);
    this.viteServer = viteServer;
    debug(logging, "build", timerMessage("Vite started", timer.viteStart));
    timer.renderStart = performance.now();
    const assets = {};
    const allPages = {};
    await Promise.all(this.manifest.routes.map(async (route) => {
      var _a;
      if (route.pathname) {
        allPages[route.component] = __spreadProps(__spreadValues({}, route), {paths: [route.pathname]});
        return;
      }
      const result = await this.getStaticPathsForRoute(route);
      if ((_a = result.rss) == null ? void 0 : _a.xml) {
        const rssFile = new URL(result.rss.url.replace(/^\/?/, "./"), this.config.dist);
        if (assets[fileURLToPath(rssFile)]) {
          throw new Error(`[getStaticPaths] RSS feed ${result.rss.url} already exists.
Use \`rss(data, {url: '...'})\` to choose a unique, custom URL. (${route.component})`);
        }
        assets[fileURLToPath(rssFile)] = result.rss.xml;
      }
      allPages[route.component] = __spreadProps(__spreadValues({}, route), {paths: result.paths});
    }));
    const input = [];
    await Promise.all(Object.entries(allPages).map(([component, route]) => Promise.all(route.paths.map(async (pathname) => {
      input.push({
        html: await ssr({
          astroConfig: this.config,
          filePath: new URL(`./${component}`, this.config.projectRoot),
          logging,
          mode: "production",
          origin,
          pathname,
          route,
          routeCache: this.routeCache,
          viteServer
        }),
        name: pathname.replace(/\/?$/, "/index.html").replace(/^\//, "")
      });
    }))));
    debug(logging, "build", timerMessage("All pages rendered", timer.renderStart));
    timer.buildStart = performance.now();
    await vite.build({
      logLevel: "error",
      mode: "production",
      build: {
        emptyOutDir: true,
        minify: "esbuild",
        outDir: fileURLToPath(this.config.dist),
        rollupOptions: {
          input: [],
          output: {format: "esm"}
        },
        target: "es2020"
      },
      plugins: [
        rollupPluginHTML({
          rootDir: viteConfig.root,
          input,
          extractAssets: false
        }),
        ...viteConfig.plugins || []
      ],
      publicDir: viteConfig.publicDir,
      root: viteConfig.root,
      server: viteConfig.server
    });
    debug(logging, "build", timerMessage("Vite build finished", timer.buildStart));
    timer.assetsStart = performance.now();
    Object.keys(assets).map((k) => {
      if (!assets[k])
        return;
      const filePath = new URL(`file://${k}`);
      fs.mkdirSync(new URL("./", filePath), {recursive: true});
      fs.writeFileSync(filePath, assets[k], "utf8");
      delete assets[k];
    });
    debug(logging, "build", timerMessage("Additional assets copied", timer.assetsStart));
    timer.sitemapStart = performance.now();
    if (this.config.buildOptions.sitemap && this.config.buildOptions.site) {
      const sitemapStart = performance.now();
      const sitemap = generateSitemap(input.map(({name}) => new URL(`/${name}`, this.config.buildOptions.site).href));
      const sitemapPath = new URL("./sitemap.xml", this.config.dist);
      await fs.promises.mkdir(new URL("./", sitemapPath), {recursive: true});
      await fs.promises.writeFile(sitemapPath, sitemap, "utf8");
    }
    debug(logging, "build", timerMessage("Sitemap built", timer.sitemapStart));
    await viteServer.close();
    if (logging.level && levels[logging.level] <= levels["info"]) {
      await this.printStats({cwd: this.config.dist, pageCount: input.length});
    }
  }
  async getStaticPathsForRoute(route) {
    if (!this.viteServer)
      throw new Error(`vite.createServer() not called!`);
    const filePath = new URL(`./${route.component}`, this.config.projectRoot);
    const mod = await this.viteServer.ssrLoadModule(fileURLToPath(filePath));
    validateGetStaticPathsModule(mod);
    const rss = generateRssFunction(this.config.buildOptions.site, route);
    const staticPaths = (await mod.getStaticPaths({paginate: generatePaginateFunction(route), rss: rss.generator})).flat();
    this.routeCache[route.component] = staticPaths;
    validateGetStaticPathsResult(staticPaths, this.logging);
    return {
      paths: staticPaths.map((staticPath) => staticPath.params && route.generate(staticPath.params)).filter(Boolean),
      rss: rss.rss
    };
  }
  async printStats({cwd, pageCount}) {
    const [js, html] = await Promise.all([profileJS({cwd, entryHTML: new URL("./index.html", cwd)}), profileHTML({cwd})]);
    console.log(`${bold(cyan("Done"))}
Pages (${pageCount} total)
  ${green(`\u2714 All pages under ${kb(html.maxSize)}`)}
JS
  ${pad("initial load", 50)}${pad(kb(js.entryHTML || 0), 8, "left")}
  ${pad("total size", 50)}${pad(kb(js.total), 8, "left")}
CSS
  ${pad("initial load", 50)}${pad("0 kB", 8, "left")}
  ${pad("total size", 50)}${pad("0 kB", 8, "left")}
Images
  ${green(`\u2714 All images under 50 kB`)}
`);
  }
}
export {
  build as default
};
//# sourceMappingURL=data:application/json;base64, 
