import { type BuildSettings, resolveBuildSettings } from "./build-settings.ts"; import type { BuildArtifact, BuildStrategy } from "./build-strategy.ts"; import { hasPackageDependency, hasRootFile, runBuildSettingsCommand, } from "./build-strategy.ts"; import { stageConfiguredArtifact } from "./configured-artifact.ts"; import type { BuildCommandIo } from "./workspace.ts"; const ASTRO_CONFIG_FILENAMES = [ "astro.config.js", "astro.config.mjs", "astro.config.cjs", "astro.config.ts", "astro.config.mts", ]; /** * Build strategy for Astro applications using the @astrojs/node adapter * in standalone mode. Runs `astro build` and produces an artifact from `dist/`. */ export class AstroBuild implements BuildStrategy { readonly #appPath: string; readonly #buildSettings?: BuildSettings; readonly #io?: BuildCommandIo; constructor(options: { appPath: string; buildSettings?: BuildSettings; io?: BuildCommandIo; }) { this.#appPath = options.appPath; this.#buildSettings = options.buildSettings; this.#io = options.io; } async canBuild(signal?: AbortSignal): Promise { return ( (await hasRootFile(this.#appPath, ASTRO_CONFIG_FILENAMES, signal)) || (await hasPackageDependency(this.#appPath, ["astro"], signal)) ); } async execute(signal?: AbortSignal): Promise { signal?.throwIfAborted(); const settings = this.#buildSettings ?? (await resolveBuildSettings({ appPath: this.#appPath, buildType: "astro", signal, })); await runBuildSettingsCommand({ appPath: this.#appPath, settings, failurePrefix: "Astro", defaultCli: { source: "Astro default", cliName: "astro", args: ["build"], missingMessage: "Could not find the Astro CLI. Install it with `npm install astro` or ensure npx/bunx is available.", }, io: this.#io, signal, }); return stageConfiguredArtifact({ appPath: this.#appPath, outputDirectory: settings.outputDirectory, entrypoint: settings.entrypoint ?? "server/entry.mjs", buildType: "astro", label: "Astro", missingEntrypointMessage: settings.entrypoint ? undefined : 'Astro build did not produce a standalone server entrypoint. Install @astrojs/node and configure it with adapter: node({ mode: "standalone" }) in your astro.config file.', traceDependencies: true, signal, }); } }