import { type BuildSettings, resolveBuildSettings } from "./build-settings.ts"; import { type BuildArtifact, type BuildStrategy, runBuildSettingsCommand, } from "./build-strategy.ts"; import { normalizeConfiguredArtifactEntrypoint, stageConfiguredArtifact, } from "./configured-artifact.ts"; import type { BuildCommandIo } from "./workspace.ts"; /** * Generic artifact strategy for frameworks the SDK does not know about yet. * Runs an optional command, stages a configured output directory as-is, and * starts the configured entrypoint from inside that artifact. */ export class CustomBuild implements BuildStrategy { readonly #appPath: string; readonly #entrypoint?: string; readonly #buildSettings?: BuildSettings; readonly #io?: BuildCommandIo; constructor(options: { appPath: string; entrypoint?: string; buildSettings?: BuildSettings; io?: BuildCommandIo; }) { this.#appPath = options.appPath; this.#entrypoint = options.entrypoint; this.#buildSettings = options.buildSettings; this.#io = options.io; } async canBuild(_signal?: AbortSignal): Promise { return Boolean(this.#entrypoint ?? this.#buildSettings?.entrypoint); } async execute(signal?: AbortSignal): Promise { signal?.throwIfAborted(); const settings = this.#buildSettings ?? (await resolveBuildSettings({ appPath: this.#appPath, buildType: "custom", signal, })); const entrypoint = this.#entrypoint ?? settings.entrypoint; if (!entrypoint) { throw new Error("Custom build entrypoint is required"); } normalizeConfiguredArtifactEntrypoint(entrypoint, "Custom"); await runBuildSettingsCommand({ appPath: this.#appPath, settings, failurePrefix: "Custom", io: this.#io, signal, }); return stageConfiguredArtifact({ appPath: this.#appPath, outputDirectory: settings.outputDirectory, entrypoint, buildType: "custom", label: "Custom", signal, }); } }