import { build } from '../src/core/build'; import { devBuild } from '../src/core/devBuild'; import type { BuildConfig as BunBuildConfig } from 'bun'; import type { ImageConfig } from './image'; import type { SitemapConfig } from './sitemap'; export type BunBuildPassKey = 'server' | 'reactClient' | 'nonReactClient' | 'islandClient' | 'globalCss' | 'vueCss'; export type ReservedBunBuildConfigKey = 'entrypoints' | 'outdir' | 'outfile' | 'root' | 'target' | 'format' | 'throw' | 'compile'; type DistributivePartialOmit = T extends unknown ? Partial>> : never; export type BunBuildConfigOverride = DistributivePartialOmit; export type BunBuildPassConfig = { default?: BunBuildConfigOverride; } & Partial>; export type BuildOptions = { /** When true, build() throws on error instead of exit(1) - used by HMR rebuilds */ throwOnError?: boolean; /** When true, HMR client code is injected into built assets. Set by devBuild(). */ injectHMR?: boolean; hmr?: { debounceMs?: number; }; /** Base manifest to merge into for incremental builds */ baseManifest?: Record; }; export type BuildPassError = { /** Internal pass id, e.g. `global-css`, `non-react-client`. */ pass: string; /** Human label used in logs/overlay, e.g. `Global CSS`. */ label: string; /** Best-effort human-readable message (specifier + referrer when known). */ message: string; /** Source file the failure was reported against, if Bun provided it. */ file?: string; /** The unresolved import specifier / missing reference, if known. */ specifier?: string; line?: number; column?: number; /** Raw Bun build logs for the failing pass (drives the error overlay). */ logs?: unknown[]; }; export type StylesConfig = { path: string; ignore?: string[]; }; export type SassPreprocessorOptions = { /** * Additional directories used when resolving Sass/SCSS @use, @forward, and @import. * The current file directory and project root are always included. */ loadPaths?: string[]; /** Source prepended to every Sass/SCSS file before compilation. */ additionalData?: string; /** Select the Sass implementation package. Defaults to "sass". */ implementation?: 'sass' | 'sass-embedded'; }; export type LessPreprocessorOptions = { /** * Additional directories used when resolving Less @import. * The current file directory and project root are always included. */ paths?: string[]; /** Source prepended to every Less file before compilation. */ additionalData?: string; /** Extra Less render options forwarded to less.render(). */ options?: Record; }; export type StylusPreprocessorOptions = { /** * Additional directories used when resolving Stylus @import. * The current file directory and project root are always included. */ paths?: string[]; /** Source prepended to every Stylus file before compilation. */ additionalData?: string; /** Extra Stylus renderer options forwarded to stylus.set(). */ options?: Record; }; export type PostCSSConfig = false | { /** * Inline PostCSS plugins. Import plugins in absolute.config.ts and pass * initialized plugin instances here. */ plugins?: unknown[] | Record; /** Extra options forwarded to postcss.process(). */ options?: Record; /** Explicit PostCSS config file, such as ./postcss.config.cjs. */ config?: string; }; export type StylePreprocessorConfig = { /** * Import aliases for preprocessor imports, e.g. { "@styles/*": "src/styles/*" }. * tsconfig compilerOptions.paths are also loaded automatically when available. */ aliases?: Record; sass?: SassPreprocessorOptions; scss?: SassPreprocessorOptions; less?: LessPreprocessorOptions; postcss?: PostCSSConfig; stylus?: StylusPreprocessorOptions; }; export type TailwindConfig = { input: string; output: string; }; export type StaticConfig = { /** Routes to pre-render at build time. Use "all" to crawl from / and discover all linked pages. */ routes: string[] | 'all'; /** Revalidation interval in seconds. When set, stale pages are re-rendered in the background (ISR). */ revalidate?: number; }; export type CompileNativeAssetConfig = { /** * Static import specifier for a native asset that Bun must embed only when * producing a standalone executable, e.g. * "@scope/native-linux-x64/native.node". */ import: string; /** * Environment variable set to the embedded asset's runtime path before the * compiled server bundle is imported. */ env: string; }; export type CompileConfig = { /** * Native assets to embed with Bun's `with { type: "file" }` compile import. * These are injected into Absolute's generated compile entrypoint, so dev * and start never evaluate `.node` files as ESM imports. */ nativeAssets?: CompileNativeAssetConfig[]; /** * Bun bundler plugins applied to the standalone server bundle produced by * `absolute compile`. The server `compile` pass runs its own `Bun.build`, * which does NOT pick up `bunBuild.plugins` (those target the client * bundles only). This is the escape hatch for deps whose published source * is bundle-hostile under `bun build --compile` — register an `onLoad` * plugin here to rewrite their source so the standalone binary can embed * them (e.g. shimming a CJS `debug` default-import interop, or stubbing a * lazy `require`). Runs after Absolute's internal compile plugins. */ plugins?: NonNullable; }; export type HttpReadyConfig = { type?: 'http'; path?: string; url?: string; method?: 'GET' | 'HEAD'; expectStatus?: number | number[]; headers?: Record; intervalMs?: number; timeoutMs?: number; }; export type TcpReadyConfig = { type: 'tcp'; host?: string; port: number; intervalMs?: number; timeoutMs?: number; }; export type CommandReadyConfig = { type: 'command'; command: string[]; intervalMs?: number; timeoutMs?: number; }; export type DelayReadyConfig = { type: 'delay'; ms: number; }; export type ServiceReadyConfig = false | string | HttpReadyConfig | TcpReadyConfig | CommandReadyConfig | DelayReadyConfig; export type ServiceShutdownConfig = false | string[] | { command: string[]; timeoutMs?: number; }; export type ServiceVisibility = 'public' | 'internal'; export type BaseBuildConfig = { buildDirectory?: string; assetsDirectory?: string; publicDirectory?: string; islands?: { registry: string; bootstrap?: string; }; reactDirectory?: string; vueDirectory?: string; angularDirectory?: string; /** Per-framework Angular config. `providers` is the global default * DI provider array every page gets at SSR + client bootstrap. * Write it as a real typed value (`providers: appProviders`) so * TypeScript catches a missing import or renamed binding at * compile time. The framework AST-parses absolute.config.ts at * build time to find the import path of the binding referenced * here, then bakes a matching import into every per-page generated * providers file. Per-page additions (e.g. `provideRouter(routes)`) * come from page-level `export const routes` and are auto-wired by * the build — users never write `provideRouter` themselves. */ angular?: { providers?: ReadonlyArray; }; astroDirectory?: string; svelteDirectory?: string; emberDirectory?: string; htmlDirectory?: string; htmxDirectory?: string; stylesConfig?: string | StylesConfig; stylePreprocessors?: StylePreprocessorConfig; postcss?: PostCSSConfig; tailwind?: TailwindConfig; /** * Bun build options applied to Absolute's app output build passes. * Framework-owned fields such as entrypoints, outdir, root, target, * format, throw, and compile are intentionally not user-configurable. */ bunBuild?: BunBuildConfigOverride | BunBuildPassConfig; options?: BuildOptions; incrementalFiles?: string[]; mode?: 'production' | 'development'; dev?: { /** Dev server port (env: ABSOLUTE_PORT, default 3000). */ port?: number; /** When `port` is busy, probe up to `portRange-1` neighboring ports * before failing (env: ABSOLUTE_PORT_RANGE, default 10). */ portRange?: number; /** When true, refuse to start if `port` is busy instead of falling * through to the next free port (env: ABSOLUTE_STRICT_PORT, default false). */ strictPort?: boolean; /** Bind host (env: ABSOLUTE_HOST, default "localhost"). */ host?: string; https?: boolean; /** Extra directories to add to the dev file watcher's positive * include list. Anything outside the configured framework dirs, * conventional source dirs (`src/`, `db/`, `assets/`, `styles/`), * and these `watchDirs` is implicitly ignored. */ watchDirs?: string[]; /** Expose the dev server to the public internet through a self-hosted * AbsoluteJS reverse-tunnel relay (for webhooks: Twilio, Stripe, OAuth). * Run the relay with `absolute tunnel-relay` on a public host; point a * dev client at it here. Prints a `Public:` URL on start. */ tunnel?: { /** Relay base URL, e.g. `https://my-relay.ondigitalocean.app` * (env: ABSOLUTE_TUNNEL_RELAY). */ relay?: string; /** Shared secret matching the relay's token (env: ABSOLUTE_TUNNEL_TOKEN). */ token?: string; }; devtools?: { projectRoot?: string; uuid?: string; uuidCachePath?: string; normalizeForWindowsContainer?: boolean; }; }; static?: StaticConfig; compile?: CompileConfig; images?: ImageConfig; sitemap?: SitemapConfig; openapi?: boolean | OpenApiConfig; telemetry?: boolean | OtelConfig; sourcemaps?: 'external' | 'inline' | boolean; }; export type OpenApiConfig = { documentation?: { description?: string; title?: string; version?: string; }; path?: string; provider?: 'scalar' | 'swagger'; }; export type OtelConfig = { serviceName?: string; }; export type AbsoluteServiceConfig = BaseBuildConfig & { kind?: 'absolute'; cwd?: string; config?: string; dependsOn?: string[]; entry?: string; env?: Record; ready?: ServiceReadyConfig; shutdown?: ServiceShutdownConfig; port?: number; visibility?: ServiceVisibility; command?: never; }; export type CommandServiceConfig = { kind: 'command'; command: string[]; cwd?: string; dependsOn?: string[]; env?: Record; ready?: ServiceReadyConfig; shutdown?: ServiceShutdownConfig; port?: number; visibility?: ServiceVisibility; entry?: never; config?: never; }; export type ServiceConfig = AbsoluteServiceConfig | CommandServiceConfig; export type WorkspaceConfig = Record; export type BuildConfig = AbsoluteServiceConfig; export type ConfigInput = BuildConfig | WorkspaceConfig; export type ReservedConfigKey = keyof BuildConfig; export type BuildResult = ReturnType; export type DevBuildResult = ReturnType; export type Result = BuildResult | DevBuildResult; export type Prettify = { [K in keyof T]: T[K]; } & {}; export {};