summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/new-llamas-wash.md5
-rw-r--r--packages/astro/src/@types/astro.ts29
-rw-r--r--packages/astro/src/cli/check/index.ts6
-rw-r--r--packages/astro/src/cli/index.ts30
-rw-r--r--packages/astro/src/core/add/index.ts2
-rw-r--r--packages/astro/src/core/build/generate.ts63
-rw-r--r--packages/astro/src/core/build/index.ts46
-rw-r--r--packages/astro/src/core/build/page-data.ts8
-rw-r--r--packages/astro/src/core/build/static-build.ts52
-rw-r--r--packages/astro/src/core/build/types.ts4
-rw-r--r--packages/astro/src/core/build/vite-plugin-css.ts7
-rw-r--r--packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts8
-rw-r--r--packages/astro/src/core/build/vite-plugin-pages.ts4
-rw-r--r--packages/astro/src/core/build/vite-plugin-ssr.ts22
-rw-r--r--packages/astro/src/core/config/config.ts (renamed from packages/astro/src/core/config.ts)298
-rw-r--r--packages/astro/src/core/config/index.ts20
-rw-r--r--packages/astro/src/core/config/schema.ts271
-rw-r--r--packages/astro/src/core/config/settings.ts31
-rw-r--r--packages/astro/src/core/config/tsconfig.ts11
-rw-r--r--packages/astro/src/core/create-vite.ts50
-rw-r--r--packages/astro/src/core/dev/index.ts24
-rw-r--r--packages/astro/src/core/endpoint/dev/index.ts2
-rw-r--r--packages/astro/src/core/preview/index.ts20
-rw-r--r--packages/astro/src/core/render/dev/index.ts36
-rw-r--r--packages/astro/src/core/render/dev/scripts.ts7
-rw-r--r--packages/astro/src/core/routing/manifest/create.ts16
-rw-r--r--packages/astro/src/core/util.ts18
-rw-r--r--packages/astro/src/integrations/index.ts46
-rw-r--r--packages/astro/src/vite-plugin-astro-postprocess/index.ts6
-rw-r--r--packages/astro/src/vite-plugin-astro-server/index.ts55
-rw-r--r--packages/astro/src/vite-plugin-astro/index.ts7
-rw-r--r--packages/astro/src/vite-plugin-config-alias/index.ts15
-rw-r--r--packages/astro/src/vite-plugin-env/index.ts7
-rw-r--r--packages/astro/src/vite-plugin-integrations-container/index.ts8
-rw-r--r--packages/astro/src/vite-plugin-jsx/index.ts10
-rw-r--r--packages/astro/src/vite-plugin-markdown-legacy/index.ts7
-rw-r--r--packages/astro/src/vite-plugin-markdown/index.ts10
-rw-r--r--packages/astro/src/vite-plugin-scripts/index.ts12
-rw-r--r--packages/astro/src/vite-plugin-scripts/page-ssr.ts12
-rw-r--r--packages/astro/test/config-mode.test.js4
-rw-r--r--packages/astro/test/config.test.js126
-rw-r--r--packages/astro/test/test-utils.js30
-rw-r--r--packages/astro/test/units/config/config-server.test.js71
-rw-r--r--packages/astro/test/units/config/config-validate.test.js (renamed from packages/astro/test/config-validate.test.js)4
44 files changed, 776 insertions, 744 deletions
diff --git a/.changeset/new-llamas-wash.md b/.changeset/new-llamas-wash.md
new file mode 100644
index 000000000..09575ff13
--- /dev/null
+++ b/.changeset/new-llamas-wash.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Internal refactor
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index 817467a30..7589534c7 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -11,7 +11,7 @@ import type * as babel from '@babel/core';
import type { AddressInfo } from 'net';
import type { TsConfigJson } from 'tsconfig-resolver';
import type * as vite from 'vite';
-import { z } from 'zod';
+import type { z } from 'zod';
import type { SerializedSSRManifest } from '../core/app/types';
import type { PageBuildData } from '../core/build/types';
import type { AstroConfigSchema } from '../core/config';
@@ -871,20 +871,21 @@ export interface AstroConfig extends z.output<typeof AstroConfigSchema> {
// This is a more detailed type than zod validation gives us.
// TypeScript still confirms zod validation matches this type.
integrations: AstroIntegration[];
+}
- // Private:
- // We have a need to pass context based on configured state,
- // that is different from the user-exposed configuration.
- // TODO: Create an AstroConfig class to manage this, long-term.
- _ctx: {
- tsConfig: TsConfigJson | undefined;
- tsConfigPath: string | undefined;
- pageExtensions: string[];
- injectedRoutes: InjectedRoute[];
- adapter: AstroAdapter | undefined;
- renderers: AstroRenderer[];
- scripts: { stage: InjectedScriptStage; content: string }[];
- };
+export interface AstroSettings {
+ config: AstroConfig;
+
+ adapter: AstroAdapter | undefined;
+ injectedRoutes: InjectedRoute[];
+ pageExtensions: string[];
+ renderers: AstroRenderer[];
+ scripts: {
+ stage: InjectedScriptStage;
+ content: string
+ }[];
+ tsConfig: TsConfigJson | undefined;
+ tsConfigPath: string | undefined;
}
export type AsyncRendererComponentFn<U> = (
diff --git a/packages/astro/src/cli/check/index.ts b/packages/astro/src/cli/check/index.ts
index 79571de0f..60e6b7a97 100644
--- a/packages/astro/src/cli/check/index.ts
+++ b/packages/astro/src/cli/check/index.ts
@@ -1,6 +1,6 @@
/* eslint-disable no-console */
import { AstroCheck, DiagnosticSeverity } from '@astrojs/language-server';
-import type { AstroConfig } from '../../@types/astro';
+import type { AstroSettings } from '../../@types/astro';
import glob from 'fast-glob';
import * as fs from 'fs';
@@ -16,10 +16,10 @@ interface Result {
hints: number;
}
-export async function check(astroConfig: AstroConfig) {
+export async function check(settings: AstroSettings) {
console.log(bold('astro check'));
- const root = astroConfig.root;
+ const root = settings.config.root;
const spinner = ora(` Getting diagnostics for Astro files in ${fileURLToPath(root)}…`).start();
diff --git a/packages/astro/src/cli/index.ts b/packages/astro/src/cli/index.ts
index 622505700..064a2b5b3 100644
--- a/packages/astro/src/cli/index.ts
+++ b/packages/astro/src/cli/index.ts
@@ -7,7 +7,7 @@ import yargs from 'yargs-parser';
import { z } from 'zod';
import add from '../core/add/index.js';
import build from '../core/build/index.js';
-import { openConfig, resolveConfigPath, resolveFlags, resolveRoot } from '../core/config.js';
+import { openConfig, resolveConfigPath, resolveFlags, resolveRoot, createSettings, loadTSConfig } from '../core/config/index.js';
import devServer from '../core/dev/index.js';
import { collectErrorMetadata } from '../core/errors.js';
import { debug, error, info, LogOptions } from '../core/logger/core.js';
@@ -150,7 +150,7 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
}
}
- let { astroConfig, userConfig } = await openConfig({
+ let { astroConfig: initialAstroConfig, userConfig: initialUserConfig } = await openConfig({
cwd: root,
flags,
cmd,
@@ -159,8 +159,14 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
await handleConfigError(e, { cwd: root, flags, logging });
return {} as any;
});
- if (!astroConfig) return;
- telemetry.record(event.eventCliSession(cmd, userConfig, flags));
+ if (!initialAstroConfig) return;
+ telemetry.record(event.eventCliSession(cmd, initialUserConfig, flags));
+ let initialTsConfig = loadTSConfig(root);
+ let settings = createSettings({
+ config: initialAstroConfig,
+ tsConfig: initialTsConfig?.config,
+ tsConfigPath: initialTsConfig?.path,
+ });
// Common CLI Commands:
// These commands run normally. All commands are assumed to have been handled
@@ -168,7 +174,7 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
switch (cmd) {
case 'dev': {
async function startDevServer({ isRestart = false }: { isRestart?: boolean } = {}) {
- const { watcher, stop } = await devServer(astroConfig, { logging, telemetry, isRestart });
+ const { watcher, stop } = await devServer(settings, { logging, telemetry, isRestart });
let restartInFlight = false;
const configFlag = resolveFlags(flags).config;
const configFlagPath = configFlag
@@ -199,7 +205,13 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
isConfigReload: true,
});
info(logging, 'astro', logMsg + '\n');
- astroConfig = newConfig.astroConfig;
+ let astroConfig = newConfig.astroConfig;
+ let tsconfig = loadTSConfig(root);
+ settings = createSettings({
+ config: astroConfig,
+ tsConfig: tsconfig?.config,
+ tsConfigPath: tsconfig?.path
+ });
await stop();
await startDevServer({ isRestart: true });
} catch (e) {
@@ -220,16 +232,16 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
}
case 'build': {
- return await build(astroConfig, { logging, telemetry });
+ return await build(settings, { logging, telemetry });
}
case 'check': {
- const ret = await check(astroConfig);
+ const ret = await check(settings);
return process.exit(ret);
}
case 'preview': {
- const server = await preview(astroConfig, { logging, telemetry });
+ const server = await preview(settings, { logging, telemetry });
return await server.closed(); // keep alive until the server is closed
}
}
diff --git a/packages/astro/src/core/add/index.ts b/packages/astro/src/core/add/index.ts
index c655dab5d..70a766e07 100644
--- a/packages/astro/src/core/add/index.ts
+++ b/packages/astro/src/core/add/index.ts
@@ -10,7 +10,7 @@ import preferredPM from 'preferred-pm';
import prompts from 'prompts';
import { fileURLToPath, pathToFileURL } from 'url';
import type yargs from 'yargs-parser';
-import { resolveConfigPath } from '../config.js';
+import { resolveConfigPath } from '../config/index.js';
import { debug, info, LogOptions } from '../logger/core.js';
import * as msg from '../messages.js';
import { printHelp } from '../messages.js';
diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts
index 6a3fe5035..a73d48945 100644
--- a/packages/astro/src/core/build/generate.ts
+++ b/packages/astro/src/core/build/generate.ts
@@ -6,6 +6,7 @@ import type { OutputAsset, OutputChunk } from 'rollup';
import { fileURLToPath } from 'url';
import type {
AstroConfig,
+ AstroSettings,
ComponentInstance,
EndpointHandler,
RouteType,
@@ -62,10 +63,10 @@ function* throttle(max: number, inPaths: string[]) {
}
}
-function shouldSkipDraft(pageModule: ComponentInstance, astroConfig: AstroConfig): boolean {
+function shouldSkipDraft(pageModule: ComponentInstance, settings: AstroSettings): boolean {
return (
// Drafts are disabled
- !astroConfig.markdown.drafts &&
+ !settings.config.markdown.drafts &&
// This is a draft post
'frontmatter' in pageModule &&
(pageModule as any).frontmatter?.draft === true
@@ -74,13 +75,13 @@ function shouldSkipDraft(pageModule: ComponentInstance, astroConfig: AstroConfig
// Gives back a facadeId that is relative to the root.
// ie, src/pages/index.astro instead of /Users/name..../src/pages/index.astro
-export function rootRelativeFacadeId(facadeId: string, astroConfig: AstroConfig): string {
- return facadeId.slice(fileURLToPath(astroConfig.root).length);
+export function rootRelativeFacadeId(facadeId: string, settings: AstroSettings): string {
+ return facadeId.slice(fileURLToPath(settings.config.root).length);
}
// Determines of a Rollup chunk is an entrypoint page.
export function chunkIsPage(
- astroConfig: AstroConfig,
+ settings: AstroSettings,
output: OutputAsset | OutputChunk,
internals: BuildInternals
) {
@@ -90,7 +91,7 @@ export function chunkIsPage(
const chunk = output as OutputChunk;
if (chunk.facadeModuleId) {
const facadeToEntryId = prependForwardSlash(
- rootRelativeFacadeId(chunk.facadeModuleId, astroConfig)
+ rootRelativeFacadeId(chunk.facadeModuleId, settings)
);
return internals.entrySpecifierToBundleMap.has(facadeToEntryId);
}
@@ -101,9 +102,9 @@ export async function generatePages(opts: StaticBuildOptions, internals: BuildIn
const timer = performance.now();
info(opts.logging, null, `\n${bgGreen(black(' generating static routes '))}`);
- const ssr = opts.astroConfig.output === 'server';
+ const ssr = opts.settings.config.output === 'server';
const serverEntry = opts.buildConfig.serverEntry;
- const outFolder = ssr ? opts.buildConfig.server : getOutDirWithinCwd(opts.astroConfig.outDir);
+ const outFolder = ssr ? opts.buildConfig.server : getOutDirWithinCwd(opts.settings.config.outDir);
const ssrEntryURL = new URL('./' + serverEntry + `?time=${Date.now()}`, outFolder);
const ssrEntry = await import(ssrEntryURL.toString());
const builtPaths = new Set<string>();
@@ -137,7 +138,7 @@ async function generatePage(
);
}
- if (shouldSkipDraft(pageModule, opts.astroConfig)) {
+ if (shouldSkipDraft(pageModule, opts.settings)) {
info(opts.logging, null, `${magenta('⚠️')} Skipping draft ${pageData.route.component}`);
return;
}
@@ -163,7 +164,7 @@ async function generatePage(
const timeEnd = performance.now();
const timeChange = getTimeStat(timeStart, timeEnd);
const timeIncrease = `(+${timeChange})`;
- const filePath = getOutputFilename(opts.astroConfig, path, pageData.route.type);
+ const filePath = getOutputFilename(opts.settings.config, path, pageData.route.type);
const lineIcon = i === paths.length - 1 ? '└─' : '├─';
info(opts.logging, null, ` ${cyan(lineIcon)} ${dim(filePath)} ${dim(timeIncrease)}`);
}
@@ -186,7 +187,7 @@ async function getPathsForRoute(
route: pageData.route,
isValidate: false,
logging: opts.logging,
- ssr: opts.astroConfig.output === 'server',
+ ssr: opts.settings.config.output === 'server',
})
.then((_result) => {
const label = _result.staticPaths.length === 1 ? 'page' : 'pages';
@@ -262,8 +263,8 @@ function shouldAppendForwardSlash(
}
function addPageName(pathname: string, opts: StaticBuildOptions): void {
- const trailingSlash = opts.astroConfig.trailingSlash;
- const buildFormat = opts.astroConfig.build.format;
+ const trailingSlash = opts.settings.config.trailingSlash;
+ const buildFormat = opts.settings.config.build.format;
const pageName = shouldAppendForwardSlash(trailingSlash, buildFormat)
? pathname.replace(/\/?$/, '/').replace(/^\//, '')
: pathname.replace(/^\//, '');
@@ -303,7 +304,7 @@ async function generatePath(
opts: StaticBuildOptions,
gopts: GeneratePathOptions
) {
- const { astroConfig, logging, origin, routeCache } = opts;
+ const { settings, logging, origin, routeCache } = opts;
const { mod, internals, linkIds, scripts: hoistedScripts, pageData, renderers } = gopts;
// This adds the page name to the array so it can be shown as part of stats.
@@ -316,18 +317,18 @@ async function generatePath(
// If a base path was provided, append it to the site URL. This ensures that
// all injected scripts and links are referenced relative to the site and subpath.
const site =
- astroConfig.base !== '/'
- ? joinPaths(astroConfig.site?.toString() || 'http://localhost/', astroConfig.base)
- : astroConfig.site;
+ settings.config.base !== '/'
+ ? joinPaths(settings.config.site?.toString() || 'http://localhost/', settings.config.base)
+ : settings.config.site;
const links = createLinkStylesheetElementSet(linkIds, site);
const scripts = createModuleScriptsSet(hoistedScripts ? [hoistedScripts] : [], site);
- if (astroConfig._ctx.scripts.some((script) => script.stage === 'page')) {
+ if (settings.scripts.some((script) => script.stage === 'page')) {
const hashedFilePath = internals.entrySpecifierToBundleMap.get(PAGE_SCRIPT_ID);
if (typeof hashedFilePath !== 'string') {
throw new Error(`Cannot find the built path for ${PAGE_SCRIPT_ID}`);
}
- const src = prependForwardSlash(npath.posix.join(astroConfig.base, hashedFilePath));
+ const src = prependForwardSlash(npath.posix.join(settings.config.base, hashedFilePath));
scripts.add({
props: { type: 'module', src },
children: '',
@@ -335,7 +336,7 @@ async function generatePath(
}
// Add all injected scripts to the page.
- for (const script of astroConfig._ctx.scripts) {
+ for (const script of settings.scripts) {
if (script.stage === 'head-inline') {
scripts.add({
props: {},
@@ -344,12 +345,12 @@ async function generatePath(
}
}
- const ssr = opts.astroConfig.output === 'server';
+ const ssr = settings.config.output === 'server';
const url = getUrlForPath(
pathname,
- opts.astroConfig.base,
+ opts.settings.config.base,
origin,
- opts.astroConfig.build.format,
+ opts.settings.config.build.format,
pageData.route.type
);
const options: RenderOptions = {
@@ -357,8 +358,8 @@ async function generatePath(
links,
logging,
markdown: {
- ...astroConfig.markdown,
- isAstroFlavoredMd: astroConfig.legacy.astroFlavoredMarkdown,
+ ...settings.config.markdown,
+ isAstroFlavoredMd: settings.config.legacy.astroFlavoredMarkdown,
},
mod,
mode: opts.mode,
@@ -376,14 +377,14 @@ async function generatePath(
}
throw new Error(`Cannot find the built path for ${specifier}`);
}
- return prependForwardSlash(npath.posix.join(astroConfig.base, hashedFilePath));
+ return prependForwardSlash(npath.posix.join(settings.config.base, hashedFilePath));
},
request: createRequest({ url, headers: new Headers(), logging, ssr }),
route: pageData.route,
routeCache,
- site: astroConfig.site
- ? new URL(astroConfig.base, astroConfig.site).toString()
- : astroConfig.site,
+ site: settings.config.site
+ ? new URL(settings.config.base, settings.config.site).toString()
+ : settings.config.site,
ssr,
streaming: true,
};
@@ -409,8 +410,8 @@ async function generatePath(
body = await response.text();
}
- const outFolder = getOutFolder(astroConfig, pathname, pageData.route.type);
- const outFile = getOutFile(astroConfig, outFolder, pathname, pageData.route.type);
+ const outFolder = getOutFolder(settings.config, pathname, pageData.route.type);
+ const outFile = getOutFile(settings.config, outFolder, pathname, pageData.route.type);
pageData.route.distURL = outFile;
await fs.promises.mkdir(outFolder, { recursive: true });
await fs.promises.writeFile(outFile, body, encoding ?? 'utf-8');
diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts
index 829637ddd..7a3b9760f 100644
--- a/packages/astro/src/core/build/index.ts
+++ b/packages/astro/src/core/build/index.ts
@@ -1,5 +1,5 @@
import type { AstroTelemetry } from '@astrojs/telemetry';
-import type { AstroConfig, BuildConfig, ManifestData, RuntimeMode } from '../../@types/astro';
+import type { AstroSettings, BuildConfig, ManifestData, RuntimeMode } from '../../@types/astro';
import type { LogOptions } from '../logger/core';
import fs from 'fs';
@@ -28,14 +28,14 @@ export interface BuildOptions {
}
/** `astro build` */
-export default async function build(config: AstroConfig, options: BuildOptions): Promise<void> {
+export default async function build(settings: AstroSettings, options: BuildOptions): Promise<void> {
applyPolyfill();
- const builder = new AstroBuilder(config, options);
+ const builder = new AstroBuilder(settings, options);
await builder.run();
}
class AstroBuilder {
- private config: AstroConfig;
+ private settings: AstroSettings;
private logging: LogOptions;
private mode: RuntimeMode = 'production';
private origin: string;
@@ -43,16 +43,16 @@ class AstroBuilder {
private manifest: ManifestData;
private timer: Record<string, number>;
- constructor(config: AstroConfig, options: BuildOptions) {
+ constructor(settings: AstroSettings, options: BuildOptions) {
if (options.mode) {
this.mode = options.mode;
}
- this.config = config;
+ this.settings = settings;
this.logging = options.logging;
this.routeCache = new RouteCache(this.logging);
- this.origin = config.site
- ? new URL(config.site).origin
- : `http://localhost:${config.server.port}`;
+ this.origin = settings.config.site
+ ? new URL(settings.config.site).origin
+ : `http://localhost:${settings.config.server.port}`;
this.manifest = { routes: [] };
this.timer = {};
}
@@ -62,8 +62,8 @@ class AstroBuilder {
debug('build', 'Initial setup...');
const { logging } = this;
this.timer.init = performance.now();
- this.config = await runHookConfigSetup({ config: this.config, command: 'build', logging });
- this.manifest = createRouteManifest({ config: this.config }, this.logging);
+ this.settings = await runHookConfigSetup({ settings: this.settings, command: 'build', logging });
+ this.manifest = createRouteManifest({ settings: this.settings }, this.logging);
const viteConfig = await createVite(
{
@@ -73,29 +73,29 @@ class AstroBuilder {
middlewareMode: true,
},
},
- { astroConfig: this.config, logging, mode: 'build' }
+ { settings: this.settings, logging, mode: 'build' }
);
- await runHookConfigDone({ config: this.config, logging });
+ await runHookConfigDone({ settings: this.settings, logging });
return { viteConfig };
}
/** Run the build logic. build() is marked private because usage should go through ".run()" */
private async build({ viteConfig }: { viteConfig: ViteConfigWithSSR }) {
const buildConfig: BuildConfig = {
- client: new URL('./client/', this.config.outDir),
- server: new URL('./server/', this.config.outDir),
+ client: new URL('./client/', this.settings.config.outDir),
+ server: new URL('./server/', this.settings.config.outDir),
serverEntry: 'entry.mjs',
};
- await runHookBuildStart({ config: this.config, buildConfig, logging: this.logging });
+ await runHookBuildStart({ config: this.settings.config, buildConfig, logging: this.logging });
- info(this.logging, 'build', `output target: ${colors.green(this.config.output)}`);
- if (this.config._ctx.adapter) {
- info(this.logging, 'build', `deploy adapter: ${colors.green(this.config._ctx.adapter.name)}`);
+ info(this.logging, 'build', `output target: ${colors.green(this.settings.config.output)}`);
+ if (this.settings.adapter) {
+ info(this.logging, 'build', `deploy adapter: ${colors.green(this.settings.adapter.name)}`);
}
info(this.logging, 'build', 'Collecting build info...');
this.timer.loadStart = performance.now();
const { assets, allPages } = await collectPagesData({
- astroConfig: this.config,
+ settings: this.settings,
logging: this.logging,
manifest: this.manifest,
});
@@ -116,7 +116,7 @@ class AstroBuilder {
await staticBuild({
allPages,
- astroConfig: this.config,
+ settings: this.settings,
logging: this.logging,
manifest: this.manifest,
mode: this.mode,
@@ -140,7 +140,7 @@ class AstroBuilder {
// You're done! Time to clean up.
await runHookBuildDone({
- config: this.config,
+ config: this.settings.config,
buildConfig,
pages: pageNames,
routes: Object.values(allPages).map((pd) => pd.route),
@@ -152,7 +152,7 @@ class AstroBuilder {
logging: this.logging,
timeStart: this.timer.init,
pageCount: pageNames.length,
- buildMode: this.config.output,
+ buildMode: this.settings.config.output,
});
}
}
diff --git a/packages/astro/src/core/build/page-data.ts b/packages/astro/src/core/build/page-data.ts
index 509d1ae20..ed4bf4399 100644
--- a/packages/astro/src/core/build/page-data.ts
+++ b/packages/astro/src/core/build/page-data.ts
@@ -1,4 +1,4 @@
-import type { AstroConfig, ManifestData } from '../../@types/astro';
+import type { AstroSettings, ManifestData } from '../../@types/astro';
import type { LogOptions } from '../logger/core';
import { info } from '../logger/core.js';
import type { AllPagesData } from './types';
@@ -7,7 +7,7 @@ import * as colors from 'kleur/colors';
import { debug } from '../logger/core.js';
export interface CollectPagesDataOptions {
- astroConfig: AstroConfig;
+ settings: AstroSettings;
logging: LogOptions;
manifest: ManifestData;
}
@@ -21,7 +21,7 @@ export interface CollectPagesDataResult {
export async function collectPagesData(
opts: CollectPagesDataOptions
): Promise<CollectPagesDataResult> {
- const { astroConfig, manifest } = opts;
+ const { settings, manifest } = opts;
const assets: Record<string, string> = {};
const allPages: AllPagesData = {};
@@ -58,7 +58,7 @@ export async function collectPagesData(
};
clearInterval(routeCollectionLogTimeout);
- if (astroConfig.output === 'static') {
+ if (settings.config.output === 'static') {
const html = `${route.pathname}`.replace(/\/?$/, '/index.html');
debug(
'build',
diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts
index 0e91dc548..9afa3ed32 100644
--- a/packages/astro/src/core/build/static-build.ts
+++ b/packages/astro/src/core/build/static-build.ts
@@ -23,10 +23,10 @@ import { vitePluginPages } from './vite-plugin-pages.js';
import { injectManifest, vitePluginSSR } from './vite-plugin-ssr.js';
export async function staticBuild(opts: StaticBuildOptions) {
- const { allPages, astroConfig } = opts;
+ const { allPages, settings } = opts;
// Verify this app is buildable.
- if (isModeServerWithNoAdapter(opts.astroConfig)) {
+ if (isModeServerWithNoAdapter(opts.settings)) {
throw new Error(`Cannot use \`output: 'server'\` without an adapter.
Install and configure the appropriate server adapter for your final deployment.
Learn more: https://docs.astro.build/en/guides/server-side-rendering/
@@ -55,7 +55,7 @@ Learn more: https://docs.astro.build/en/guides/server-side-rendering/
timer.buildStart = performance.now();
for (const [component, pageData] of Object.entries(allPages)) {
- const astroModuleURL = new URL('./' + component, astroConfig.root);
+ const astroModuleURL = new URL('./' + component, settings.config.root);
const astroModuleId = prependForwardSlash(component);
// Track the page data in internals
@@ -68,15 +68,15 @@ Learn more: https://docs.astro.build/en/guides/server-side-rendering/
// Empty out the dist folder, if needed. Vite has a config for doing this
// but because we are running 2 vite builds in parallel, that would cause a race
// condition, so we are doing it ourselves
- emptyDir(astroConfig.outDir, new Set('.git'));
+ emptyDir(settings.config.outDir, new Set('.git'));
// Build your project (SSR application code, assets, client JS, etc.)
timer.ssr = performance.now();
- info(opts.logging, 'build', `Building ${astroConfig.output} entrypoints...`);
+ info(opts.logging, 'build', `Building ${settings.config.output} entrypoints...`);
await ssrBuild(opts, internals, pageInput);
info(opts.logging, 'build', dim(`Completed in ${getTimeStat(timer.ssr, performance.now())}.`));
- const rendererClientEntrypoints = opts.astroConfig._ctx.renderers
+ const rendererClientEntrypoints = settings.renderers
.map((r) => r.clientEntrypoint)
.filter((a) => typeof a === 'string') as string[];
@@ -87,7 +87,7 @@ Learn more: https://docs.astro.build/en/guides/server-side-rendering/
...internals.discoveredScripts,
]);
- if (astroConfig._ctx.scripts.some((script) => script.stage === 'page')) {
+ if (settings.scripts.some((script) => script.stage === 'page')) {
clientInput.add(PAGE_SCRIPT_ID);
}
@@ -96,7 +96,7 @@ Learn more: https://docs.astro.build/en/guides/server-side-rendering/
await clientBuild(opts, internals, clientInput);
timer.generate = performance.now();
- if (astroConfig.output === 'static') {
+ if (settings.config.output === 'static') {
await generatePages(opts, internals);
await cleanSsrOutput(opts);
} else {
@@ -109,9 +109,9 @@ Learn more: https://docs.astro.build/en/guides/server-side-rendering/
}
async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, input: Set<string>) {
- const { astroConfig, viteConfig } = opts;
- const ssr = astroConfig.output === 'server';
- const out = ssr ? opts.buildConfig.server : getOutDirWithinCwd(astroConfig.outDir);
+ const { settings, viteConfig } = opts;
+ const ssr = settings.config.output === 'server';
+ const out = ssr ? opts.buildConfig.server : getOutDirWithinCwd(settings.config.outDir);
const viteBuildConfig: ViteConfigWithSSR = {
...viteConfig,
@@ -148,21 +148,20 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp
buildOptions: opts,
internals,
target: 'server',
- astroConfig,
}),
...(viteConfig.plugins || []),
// SSR needs to be last
- opts.astroConfig.output === 'server' &&
- vitePluginSSR(internals, opts.astroConfig._ctx.adapter!),
+ settings.config.output === 'server' &&
+ vitePluginSSR(internals, settings.adapter!),
vitePluginAnalyzer(internals),
],
publicDir: ssr ? false : viteConfig.publicDir,
envPrefix: 'PUBLIC_',
- base: astroConfig.base,
+ base: settings.config.base,
};
await runHookBuildSetup({
- config: astroConfig,
+ config: settings.config,
pages: internals.pagesByComponent,
vite: viteBuildConfig,
target: 'server',
@@ -177,16 +176,16 @@ async function clientBuild(
internals: BuildInternals,
input: Set<string>
) {
- const { astroConfig, viteConfig } = opts;
+ const { settings, viteConfig } = opts;
const timer = performance.now();
- const ssr = astroConfig.output === 'server';
- const out = ssr ? opts.buildConfig.client : astroConfig.outDir;
+ const ssr = settings.config.output === 'server';
+ const out = ssr ? opts.buildConfig.client : settings.config.outDir;
// Nothing to do if there is no client-side JS.
if (!input.size) {
// If SSR, copy public over
if (ssr) {
- await copyFiles(astroConfig.publicDir, out);
+ await copyFiles(settings.config.publicDir, out);
}
return null;
@@ -219,21 +218,20 @@ async function clientBuild(
},
plugins: [
vitePluginInternals(input, internals),
- vitePluginHoistedScripts(astroConfig, internals),
+ vitePluginHoistedScripts(settings, internals),
rollupPluginAstroBuildCSS({
buildOptions: opts,
internals,
target: 'client',
- astroConfig,
}),
...(viteConfig.plugins || []),
],
envPrefix: 'PUBLIC_',
- base: astroConfig.base,
+ base: settings.config.base,
} as ViteConfigWithSSR;
await runHookBuildSetup({
- config: astroConfig,
+ config: settings.config,
pages: internals.pagesByComponent,
vite: viteBuildConfig,
target: 'client',
@@ -246,9 +244,9 @@ async function clientBuild(
}
async function cleanSsrOutput(opts: StaticBuildOptions) {
- const out = getOutDirWithinCwd(opts.astroConfig.outDir);
+ const out = getOutDirWithinCwd(opts.settings.config.outDir);
// Clean out directly if the outDir is outside of root
- if (out.toString() !== opts.astroConfig.outDir.toString()) {
+ if (out.toString() !== opts.settings.config.outDir.toString()) {
await fs.promises.rm(out, { recursive: true });
return;
}
@@ -284,7 +282,7 @@ async function copyFiles(fromFolder: URL, toFolder: URL) {
async function ssrMoveAssets(opts: StaticBuildOptions) {
info(opts.logging, 'build', 'Rearranging server assets...');
const serverRoot =
- opts.astroConfig.output === 'static' ? opts.buildConfig.client : opts.buildConfig.server;
+ opts.settings.config.output === 'static' ? opts.buildConfig.client : opts.buildConfig.server;
const clientRoot = opts.buildConfig.client;
const serverAssets = new URL('./assets/', serverRoot);
const clientAssets = new URL('./assets/', clientRoot);
diff --git a/packages/astro/src/core/build/types.ts b/packages/astro/src/core/build/types.ts
index 480af85d0..b8beacbb9 100644
--- a/packages/astro/src/core/build/types.ts
+++ b/packages/astro/src/core/build/types.ts
@@ -1,5 +1,5 @@
import type {
- AstroConfig,
+ AstroSettings,
BuildConfig,
ComponentInstance,
ManifestData,
@@ -26,7 +26,7 @@ export type AllPagesData = Record<ComponentPath, PageBuildData>;
/** Options for the static build */
export interface StaticBuildOptions {
allPages: AllPagesData;
- astroConfig: AstroConfig;
+ settings: AstroSettings;
buildConfig: BuildConfig;
logging: LogOptions;
manifest: ManifestData;
diff --git a/packages/astro/src/core/build/vite-plugin-css.ts b/packages/astro/src/core/build/vite-plugin-css.ts
index 4d77f6f15..1ef7202d5 100644
--- a/packages/astro/src/core/build/vite-plugin-css.ts
+++ b/packages/astro/src/core/build/vite-plugin-css.ts
@@ -22,7 +22,6 @@ interface PluginOptions {
internals: BuildInternals;
buildOptions: StaticBuildOptions;
target: 'client' | 'server';
- astroConfig: AstroConfig;
}
// Arbitrary magic number, can change.
@@ -30,13 +29,13 @@ const MAX_NAME_LENGTH = 70;
export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
const { internals, buildOptions } = options;
- const { astroConfig } = buildOptions;
+ const { settings } = buildOptions;
let resolvedConfig: ResolvedConfig;
// Turn a page location into a name to be used for the CSS file.
function nameifyPage(id: string) {
- let rel = relativeToSrcDir(astroConfig, id);
+ let rel = relativeToSrcDir(settings.config, id);
// Remove pages, ex. blog/posts/something.astro
if (rel.startsWith('pages/')) {
rel = rel.slice(6);
@@ -240,7 +239,7 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[]
for (const [, output] of Object.entries(bundle)) {
if (output.type === 'asset') {
if (output.name?.endsWith('.css') && typeof output.source === 'string') {
- const cssTarget = options.astroConfig.vite.build?.cssTarget;
+ const cssTarget = settings.config.vite.build?.cssTarget;
const { code: minifiedCSS } = await esbuild.transform(output.source, {
loader: 'css',
minify: true,
diff --git a/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts b/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts
index 9ab7ece45..23230035c 100644
--- a/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts
+++ b/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts
@@ -1,5 +1,5 @@
import type { Plugin as VitePlugin } from 'vite';
-import type { AstroConfig } from '../../@types/astro';
+import type { AstroSettings } from '../../@types/astro';
import type { BuildInternals } from '../../core/build/internal.js';
import { viteID } from '../util.js';
import { getPageDataByViteID } from './internal.js';
@@ -9,7 +9,7 @@ function virtualHoistedEntry(id: string) {
}
export function vitePluginHoistedScripts(
- astroConfig: AstroConfig,
+ settings: AstroSettings,
internals: BuildInternals
): VitePlugin {
return {
@@ -40,7 +40,7 @@ export function vitePluginHoistedScripts(
},
async generateBundle(_options, bundle) {
- let assetInlineLimit = astroConfig.vite?.build?.assetsInlineLimit || 4096;
+ let assetInlineLimit = settings.config.vite?.build?.assetsInlineLimit || 4096;
// Find all page entry points and create a map of the entry point to the hashed hoisted script.
// This is used when we render so that we can add the script to the head.
@@ -58,7 +58,7 @@ export function vitePluginHoistedScripts(
const facadeId = output.facadeModuleId!;
const pages = internals.hoistedScriptIdToPagesMap.get(facadeId)!;
for (const pathname of pages) {
- const vid = viteID(new URL('.' + pathname, astroConfig.root));
+ const vid = viteID(new URL('.' + pathname, settings.config.root));
const pageInfo = getPageDataByViteID(internals, vid);
if (pageInfo) {
if (canBeInlined) {
diff --git a/packages/astro/src/core/build/vite-plugin-pages.ts b/packages/astro/src/core/build/vite-plugin-pages.ts
index ceaf87eeb..7b81ba398 100644
--- a/packages/astro/src/core/build/vite-plugin-pages.ts
+++ b/packages/astro/src/core/build/vite-plugin-pages.ts
@@ -10,7 +10,7 @@ export function vitePluginPages(opts: StaticBuildOptions, internals: BuildIntern
name: '@astro/plugin-build-pages',
options(options) {
- if (opts.astroConfig.output === 'static') {
+ if (opts.settings.config.output === 'static') {
return addRollupInput(options, [pagesVirtualModuleId]);
}
},
@@ -35,7 +35,7 @@ export function vitePluginPages(opts: StaticBuildOptions, internals: BuildIntern
i = 0;
let rendererItems = '';
- for (const renderer of opts.astroConfig._ctx.renderers) {
+ for (const renderer of opts.settings.renderers) {
const variable = `_renderer${i}`;
// Use unshift so that renderers are imported before user code, in case they set globals
// that user code depends on.
diff --git a/packages/astro/src/core/build/vite-plugin-ssr.ts b/packages/astro/src/core/build/vite-plugin-ssr.ts
index 3f8387f13..e2e6ff326 100644
--- a/packages/astro/src/core/build/vite-plugin-ssr.ts
+++ b/packages/astro/src/core/build/vite-plugin-ssr.ts
@@ -103,7 +103,7 @@ export async function injectManifest(buildOpts: StaticBuildOptions, internals: B
const staticFiles = internals.staticFiles;
const manifest = buildManifest(buildOpts, internals, Array.from(staticFiles));
- await runHookBuildSsr({ config: buildOpts.astroConfig, manifest, logging: buildOpts.logging });
+ await runHookBuildSsr({ config: buildOpts.settings.config, manifest, logging: buildOpts.logging });
const chunk = internals.ssrEntryChunk;
const code = chunk.code;
@@ -120,11 +120,11 @@ function buildManifest(
internals: BuildInternals,
staticFiles: string[]
): SerializedSSRManifest {
- const { astroConfig } = opts;
+ const { settings } = opts;
const routes: SerializedRouteInfo[] = [];
const entryModules = Object.fromEntries(internals.entrySpecifierToBundleMap.entries());
- if (astroConfig._ctx.scripts.some((script) => script.stage === 'page')) {
+ if (settings.scripts.some((script) => script.stage === 'page')) {
staticFiles.push(entryModules[PAGE_SCRIPT_ID]);
}
@@ -133,7 +133,7 @@ function buildManifest(
if (pageData.hoistedScript) {
scripts.unshift(pageData.hoistedScript);
}
- if (astroConfig._ctx.scripts.some((script) => script.stage === 'page')) {
+ if (settings.scripts.some((script) => script.stage === 'page')) {
scripts.push({ type: 'external', value: entryModules[PAGE_SCRIPT_ID] });
}
@@ -142,11 +142,11 @@ function buildManifest(
links: sortedCSS(pageData),
scripts: [
...scripts,
- ...astroConfig._ctx.scripts
+ ...settings.scripts
.filter((script) => script.stage === 'head-inline')
.map(({ stage, content }) => ({ stage, children: content })),
],
- routeData: serializeRouteData(pageData.route, astroConfig.trailingSlash),
+ routeData: serializeRouteData(pageData.route, settings.config.trailingSlash),
});
}
@@ -157,13 +157,13 @@ function buildManifest(
}
const ssrManifest: SerializedSSRManifest = {
- adapterName: opts.astroConfig._ctx.adapter!.name,
+ adapterName: opts.settings.adapter!.name,
routes,
- site: astroConfig.site,
- base: astroConfig.base,
+ site: settings.config.site,
+ base: settings.config.base,
markdown: {
- ...astroConfig.markdown,
- isAstroFlavoredMd: astroConfig.legacy.astroFlavoredMarkdown,
+ ...settings.config.markdown,
+ isAstroFlavoredMd: settings.config.legacy.astroFlavoredMarkdown,
},
pageMap: null as any,
renderers: [],
diff --git a/packages/astro/src/core/config.ts b/packages/astro/src/core/config/config.ts
index 58650613e..2c60257f4 100644
--- a/packages/astro/src/core/config.ts
+++ b/packages/astro/src/core/config/config.ts
@@ -1,90 +1,20 @@
-import type { RehypePlugin, RemarkPlugin, RemarkRehype } from '@astrojs/markdown-remark';
-import fs from 'fs';
-import type * as Postcss from 'postcss';
-import type { ILanguageRegistration, IThemeRegistration, Theme } from 'shiki';
import type { Arguments as Flags } from 'yargs-parser';
-import type { AstroConfig, AstroUserConfig, CLIFlags, ViteUserConfig } from '../@types/astro';
+import type { AstroConfig, AstroUserConfig, CLIFlags } from '../../@types/astro';
+import fs from 'fs';
import load, { ProloadError, resolve } from '@proload/core';
import loadTypeScript from '@proload/plugin-tsm';
import * as colors from 'kleur/colors';
import path from 'path';
-import postcssrc from 'postcss-load-config';
-import { BUNDLED_THEMES } from 'shiki';
-import * as tsr from 'tsconfig-resolver';
import { fileURLToPath, pathToFileURL } from 'url';
import * as vite from 'vite';
import { mergeConfig as mergeViteConfig } from 'vite';
-import { z } from 'zod';
-import jsxRenderer from '../jsx/renderer.js';
-import { LogOptions } from './logger/core.js';
-import { appendForwardSlash, prependForwardSlash, trimSlashes } from './path.js';
-import { arraify, isObject } from './util.js';
+import { LogOptions } from '../logger/core.js';
+import { arraify, isObject } from '../util.js';
+import { createRelativeSchema } from './schema.js';
load.use([loadTypeScript]);
-interface PostCSSConfigResult {
- options: Postcss.ProcessOptions;
- plugins: Postcss.Plugin[];
-}
-
-const ASTRO_CONFIG_DEFAULTS: AstroUserConfig & any = {
- root: '.',
- srcDir: './src',
- publicDir: './public',
- outDir: './dist',
- base: '/',
- trailingSlash: 'ignore',
- build: { format: 'directory' },
- server: {
- host: false,
- port: 3000,
- streaming: true,
- },
- style: { postcss: { options: {}, plugins: [] } },
- integrations: [],
- markdown: {
- drafts: false,
- syntaxHighlight: 'shiki',
- shikiConfig: {
- langs: [],
- theme: 'github-dark',
- wrap: false,
- },
- remarkPlugins: [],
- rehypePlugins: [],
- remarkRehype: {},
- },
- vite: {},
- legacy: {
- astroFlavoredMarkdown: false,
- },
-};
-
-async function resolvePostcssConfig(inlineOptions: any, root: URL): Promise<PostCSSConfigResult> {
- if (isObject(inlineOptions)) {
- const options = { ...inlineOptions };
- delete options.plugins;
- return {
- options,
- plugins: inlineOptions.plugins || [],
- };
- }
- const searchPath = typeof inlineOptions === 'string' ? inlineOptions : fileURLToPath(root);
- try {
- // @ts-ignore
- return await postcssrc({}, searchPath);
- } catch (err: any) {
- if (!/No PostCSS Config found/.test(err.message)) {
- throw err;
- }
- return {
- options: {},
- plugins: [],
- };
- }
-}
-
export const LEGACY_ASTRO_CONFIG_KEYS = new Set([
'projectRoot',
'src',
@@ -97,146 +27,6 @@ export const LEGACY_ASTRO_CONFIG_KEYS = new Set([
'devOptions',
]);
-export const AstroConfigSchema = z.object({
- root: z
- .string()
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.root)
- .transform((val) => new URL(val)),
- srcDir: z
- .string()
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.srcDir)
- .transform((val) => new URL(val)),
- publicDir: z
- .string()
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.publicDir)
- .transform((val) => new URL(val)),
- outDir: z
- .string()
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.outDir)
- .transform((val) => new URL(val)),
- site: z
- .string()
- .url()
- .optional()
- .transform((val) => (val ? appendForwardSlash(val) : val)),
- base: z
- .string()
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.base)
- .transform((val) => prependForwardSlash(appendForwardSlash(trimSlashes(val)))),
- trailingSlash: z
- .union([z.literal('always'), z.literal('never'), z.literal('ignore')])
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.trailingSlash),
- output: z
- .union([z.literal('static'), z.literal('server')])
- .optional()
- .default('static'),
- adapter: z.object({ name: z.string(), hooks: z.object({}).passthrough().default({}) }).optional(),
- integrations: z.preprocess(
- // preprocess
- (val) => (Array.isArray(val) ? val.flat(Infinity).filter(Boolean) : val),
- // validate
- z
- .array(z.object({ name: z.string(), hooks: z.object({}).passthrough().default({}) }))
- .default(ASTRO_CONFIG_DEFAULTS.integrations)
- ),
- build: z
- .object({
- format: z
- .union([z.literal('file'), z.literal('directory')])
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.build.format),
- })
- .optional()
- .default({}),
- server: z.preprocess(
- // preprocess
- // NOTE: Uses the "error" command here because this is overwritten by the
- // individualized schema parser with the correct command.
- (val) => (typeof val === 'function' ? val({ command: 'error' }) : val),
- // validate
- z
- .object({
- host: z
- .union([z.string(), z.boolean()])
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.server.host),
- port: z.number().optional().default(ASTRO_CONFIG_DEFAULTS.server.port),
- })
- .optional()
- .default({})
- ),
- style: z
- .object({
- postcss: z
- .object({
- options: z.any(),
- plugins: z.array(z.any()),
- })
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.style.postcss),
- })
- .optional()
- .default({}),
- markdown: z
- .object({
- drafts: z.boolean().default(false),
- syntaxHighlight: z
- .union([z.literal('shiki'), z.literal('prism'), z.literal(false)])
- .default(ASTRO_CONFIG_DEFAULTS.markdown.syntaxHighlight),
- shikiConfig: z
- .object({
- langs: z.custom<ILanguageRegistration>().array().default([]),
- theme: z
- .enum(BUNDLED_THEMES as [Theme, ...Theme[]])
- .or(z.custom<IThemeRegistration>())
- .default(ASTRO_CONFIG_DEFAULTS.markdown.shikiConfig.theme),
- wrap: z.boolean().or(z.null()).default(ASTRO_CONFIG_DEFAULTS.markdown.shikiConfig.wrap),
- })
- .default({}),
- remarkPlugins: z
- .union([
- z.string(),
- z.tuple([z.string(), z.any()]),
- z.custom<RemarkPlugin>((data) => typeof data === 'function'),
- z.tuple([z.custom<RemarkPlugin>((data) => typeof data === 'function'), z.any()]),
- ])
- .array()
- .default(ASTRO_CONFIG_DEFAULTS.markdown.remarkPlugins),
- rehypePlugins: z
- .union([
- z.string(),
- z.tuple([z.string(), z.any()]),
- z.custom<RehypePlugin>((data) => typeof data === 'function'),
- z.tuple([z.custom<RehypePlugin>((data) => typeof data === 'function'), z.any()]),
- ])
- .array()
- .default(ASTRO_CONFIG_DEFAULTS.markdown.rehypePlugins),
- remarkRehype: z
- .custom<RemarkRehype>((data) => data instanceof Object && !Array.isArray(data))
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.markdown.remarkRehype),
- extendDefaultPlugins: z.boolean().default(false),
- })
- .default({}),
- vite: z
- .custom<ViteUserConfig>((data) => data instanceof Object && !Array.isArray(data))
- .default(ASTRO_CONFIG_DEFAULTS.vite),
- legacy: z
- .object({
- astroFlavoredMarkdown: z
- .boolean()
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.legacy.astroFlavoredMarkdown),
- })
- .optional()
- .default({}),
-});
/** Turn raw config values into normalized values */
export async function validateConfig(
@@ -294,72 +84,10 @@ export async function validateConfig(
}
/* eslint-enable no-console */
- // We need to extend the global schema to add transforms that are relative to root.
- // This is type checked against the global schema to make sure we still match.
- const AstroConfigRelativeSchema = AstroConfigSchema.extend({
- root: z
- .string()
- .default(ASTRO_CONFIG_DEFAULTS.root)
- .transform((val) => new URL(appendForwardSlash(val), fileProtocolRoot)),
- srcDir: z
- .string()
- .default(ASTRO_CONFIG_DEFAULTS.srcDir)
- .transform((val) => new URL(appendForwardSlash(val), fileProtocolRoot)),
- publicDir: z
- .string()
- .default(ASTRO_CONFIG_DEFAULTS.publicDir)
- .transform((val) => new URL(appendForwardSlash(val), fileProtocolRoot)),
- outDir: z
- .string()
- .default(ASTRO_CONFIG_DEFAULTS.outDir)
- .transform((val) => new URL(appendForwardSlash(val), fileProtocolRoot)),
- server: z.preprocess(
- // preprocess
- (val) =>
- typeof val === 'function' ? val({ command: cmd === 'dev' ? 'dev' : 'preview' }) : val,
- // validate
- z
- .object({
- host: z
- .union([z.string(), z.boolean()])
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.server.host),
- port: z.number().optional().default(ASTRO_CONFIG_DEFAULTS.server.port),
- streaming: z.boolean().optional().default(true),
- })
- .optional()
- .default({})
- ),
- style: z
- .object({
- postcss: z.preprocess(
- (val) => resolvePostcssConfig(val, fileProtocolRoot),
- z
- .object({
- options: z.any(),
- plugins: z.array(z.any()),
- })
- .optional()
- .default(ASTRO_CONFIG_DEFAULTS.style.postcss)
- ),
- })
- .optional()
- .default({}),
- });
- const tsconfig = loadTSConfig(root);
+ const AstroConfigRelativeSchema = createRelativeSchema(cmd, fileProtocolRoot);
+
// First-Pass Validation
- const result = {
- ...(await AstroConfigRelativeSchema.parseAsync(userConfig)),
- _ctx: {
- pageExtensions: ['.astro', '.md', '.html'],
- tsConfig: tsconfig?.config,
- tsConfigPath: tsconfig?.path,
- scripts: [],
- renderers: [jsxRenderer],
- injectedRoutes: [],
- adapter: undefined,
- },
- };
+ const result = await AstroConfigRelativeSchema.parseAsync(userConfig);
// If successful, return the result as a verified AstroConfig object.
return result;
@@ -554,16 +282,6 @@ async function tryLoadConfig(
}
}
-function loadTSConfig(cwd: string | undefined): tsr.TsConfigResult | undefined {
- for (const searchName of ['tsconfig.json', 'jsconfig.json']) {
- const config = tsr.tsconfigResolverSync({ cwd, searchName });
- if (config.exists) {
- return config;
- }
- }
- return undefined;
-}
-
/**
* Attempt to load an `astro.config.mjs` file
* @deprecated
diff --git a/packages/astro/src/core/config/index.ts b/packages/astro/src/core/config/index.ts
new file mode 100644
index 000000000..b22083c4a
--- /dev/null
+++ b/packages/astro/src/core/config/index.ts
@@ -0,0 +1,20 @@
+
+export type {
+ AstroConfigSchema
+} from './schema';
+
+export {
+ openConfig,
+ resolveConfigPath,
+ resolveFlags,
+ resolveRoot,
+ validateConfig,
+} from './config.js';
+
+export {
+ createSettings
+} from './settings.js';
+
+export {
+ loadTSConfig
+} from './tsconfig.js';
diff --git a/packages/astro/src/core/config/schema.ts b/packages/astro/src/core/config/schema.ts
new file mode 100644
index 000000000..9bcfd15b3
--- /dev/null
+++ b/packages/astro/src/core/config/schema.ts
@@ -0,0 +1,271 @@
+import type { RehypePlugin, RemarkPlugin, RemarkRehype } from '@astrojs/markdown-remark';
+import type * as Postcss from 'postcss';
+import type { ILanguageRegistration, IThemeRegistration, Theme } from 'shiki';
+import type { AstroUserConfig, ViteUserConfig } from '../../@types/astro';
+
+import postcssrc from 'postcss-load-config';
+import { BUNDLED_THEMES } from 'shiki';
+import { fileURLToPath } from 'url';
+import { z } from 'zod';
+import { appendForwardSlash, prependForwardSlash, trimSlashes } from '../path.js';
+import { isObject } from '../util.js';
+
+const ASTRO_CONFIG_DEFAULTS: AstroUserConfig & any = {
+ root: '.',
+ srcDir: './src',
+ publicDir: './public',
+ outDir: './dist',
+ base: '/',
+ trailingSlash: 'ignore',
+ build: { format: 'directory' },
+ server: {
+ host: false,
+ port: 3000,
+ streaming: true,
+ },
+ style: { postcss: { options: {}, plugins: [] } },
+ integrations: [],
+ markdown: {
+ drafts: false,
+ syntaxHighlight: 'shiki',
+ shikiConfig: {
+ langs: [],
+ theme: 'github-dark',
+ wrap: false,
+ },
+ remarkPlugins: [],
+ rehypePlugins: [],
+ remarkRehype: {},
+ },
+ vite: {},
+ legacy: {
+ astroFlavoredMarkdown: false,
+ },
+};
+
+export const AstroConfigSchema = z.object({
+ root: z
+ .string()
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.root)
+ .transform((val) => new URL(val)),
+ srcDir: z
+ .string()
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.srcDir)
+ .transform((val) => new URL(val)),
+ publicDir: z
+ .string()
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.publicDir)
+ .transform((val) => new URL(val)),
+ outDir: z
+ .string()
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.outDir)
+ .transform((val) => new URL(val)),
+ site: z
+ .string()
+ .url()
+ .optional()
+ .transform((val) => (val ? appendForwardSlash(val) : val)),
+ base: z
+ .string()
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.base)
+ .transform((val) => prependForwardSlash(appendForwardSlash(trimSlashes(val)))),
+ trailingSlash: z
+ .union([z.literal('always'), z.literal('never'), z.literal('ignore')])
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.trailingSlash),
+ output: z
+ .union([z.literal('static'), z.literal('server')])
+ .optional()
+ .default('static'),
+ adapter: z.object({ name: z.string(), hooks: z.object({}).passthrough().default({}) }).optional(),
+ integrations: z.preprocess(
+ // preprocess
+ (val) => (Array.isArray(val) ? val.flat(Infinity).filter(Boolean) : val),
+ // validate
+ z
+ .array(z.object({ name: z.string(), hooks: z.object({}).passthrough().default({}) }))
+ .default(ASTRO_CONFIG_DEFAULTS.integrations)
+ ),
+ build: z
+ .object({
+ format: z
+ .union([z.literal('file'), z.literal('directory')])
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.build.format),
+ })
+ .optional()
+ .default({}),
+ server: z.preprocess(
+ // preprocess
+ // NOTE: Uses the "error" command here because this is overwritten by the
+ // individualized schema parser with the correct command.
+ (val) => (typeof val === 'function' ? val({ command: 'error' }) : val),
+ // validate
+ z
+ .object({
+ host: z
+ .union([z.string(), z.boolean()])
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.server.host),
+ port: z.number().optional().default(ASTRO_CONFIG_DEFAULTS.server.port),
+ })
+ .optional()
+ .default({})
+ ),
+ style: z
+ .object({
+ postcss: z
+ .object({
+ options: z.any(),
+ plugins: z.array(z.any()),
+ })
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.style.postcss),
+ })
+ .optional()
+ .default({}),
+ markdown: z
+ .object({
+ drafts: z.boolean().default(false),
+ syntaxHighlight: z
+ .union([z.literal('shiki'), z.literal('prism'), z.literal(false)])
+ .default(ASTRO_CONFIG_DEFAULTS.markdown.syntaxHighlight),
+ shikiConfig: z
+ .object({
+ langs: z.custom<ILanguageRegistration>().array().default([]),
+ theme: z
+ .enum(BUNDLED_THEMES as [Theme, ...Theme[]])
+ .or(z.custom<IThemeRegistration>())
+ .default(ASTRO_CONFIG_DEFAULTS.markdown.shikiConfig.theme),
+ wrap: z.boolean().or(z.null()).default(ASTRO_CONFIG_DEFAULTS.markdown.shikiConfig.wrap),
+ })
+ .default({}),
+ remarkPlugins: z
+ .union([
+ z.string(),
+ z.tuple([z.string(), z.any()]),
+ z.custom<RemarkPlugin>((data) => typeof data === 'function'),
+ z.tuple([z.custom<RemarkPlugin>((data) => typeof data === 'function'), z.any()]),
+ ])
+ .array()
+ .default(ASTRO_CONFIG_DEFAULTS.markdown.remarkPlugins),
+ rehypePlugins: z
+ .union([
+ z.string(),
+ z.tuple([z.string(), z.any()]),
+ z.custom<RehypePlugin>((data) => typeof data === 'function'),
+ z.tuple([z.custom<RehypePlugin>((data) => typeof data === 'function'), z.any()]),
+ ])
+ .array()
+ .default(ASTRO_CONFIG_DEFAULTS.markdown.rehypePlugins),
+ remarkRehype: z
+ .custom<RemarkRehype>((data) => data instanceof Object && !Array.isArray(data))
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.markdown.remarkRehype),
+ extendDefaultPlugins: z.boolean().default(false),
+ })
+ .default({}),
+ vite: z
+ .custom<ViteUserConfig>((data) => data instanceof Object && !Array.isArray(data))
+ .default(ASTRO_CONFIG_DEFAULTS.vite),
+ legacy: z
+ .object({
+ astroFlavoredMarkdown: z
+ .boolean()
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.legacy.astroFlavoredMarkdown),
+ })
+ .optional()
+ .default({}),
+});
+
+interface PostCSSConfigResult {
+ options: Postcss.ProcessOptions;
+ plugins: Postcss.Plugin[];
+}
+
+async function resolvePostcssConfig(inlineOptions: any, root: URL): Promise<PostCSSConfigResult> {
+ if (isObject(inlineOptions)) {
+ const options = { ...inlineOptions };
+ delete options.plugins;
+ return {
+ options,
+ plugins: inlineOptions.plugins || [],
+ };
+ }
+ const searchPath = typeof inlineOptions === 'string' ? inlineOptions : fileURLToPath(root);
+ try {
+ // @ts-ignore
+ return await postcssrc({}, searchPath);
+ } catch (err: any) {
+ if (!/No PostCSS Config found/.test(err.message)) {
+ throw err;
+ }
+ return {
+ options: {},
+ plugins: [],
+ };
+ }
+}
+
+export function createRelativeSchema(cmd: string, fileProtocolRoot: URL) {
+ // We need to extend the global schema to add transforms that are relative to root.
+ // This is type checked against the global schema to make sure we still match.
+ const AstroConfigRelativeSchema = AstroConfigSchema.extend({
+ root: z
+ .string()
+ .default(ASTRO_CONFIG_DEFAULTS.root)
+ .transform((val) => new URL(appendForwardSlash(val), fileProtocolRoot)),
+ srcDir: z
+ .string()
+ .default(ASTRO_CONFIG_DEFAULTS.srcDir)
+ .transform((val) => new URL(appendForwardSlash(val), fileProtocolRoot)),
+ publicDir: z
+ .string()
+ .default(ASTRO_CONFIG_DEFAULTS.publicDir)
+ .transform((val) => new URL(appendForwardSlash(val), fileProtocolRoot)),
+ outDir: z
+ .string()
+ .default(ASTRO_CONFIG_DEFAULTS.outDir)
+ .transform((val) => new URL(appendForwardSlash(val), fileProtocolRoot)),
+ server: z.preprocess(
+ // preprocess
+ (val) =>
+ typeof val === 'function' ? val({ command: cmd === 'dev' ? 'dev' : 'preview' }) : val,
+ // validate
+ z
+ .object({
+ host: z
+ .union([z.string(), z.boolean()])
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.server.host),
+ port: z.number().optional().default(ASTRO_CONFIG_DEFAULTS.server.port),
+ streaming: z.boolean().optional().default(true),
+ })
+ .optional()
+ .default({})
+ ),
+ style: z
+ .object({
+ postcss: z.preprocess(
+ (val) => resolvePostcssConfig(val, fileProtocolRoot),
+ z
+ .object({
+ options: z.any(),
+ plugins: z.array(z.any()),
+ })
+ .optional()
+ .default(ASTRO_CONFIG_DEFAULTS.style.postcss)
+ ),
+ })
+ .optional()
+ .default({}),
+ });
+
+ return AstroConfigRelativeSchema;
+}
diff --git a/packages/astro/src/core/config/settings.ts b/packages/astro/src/core/config/settings.ts
new file mode 100644
index 000000000..57af38618
--- /dev/null
+++ b/packages/astro/src/core/config/settings.ts
@@ -0,0 +1,31 @@
+import type {
+ AstroConfig,
+ AstroSettings,
+} from '../../@types/astro';
+import type { TsConfigJson } from 'tsconfig-resolver';
+
+import jsxRenderer from '../../jsx/renderer.js';
+
+export interface CreateSettings {
+ config: AstroConfig;
+ tsConfig?: TsConfigJson;
+ tsConfigPath?: string;
+}
+
+export function createSettings({
+ config,
+ tsConfig,
+ tsConfigPath,
+}: CreateSettings): AstroSettings {
+ return {
+ config,
+ tsConfig,
+ tsConfigPath,
+
+ adapter: undefined,
+ injectedRoutes: [],
+ pageExtensions: ['.astro', '.md', '.html'],
+ renderers: [jsxRenderer],
+ scripts: [],
+ };
+}
diff --git a/packages/astro/src/core/config/tsconfig.ts b/packages/astro/src/core/config/tsconfig.ts
new file mode 100644
index 000000000..ddfa72300
--- /dev/null
+++ b/packages/astro/src/core/config/tsconfig.ts
@@ -0,0 +1,11 @@
+import * as tsr from 'tsconfig-resolver';
+
+export function loadTSConfig(cwd: string | undefined): tsr.TsConfigResult | undefined {
+ for (const searchName of ['tsconfig.json', 'jsconfig.json']) {
+ const config = tsr.tsconfigResolverSync({ cwd, searchName });
+ if (config.exists) {
+ return config;
+ }
+ }
+ return undefined;
+}
diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts
index 8ee301344..9c4757f44 100644
--- a/packages/astro/src/core/create-vite.ts
+++ b/packages/astro/src/core/create-vite.ts
@@ -1,4 +1,4 @@
-import type { AstroConfig } from '../@types/astro';
+import type { AstroSettings } from '../@types/astro';
import type { LogOptions } from './logger/core';
import fs from 'fs';
@@ -25,7 +25,7 @@ import { resolveDependency } from './util.js';
export type ViteConfigWithSSR = vite.InlineConfig & { ssr?: vite.SSROptions };
interface CreateViteOptions {
- astroConfig: AstroConfig;
+ settings: AstroSettings;
logging: LogOptions;
mode: 'dev' | 'build' | string;
}
@@ -59,12 +59,12 @@ function getSsrNoExternalDeps(projectRoot: URL): string[] {
/** Return a common starting point for all Vite actions */
export async function createVite(
commandConfig: ViteConfigWithSSR,
- { astroConfig, logging, mode }: CreateViteOptions
+ { settings, logging, mode }: CreateViteOptions
): Promise<ViteConfigWithSSR> {
- const thirdPartyAstroPackages = await getAstroPackages(astroConfig);
+ const thirdPartyAstroPackages = await getAstroPackages(settings);
// Start with the Vite configuration that Astro core needs
const commonConfig: ViteConfigWithSSR = {
- cacheDir: fileURLToPath(new URL('./node_modules/.vite/', astroConfig.root)), // using local caches allows Astro to be used in monorepos, etc.
+ cacheDir: fileURLToPath(new URL('./node_modules/.vite/', settings.config.root)), // using local caches allows Astro to be used in monorepos, etc.
clearScreen: false, // we want to control the output, not Vite
logLevel: 'warn', // log warnings and errors only
appType: 'custom',
@@ -73,27 +73,27 @@ export async function createVite(
exclude: ['node-fetch'],
},
plugins: [
- configAliasVitePlugin({ config: astroConfig }),
- astroVitePlugin({ config: astroConfig, logging }),
- astroScriptsPlugin({ config: astroConfig }),
+ configAliasVitePlugin({ settings }),
+ astroVitePlugin({ settings, logging }),
+ astroScriptsPlugin({ settings }),
// The server plugin is for dev only and having it run during the build causes
// the build to run very slow as the filewatcher is triggered often.
- mode !== 'build' && astroViteServerPlugin({ config: astroConfig, logging }),
- envVitePlugin({ config: astroConfig }),
- astroConfig.legacy.astroFlavoredMarkdown
- ? legacyMarkdownVitePlugin({ config: astroConfig, logging })
- : markdownVitePlugin({ config: astroConfig, logging }),
+ mode !== 'build' && astroViteServerPlugin({ settings, logging }),
+ envVitePlugin({ settings }),
+ settings.config.legacy.astroFlavoredMarkdown
+ ? legacyMarkdownVitePlugin({ settings, logging })
+ : markdownVitePlugin({ settings, logging }),
htmlVitePlugin(),
- jsxVitePlugin({ config: astroConfig, logging }),
- astroPostprocessVitePlugin({ config: astroConfig }),
- astroIntegrationsContainerPlugin({ config: astroConfig, logging }),
- astroScriptsPageSSRPlugin({ config: astroConfig }),
+ jsxVitePlugin({ settings, logging }),
+ astroPostprocessVitePlugin({ settings }),
+ astroIntegrationsContainerPlugin({ settings, logging }),
+ astroScriptsPageSSRPlugin({ settings }),
],
- publicDir: fileURLToPath(astroConfig.publicDir),
- root: fileURLToPath(astroConfig.root),
+ publicDir: fileURLToPath(settings.config.publicDir),
+ root: fileURLToPath(settings.config.root),
envPrefix: 'PUBLIC_',
define: {
- 'import.meta.env.SITE': astroConfig.site ? `'${astroConfig.site}'` : 'undefined',
+ 'import.meta.env.SITE': settings.config.site ? `'${settings.config.site}'` : 'undefined',
},
server: {
hmr:
@@ -110,7 +110,7 @@ export async function createVite(
},
},
css: {
- postcss: astroConfig.style.postcss || {},
+ postcss: settings.config.style.postcss || {},
},
resolve: {
alias: [
@@ -129,7 +129,7 @@ export async function createVite(
conditions: ['astro'],
},
ssr: {
- noExternal: [...getSsrNoExternalDeps(astroConfig.root), ...thirdPartyAstroPackages],
+ noExternal: [...getSsrNoExternalDeps(settings.config.root), ...thirdPartyAstroPackages],
},
};
@@ -140,7 +140,7 @@ export async function createVite(
// 3. integration-provided vite config, via the `config:setup` hook
// 4. command vite config, passed as the argument to this function
let result = commonConfig;
- result = vite.mergeConfig(result, astroConfig.vite || {});
+ result = vite.mergeConfig(result, settings.config.vite || {});
result = vite.mergeConfig(result, commandConfig);
if (result.plugins) {
sortPlugins(result.plugins);
@@ -175,8 +175,8 @@ function sortPlugins(pluginOptions: vite.PluginOption[]) {
// Scans `projectRoot` for third-party Astro packages that could export an `.astro` file
// `.astro` files need to be built by Vite, so these should use `noExternal`
-async function getAstroPackages({ root }: AstroConfig): Promise<string[]> {
- const { astroPackages } = new DependencyWalker(root);
+async function getAstroPackages(settings: AstroSettings): Promise<string[]> {
+ const { astroPackages } = new DependencyWalker(settings.config.root);
return astroPackages;
}
diff --git a/packages/astro/src/core/dev/index.ts b/packages/astro/src/core/dev/index.ts
index e8069db90..0466d826b 100644
--- a/packages/astro/src/core/dev/index.ts
+++ b/packages/astro/src/core/dev/index.ts
@@ -2,7 +2,7 @@ import type { AstroTelemetry } from '@astrojs/telemetry';
import type { AddressInfo } from 'net';
import { performance } from 'perf_hooks';
import * as vite from 'vite';
-import type { AstroConfig } from '../../@types/astro';
+import type { AstroSettings } from '../../@types/astro';
import {
runHookConfigDone,
runHookConfigSetup,
@@ -28,17 +28,17 @@ export interface DevServer {
}
/** `astro dev` */
-export default async function dev(config: AstroConfig, options: DevOptions): Promise<DevServer> {
+export default async function dev(settings: AstroSettings, options: DevOptions): Promise<DevServer> {
const devStart = performance.now();
applyPolyfill();
await options.telemetry.record([]);
- config = await runHookConfigSetup({ config, command: 'dev', logging: options.logging });
- const { host, port } = config.server;
+ settings = await runHookConfigSetup({ settings, command: 'dev', logging: options.logging });
+ const { host, port } = settings.config.server;
const { isRestart = false } = options;
// The client entrypoint for renderers. Since these are imported dynamically
// we need to tell Vite to preoptimize them.
- const rendererClientEntries = config._ctx.renderers
+ const rendererClientEntries = settings.renderers
.map((r) => r.clientEntrypoint)
.filter(Boolean) as string[];
@@ -50,21 +50,21 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro
include: rendererClientEntries,
},
},
- { astroConfig: config, logging: options.logging, mode: 'dev' }
+ { settings, logging: options.logging, mode: 'dev' }
);
- await runHookConfigDone({ config, logging: options.logging });
+ await runHookConfigDone({ settings, logging: options.logging });
const viteServer = await vite.createServer(viteConfig);
- runHookServerSetup({ config, server: viteServer, logging: options.logging });
+ runHookServerSetup({ config: settings.config, server: viteServer, logging: options.logging });
await viteServer.listen(port);
const devServerAddressInfo = viteServer.httpServer!.address() as AddressInfo;
- const site = config.site ? new URL(config.base, config.site) : undefined;
+ const site = settings.config.site ? new URL(settings.config.base, settings.config.site) : undefined;
info(
options.logging,
null,
msg.devStart({
startupTime: performance.now() - devStart,
- config,
+ config: settings.config,
devServerAddressInfo,
site,
https: !!viteConfig.server?.https,
@@ -80,7 +80,7 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro
warn(options.logging, null, msg.fsStrictWarning());
}
- await runHookServerStart({ config, address: devServerAddressInfo, logging: options.logging });
+ await runHookServerStart({ config: settings.config, address: devServerAddressInfo, logging: options.logging });
return {
address: devServerAddressInfo,
@@ -89,7 +89,7 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro
},
stop: async () => {
await viteServer.close();
- await runHookServerDone({ config, logging: options.logging });
+ await runHookServerDone({ config: settings.config, logging: options.logging });
},
};
}
diff --git a/packages/astro/src/core/endpoint/dev/index.ts b/packages/astro/src/core/endpoint/dev/index.ts
index 342c9a4f4..b2f16225b 100644
--- a/packages/astro/src/core/endpoint/dev/index.ts
+++ b/packages/astro/src/core/endpoint/dev/index.ts
@@ -7,6 +7,6 @@ export async function call(ssrOpts: SSROptions) {
const [, mod] = await preload(ssrOpts);
return await callEndpoint(mod as unknown as EndpointHandler, {
...ssrOpts,
- ssr: ssrOpts.astroConfig.output === 'server',
+ ssr: ssrOpts.settings.config.output === 'server',
});
}
diff --git a/packages/astro/src/core/preview/index.ts b/packages/astro/src/core/preview/index.ts
index 04d5af61f..1d81df989 100644
--- a/packages/astro/src/core/preview/index.ts
+++ b/packages/astro/src/core/preview/index.ts
@@ -1,6 +1,6 @@
import type { AstroTelemetry } from '@astrojs/telemetry';
import type { AddressInfo } from 'net';
-import type { AstroConfig } from '../../@types/astro';
+import type { AstroSettings } from '../../@types/astro';
import type { LogOptions } from '../logger/core';
import fs from 'fs';
@@ -30,20 +30,20 @@ const HAS_FILE_EXTENSION_REGEXP = /^.*\.[^\\]+$/;
/** The primary dev action */
export default async function preview(
- config: AstroConfig,
+ settings: AstroSettings,
{ logging }: PreviewOptions
): Promise<PreviewServer> {
- if (config.output === 'server') {
+ if (settings.config.output === 'server') {
throw new Error(
`[preview] 'output: server' not supported. Use your deploy platform's preview command directly instead, if one exists. (ex: 'netlify dev', 'vercel dev', 'wrangler', etc.)`
);
}
const startServerTime = performance.now();
const defaultOrigin = 'http://localhost';
- const trailingSlash = config.trailingSlash;
+ const trailingSlash = settings.config.trailingSlash;
/** Base request URL. */
- let baseURL = new URL(config.base, new URL(config.site || '/', defaultOrigin));
- const staticFileServer = sirv(fileURLToPath(config.outDir), {
+ let baseURL = new URL(settings.config.base, new URL(settings.config.site || '/', defaultOrigin));
+ const staticFileServer = sirv(fileURLToPath(settings.config.outDir), {
dev: true,
etag: true,
maxAge: 0,
@@ -84,7 +84,7 @@ export default async function preview(
// HACK: rewrite req.url so that sirv finds the file
req.url = '/' + req.url?.replace(baseURL.pathname, '');
staticFileServer(req, res, () => {
- const errorPagePath = fileURLToPath(config.outDir + '/404.html');
+ const errorPagePath = fileURLToPath(settings.config.outDir + '/404.html');
if (fs.existsSync(errorPagePath)) {
res.statusCode = 404;
res.setHeader('Content-Type', 'text/html;charset=utf-8');
@@ -100,8 +100,8 @@ export default async function preview(
}
});
- let { port } = config.server;
- const host = getResolvedHostForHttpServer(config.server.host);
+ let { port } = settings.config.server;
+ const host = getResolvedHostForHttpServer(settings.config.server.host);
let httpServer: http.Server;
@@ -119,7 +119,7 @@ export default async function preview(
null,
msg.devStart({
startupTime: performance.now() - timerStart,
- config,
+ config: settings.config,
devServerAddressInfo,
https: false,
site: baseURL,
diff --git a/packages/astro/src/core/render/dev/index.ts b/packages/astro/src/core/render/dev/index.ts
index 672af88c2..3003d6417 100644
--- a/packages/astro/src/core/render/dev/index.ts
+++ b/packages/astro/src/core/render/dev/index.ts
@@ -1,7 +1,7 @@
import { fileURLToPath } from 'url';
import type { ViteDevServer } from 'vite';
import type {
- AstroConfig,
+ AstroSettings,
AstroRenderer,
ComponentInstance,
RouteData,
@@ -20,8 +20,8 @@ import { resolveClientDevPath } from './resolve.js';
import { getScriptsForURL } from './scripts.js';
export interface SSROptions {
- /** an instance of the AstroConfig */
- astroConfig: AstroConfig;
+ /** an instance of the AstroSettings */
+ settings: AstroSettings;
/** location of file on disk */
filePath: URL;
/** logging options */
@@ -58,18 +58,18 @@ async function loadRenderer(
export async function loadRenderers(
viteServer: ViteDevServer,
- astroConfig: AstroConfig
+ settings: AstroSettings
): Promise<SSRLoadedRenderer[]> {
- return Promise.all(astroConfig._ctx.renderers.map((r) => loadRenderer(viteServer, r)));
+ return Promise.all(settings.renderers.map((r) => loadRenderer(viteServer, r)));
}
export async function preload({
- astroConfig,
+ settings,
filePath,
viteServer,
-}: Pick<SSROptions, 'astroConfig' | 'filePath' | 'viteServer'>): Promise<ComponentPreload> {
+}: Pick<SSROptions, 'settings' | 'filePath' | 'viteServer'>): Promise<ComponentPreload> {
// Important: This needs to happen first, in case a renderer provides polyfills.
- const renderers = await loadRenderers(viteServer, astroConfig);
+ const renderers = await loadRenderers(viteServer, settings);
// Load the module from the Vite SSR Runtime.
const mod = (await viteServer.ssrLoadModule(fileURLToPath(filePath))) as ComponentInstance;
if (viteServer.config.mode === 'development' || !mod?.$$metadata) {
@@ -92,7 +92,7 @@ export async function render(
ssrOpts: SSROptions
): Promise<Response> {
const {
- astroConfig,
+ settings,
filePath,
logging,
mode,
@@ -104,10 +104,10 @@ export async function render(
viteServer,
} = ssrOpts;
// Add hoisted script tags
- const scripts = await getScriptsForURL(filePath, astroConfig, viteServer);
+ const scripts = await getScriptsForURL(filePath, viteServer);
// Inject HMR scripts
- if (isPage(filePath, astroConfig) && mode === 'development') {
+ if (isPage(filePath, settings) && mode === 'development') {
scripts.add({
props: { type: 'module', src: '/@vite/client' },
children: '',
@@ -122,13 +122,13 @@ export async function render(
}
// TODO: We should allow adding generic HTML elements to the head, not just scripts
- for (const script of astroConfig._ctx.scripts) {
+ for (const script of settings.scripts) {
if (script.stage === 'head-inline') {
scripts.add({
props: {},
children: script.content,
});
- } else if (script.stage === 'page' && isPage(filePath, astroConfig)) {
+ } else if (script.stage === 'page' && isPage(filePath, settings)) {
scripts.add({
props: { type: 'module', src: `/@id/${PAGE_SCRIPT_ID}` },
children: '',
@@ -167,13 +167,13 @@ export async function render(
});
let response = await coreRender({
- adapterName: astroConfig.adapter?.name,
+ adapterName: settings.config.adapter?.name,
links,
styles,
logging,
markdown: {
- ...astroConfig.markdown,
- isAstroFlavoredMd: astroConfig.legacy.astroFlavoredMarkdown,
+ ...settings.config.markdown,
+ isAstroFlavoredMd: settings.config.legacy.astroFlavoredMarkdown,
},
mod,
mode,
@@ -191,8 +191,8 @@ export async function render(
request,
route,
routeCache,
- site: astroConfig.site ? new URL(astroConfig.base, astroConfig.site).toString() : undefined,
- ssr: astroConfig.output === 'server',
+ site: settings.config.site ? new URL(settings.config.base, settings.config.site).toString() : undefined,
+ ssr: settings.config.output === 'server',
streaming: true,
});
diff --git a/packages/astro/src/core/render/dev/scripts.ts b/packages/astro/src/core/render/dev/scripts.ts
index 67e9bd1e4..1297a8a92 100644
--- a/packages/astro/src/core/render/dev/scripts.ts
+++ b/packages/astro/src/core/render/dev/scripts.ts
@@ -10,19 +10,17 @@ import { crawlGraph } from './vite.js';
export async function getScriptsForURL(
filePath: URL,
- astroConfig: AstroConfig,
viteServer: vite.ViteDevServer
): Promise<Set<SSRElement>> {
const elements = new Set<SSRElement>();
const rootID = viteID(filePath);
- let rootProjectFolder = slash(fileURLToPath(astroConfig.root));
const modInfo = viteServer.pluginContainer.getModuleInfo(rootID);
- addHoistedScripts(elements, modInfo, rootProjectFolder);
+ addHoistedScripts(elements, modInfo);
for await (const moduleNode of crawlGraph(viteServer, rootID, true)) {
const id = moduleNode.id;
if (id) {
const info = viteServer.pluginContainer.getModuleInfo(id);
- addHoistedScripts(elements, info, rootProjectFolder);
+ addHoistedScripts(elements, info);
}
}
@@ -32,7 +30,6 @@ export async function getScriptsForURL(
function addHoistedScripts(
set: Set<SSRElement>,
info: ModuleInfo | null,
- rootProjectFolder: string
) {
if (!info?.meta?.astro) {
return;
diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts
index 0efd29796..f2bcd9b4b 100644
--- a/packages/astro/src/core/routing/manifest/create.ts
+++ b/packages/astro/src/core/routing/manifest/create.ts
@@ -1,5 +1,6 @@
import type {
AstroConfig,
+ AstroSettings,
InjectedRoute,
ManifestData,
RouteData,
@@ -190,7 +191,7 @@ function injectedRouteToItem(
/** Create manifest of all static routes */
export function createRouteManifest(
- { config, cwd }: { config: AstroConfig; cwd?: string },
+ { settings, cwd }: { settings: AstroSettings; cwd?: string },
logging: LogOptions
): ManifestData {
const components: string[] = [];
@@ -198,7 +199,7 @@ export function createRouteManifest(
const validPageExtensions: Set<string> = new Set([
'.astro',
'.md',
- ...config._ctx.pageExtensions,
+ ...settings.pageExtensions,
]);
const validEndpointExtensions: Set<string> = new Set(['.js', '.ts']);
@@ -206,7 +207,7 @@ export function createRouteManifest(
let items: Item[] = [];
fs.readdirSync(dir).forEach((basename) => {
const resolved = path.join(dir, basename);
- const file = slash(path.relative(cwd || fileURLToPath(config.root), resolved));
+ const file = slash(path.relative(cwd || fileURLToPath(settings.config.root), resolved));
const isDir = fs.statSync(resolved).isDirectory();
const ext = path.extname(basename);
@@ -283,7 +284,7 @@ export function createRouteManifest(
} else {
components.push(item.file);
const component = item.file;
- const trailingSlash = item.isPage ? config.trailingSlash : 'never';
+ const trailingSlash = item.isPage ? settings.config.trailingSlash : 'never';
const pattern = getPattern(segments, trailingSlash);
const generate = getRouteGenerator(segments, trailingSlash);
const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic)
@@ -307,17 +308,18 @@ export function createRouteManifest(
});
}
+ const { config } = settings;
const pages = resolvePages(config);
if (fs.existsSync(pages)) {
walk(fileURLToPath(pages), [], []);
- } else if (config?._ctx?.injectedRoutes?.length === 0) {
- const pagesDirRootRelative = pages.href.slice(config.root.href.length);
+ } else if (settings.injectedRoutes.length === 0) {
+ const pagesDirRootRelative = pages.href.slice(settings.config.root.href.length);
warn(logging, 'astro', `Missing pages directory: ${pagesDirRootRelative}`);
}
- config?._ctx?.injectedRoutes
+ settings.injectedRoutes
?.sort((a, b) =>
// sort injected routes in the same way as user-defined routes
comparator(injectedRouteToItem({ config, cwd }, a), injectedRouteToItem({ config, cwd }, b))
diff --git a/packages/astro/src/core/util.ts b/packages/astro/src/core/util.ts
index 0abc9b40b..17fbc41a6 100644
--- a/packages/astro/src/core/util.ts
+++ b/packages/astro/src/core/util.ts
@@ -5,7 +5,7 @@ import resolve from 'resolve';
import slash from 'slash';
import { fileURLToPath, pathToFileURL } from 'url';
import type { ErrorPayload, ViteDevServer } from 'vite';
-import type { AstroConfig, RouteType } from '../@types/astro';
+import type { AstroConfig, AstroSettings, RouteType } from '../@types/astro';
import { prependForwardSlash, removeTrailingForwardSlash } from './path.js';
// process.env.PACKAGE_VERSION is injected when we build and publish the astro package.
@@ -172,21 +172,21 @@ function isPublicRoute(file: URL, config: AstroConfig): boolean {
return true;
}
-function endsWithPageExt(file: URL, config: AstroConfig): boolean {
- for (const ext of config._ctx.pageExtensions) {
+function endsWithPageExt(file: URL, settings: AstroSettings): boolean {
+ for (const ext of settings.pageExtensions) {
if (file.toString().endsWith(ext)) return true;
}
return false;
}
-export function isPage(file: URL, config: AstroConfig): boolean {
- if (!isInPagesDir(file, config)) return false;
- if (!isPublicRoute(file, config)) return false;
- return endsWithPageExt(file, config);
+export function isPage(file: URL, settings: AstroSettings): boolean {
+ if (!isInPagesDir(file, settings.config)) return false;
+ if (!isPublicRoute(file, settings.config)) return false;
+ return endsWithPageExt(file, settings);
}
-export function isModeServerWithNoAdapter(config: AstroConfig): boolean {
- return config.output === 'server' && !config._ctx.adapter;
+export function isModeServerWithNoAdapter(settings: AstroSettings): boolean {
+ return settings.config.output === 'server' && !settings.adapter;
}
export function relativeToSrcDir(config: AstroConfig, idOrUrl: URL | string) {
diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts
index 68d2a23ae..aec6fa881 100644
--- a/packages/astro/src/integrations/index.ts
+++ b/packages/astro/src/integrations/index.ts
@@ -3,6 +3,7 @@ import type { AddressInfo } from 'net';
import type { ViteDevServer } from 'vite';
import {
AstroConfig,
+ AstroSettings,
AstroRenderer,
BuildConfig,
HookParameters,
@@ -10,7 +11,7 @@ import {
} from '../@types/astro.js';
import type { SerializedSSRManifest } from '../core/app/types';
import type { PageBuildData } from '../core/build/types';
-import { mergeConfig } from '../core/config.js';
+import { mergeConfig } from '../core/config/config.js';
import type { ViteConfigWithSSR } from '../core/create-vite.js';
import { info, LogOptions } from '../core/logger/core.js';
@@ -34,21 +35,22 @@ async function withTakingALongTimeMsg<T>({
}
export async function runHookConfigSetup({
- config: _config,
+ settings,
command,
logging,
}: {
- config: AstroConfig;
+ settings: AstroSettings;
command: 'dev' | 'build';
logging: LogOptions;
-}): Promise<AstroConfig> {
+}): Promise<AstroSettings> {
// An adapter is an integration, so if one is provided push it.
- if (_config.adapter) {
- _config.integrations.push(_config.adapter);
+ if (settings.config.adapter) {
+ settings.config.integrations.push(settings.config.adapter);
}
-
- let updatedConfig: AstroConfig = { ..._config };
- for (const integration of _config.integrations) {
+
+ let updatedConfig: AstroConfig = { ...settings.config };
+ let updatedSettings: AstroSettings = { ...settings, config: updatedConfig };
+ for (const integration of settings.config.integrations) {
/**
* By making integration hooks optional, Astro can now ignore null or undefined Integrations
* instead of giving an internal error most people can't read
@@ -74,22 +76,22 @@ export async function runHookConfigSetup({
throw new Error(`Renderer ${bold(renderer.name)} does not provide a serverEntrypoint.`);
}
- updatedConfig._ctx.renderers.push(renderer);
+ updatedSettings.renderers.push(renderer);
},
injectScript: (stage, content) => {
- updatedConfig._ctx.scripts.push({ stage, content });
+ updatedSettings.scripts.push({ stage, content });
},
updateConfig: (newConfig) => {
updatedConfig = mergeConfig(updatedConfig, newConfig) as AstroConfig;
},
injectRoute: (injectRoute) => {
- updatedConfig._ctx.injectedRoutes.push(injectRoute);
+ updatedSettings.injectedRoutes.push(injectRoute);
},
};
// Semi-private `addPageExtension` hook
function addPageExtension(...input: (string | string[])[]) {
const exts = (input.flat(Infinity) as string[]).map((ext) => `.${ext.replace(/^\./, '')}`);
- updatedConfig._ctx.pageExtensions.push(...exts);
+ updatedSettings.pageExtensions.push(...exts);
}
Object.defineProperty(hooks, 'addPageExtension', {
value: addPageExtension,
@@ -103,29 +105,31 @@ export async function runHookConfigSetup({
});
}
}
- return updatedConfig;
+
+ updatedSettings.config = updatedConfig;
+ return updatedSettings;
}
export async function runHookConfigDone({
- config,
+ settings,
logging,
}: {
- config: AstroConfig;
+ settings: AstroSettings;
logging: LogOptions;
}) {
- for (const integration of config.integrations) {
+ for (const integration of settings.config.integrations) {
if (integration?.hooks?.['astro:config:done']) {
await withTakingALongTimeMsg({
name: integration.name,
hookResult: integration.hooks['astro:config:done']({
- config,
+ config: settings.config,
setAdapter(adapter) {
- if (config._ctx.adapter && config._ctx.adapter.name !== adapter.name) {
+ if (settings.adapter && settings.adapter.name !== adapter.name) {
throw new Error(
- `Integration "${integration.name}" conflicts with "${config._ctx.adapter.name}". You can only configure one deployment integration.`
+ `Integration "${integration.name}" conflicts with "${settings.adapter.name}". You can only configure one deployment integration.`
);
}
- config._ctx.adapter = adapter;
+ settings.adapter = adapter;
},
}),
logging,
diff --git a/packages/astro/src/vite-plugin-astro-postprocess/index.ts b/packages/astro/src/vite-plugin-astro-postprocess/index.ts
index 9d1fb460b..f9ef9281c 100644
--- a/packages/astro/src/vite-plugin-astro-postprocess/index.ts
+++ b/packages/astro/src/vite-plugin-astro-postprocess/index.ts
@@ -3,18 +3,18 @@ import type { ArrowFunctionExpressionKind, CallExpressionKind } from 'ast-types/
import type { NodePath } from 'ast-types/lib/node-path';
import { parse, print, types, visit } from 'recast';
import type { Plugin } from 'vite';
-import type { AstroConfig } from '../@types/astro';
+import type { AstroSettings } from '../@types/astro';
// Check for `Astro.glob()`. Be very forgiving of whitespace. False positives are okay.
const ASTRO_GLOB_REGEX = /Astro2?\s*\.\s*glob\s*\(/;
interface AstroPluginOptions {
- config: AstroConfig;
+ settings: AstroSettings;
}
// esbuild transforms the component-scoped Astro into Astro2, so need to check both.
const validAstroGlobalNames = new Set(['Astro', 'Astro2']);
-export default function astro({ config }: AstroPluginOptions): Plugin {
+export default function astro(_opts: AstroPluginOptions): Plugin {
return {
name: 'astro:postprocess',
async transform(code, id) {
diff --git a/packages/astro/src/vite-plugin-astro-server/index.ts b/packages/astro/src/vite-plugin-astro-server/index.ts
index 188b39f70..72f2ce9ba 100644
--- a/packages/astro/src/vite-plugin-astro-server/index.ts
+++ b/packages/astro/src/vite-plugin-astro-server/index.ts
@@ -1,7 +1,7 @@
import type http from 'http';
import mime from 'mime';
import type * as vite from 'vite';
-import type { AstroConfig, ManifestData } from '../@types/astro';
+import type { AstroSettings, ManifestData } from '../@types/astro';
import type { SSROptions } from '../core/render/dev/index';
import { Readable } from 'stream';
@@ -24,7 +24,7 @@ import { resolvePages } from '../core/util.js';
import notFoundTemplate, { subpathNotUsedTemplate } from '../template/4xx.js';
interface AstroPluginOptions {
- config: AstroConfig;
+ settings: AstroSettings;
logging: LogOptions;
}
@@ -94,7 +94,7 @@ async function writeSSRResult(webResponse: Response, res: http.ServerResponse) {
async function handle404Response(
origin: string,
- config: AstroConfig,
+ settings: AstroSettings,
req: http.IncomingMessage,
res: http.ServerResponse
) {
@@ -129,7 +129,7 @@ async function handle500Response(
}
}
-function getCustom404Route(config: AstroConfig, manifest: ManifestData) {
+function getCustom404Route({ config }: AstroSettings, manifest: ManifestData) {
// For Windows compat, use relative page paths to match the 404 route
const relPages = resolvePages(config).href.replace(config.root.href, '');
const pattern = new RegExp(`${appendForwardSlash(relPages)}404.(astro|md)`);
@@ -141,9 +141,10 @@ function log404(logging: LogOptions, pathname: string) {
}
export function baseMiddleware(
- config: AstroConfig,
+ settings: AstroSettings,
logging: LogOptions
): vite.Connect.NextHandleFunction {
+ const { config } = settings;
const site = config.site ? new URL(config.base, config.site) : undefined;
const devRoot = site ? site.pathname : '/';
@@ -184,13 +185,13 @@ async function matchRoute(
viteServer: vite.ViteDevServer,
logging: LogOptions,
manifest: ManifestData,
- config: AstroConfig
+ settings: AstroSettings
) {
const matches = matchAllRoutes(pathname, manifest);
for await (const maybeRoute of matches) {
- const filePath = new URL(`./${maybeRoute.component}`, config.root);
- const preloadedComponent = await preload({ astroConfig: config, filePath, viteServer });
+ const filePath = new URL(`./${maybeRoute.component}`, settings.config.root);
+ const preloadedComponent = await preload({ settings, filePath, viteServer });
const [, mod] = preloadedComponent;
// attempt to get static paths
// if this fails, we have a bad URL match!
@@ -200,7 +201,7 @@ async function matchRoute(
routeCache,
pathname: pathname,
logging,
- ssr: config.output === 'server',
+ ssr: settings.config.output === 'server',
});
if (paramsAndPropsRes !== GetParamsAndPropsError.NoMatchingStaticPath) {
@@ -222,11 +223,11 @@ async function matchRoute(
}
log404(logging, pathname);
- const custom404 = getCustom404Route(config, manifest);
+ const custom404 = getCustom404Route(settings, manifest);
if (custom404) {
- const filePath = new URL(`./${custom404.component}`, config.root);
- const preloadedComponent = await preload({ astroConfig: config, filePath, viteServer });
+ const filePath = new URL(`./${custom404.component}`, settings.config.root);
+ const preloadedComponent = await preload({ settings, filePath, viteServer });
const [, mod] = preloadedComponent;
return {
@@ -246,10 +247,11 @@ async function handleRequest(
viteServer: vite.ViteDevServer,
logging: LogOptions,
manifest: ManifestData,
- config: AstroConfig,
+ settings: AstroSettings,
req: http.IncomingMessage,
res: http.ServerResponse
) {
+ const { config } = settings;
const origin = `${viteServer.config.server.https ? 'https' : 'http'}://${req.headers.host}`;
const buildingToSSR = config.output === 'server';
// Ignore `.html` extensions and `index.html` in request URLS to ensure that
@@ -292,7 +294,7 @@ async function handleRequest(
viteServer,
logging,
manifest,
- config
+ settings
);
filePath = matchedRoute?.filePath;
@@ -306,7 +308,7 @@ async function handleRequest(
viteServer,
manifest,
logging,
- config,
+ settings,
req,
res
);
@@ -328,14 +330,15 @@ async function handleRoute(
viteServer: vite.ViteDevServer,
manifest: ManifestData,
logging: LogOptions,
- config: AstroConfig,
+ settings: AstroSettings,
req: http.IncomingMessage,
res: http.ServerResponse
): Promise<void> {
if (!matchedRoute) {
- return handle404Response(origin, config, req, res);
+ return handle404Response(origin, settings, req, res);
}
+ const { config } = settings;
const filePath: URL | undefined = matchedRoute.filePath;
const { route, preloadedComponent, mod } = matchedRoute;
const buildingToSSR = config.output === 'server';
@@ -363,7 +366,7 @@ async function handleRoute(
});
const options: SSROptions = {
- astroConfig: config,
+ settings,
filePath,
logging,
mode: 'development',
@@ -386,7 +389,7 @@ async function handleRoute(
viteServer,
logging,
manifest,
- config
+ settings
);
return handleRoute(
fourOhFourRoute,
@@ -398,7 +401,7 @@ async function handleRoute(
viteServer,
manifest,
logging,
- config,
+ settings,
req,
res
);
@@ -423,17 +426,17 @@ async function handleRoute(
}
}
-export default function createPlugin({ config, logging }: AstroPluginOptions): vite.Plugin {
+export default function createPlugin({ settings, logging }: AstroPluginOptions): vite.Plugin {
return {
name: 'astro:server',
configureServer(viteServer) {
let routeCache = new RouteCache(logging);
- let manifest: ManifestData = createRouteManifest({ config: config }, logging);
+ let manifest: ManifestData = createRouteManifest({ settings }, logging);
/** rebuild the route cache + manifest, as needed. */
function rebuildManifest(needsManifestRebuild: boolean, file: string) {
routeCache.clearAll();
if (needsManifestRebuild) {
- manifest = createRouteManifest({ config: config }, logging);
+ manifest = createRouteManifest({ settings }, logging);
}
}
// Rebuild route manifest on file change, if needed.
@@ -442,17 +445,17 @@ export default function createPlugin({ config, logging }: AstroPluginOptions): v
viteServer.watcher.on('change', rebuildManifest.bind(null, false));
return () => {
// Push this middleware to the front of the stack so that it can intercept responses.
- if (config.base !== '/') {
+ if (settings.config.base !== '/') {
viteServer.middlewares.stack.unshift({
route: '',
- handle: baseMiddleware(config, logging),
+ handle: baseMiddleware(settings, logging),
});
}
viteServer.middlewares.use(async (req, res) => {
if (!req.url || !req.method) {
throw new Error('Incomplete request');
}
- handleRequest(routeCache, viteServer, logging, manifest, config, req, res);
+ handleRequest(routeCache, viteServer, logging, manifest, settings, req, res);
});
};
},
diff --git a/packages/astro/src/vite-plugin-astro/index.ts b/packages/astro/src/vite-plugin-astro/index.ts
index 5d1bf2c18..20fa69053 100644
--- a/packages/astro/src/vite-plugin-astro/index.ts
+++ b/packages/astro/src/vite-plugin-astro/index.ts
@@ -1,6 +1,6 @@
import type { PluginContext, SourceDescription } from 'rollup';
import type * as vite from 'vite';
-import type { AstroConfig } from '../@types/astro';
+import type { AstroSettings } from '../@types/astro';
import type { LogOptions } from '../core/logger/core.js';
import type { ViteStyleTransformer } from '../vite-style-transform';
import type { PluginMetadata as AstroPluginMetadata } from './types';
@@ -22,12 +22,13 @@ import { parseAstroRequest, ParsedRequestResult } from './query.js';
const FRONTMATTER_PARSE_REGEXP = /^\-\-\-(.*)^\-\-\-/ms;
interface AstroPluginOptions {
- config: AstroConfig;
+ settings: AstroSettings;
logging: LogOptions;
}
/** Transform .astro files for Vite */
-export default function astro({ config, logging }: AstroPluginOptions): vite.Plugin {
+export default function astro({ settings, logging }: AstroPluginOptions): vite.Plugin {
+ const { config } = settings;
function normalizeFilename(filename: string) {
if (filename.startsWith('/@fs')) {
filename = filename.slice('/@fs'.length);
diff --git a/packages/astro/src/vite-plugin-config-alias/index.ts b/packages/astro/src/vite-plugin-config-alias/index.ts
index 4a9923eda..aa4f564b7 100644
--- a/packages/astro/src/vite-plugin-config-alias/index.ts
+++ b/packages/astro/src/vite-plugin-config-alias/index.ts
@@ -1,5 +1,5 @@
import * as path from 'path';
-import type { AstroConfig } from '../@types/astro';
+import type { AstroSettings } from '../@types/astro';
import type * as vite from 'vite';
@@ -13,10 +13,10 @@ export declare interface Alias {
const normalize = (pathname: string) => String(pathname).split(path.sep).join(path.posix.sep);
/** Returns a list of compiled aliases. */
-const getConfigAlias = (astroConfig: AstroConfig): Alias[] | null => {
+const getConfigAlias = (settings: AstroSettings): Alias[] | null => {
/** Closest tsconfig.json or jsconfig.json */
- const config = astroConfig._ctx.tsConfig;
- const configPath = astroConfig._ctx.tsConfigPath;
+ const config = settings.tsConfig;
+ const configPath = settings.tsConfigPath;
// if no config was found, return null
if (!config || !configPath) return null;
@@ -77,12 +77,13 @@ const getConfigAlias = (astroConfig: AstroConfig): Alias[] | null => {
/** Returns a Vite plugin used to alias pathes from tsconfig.json and jsconfig.json. */
export default function configAliasVitePlugin({
- config: astroConfig,
+ settings,
}: {
- config: AstroConfig;
+ settings: AstroSettings;
}): vite.PluginOption {
+ const { config } = settings;
/** Aliases from the tsconfig.json or jsconfig.json configuration. */
- const configAlias = getConfigAlias(astroConfig);
+ const configAlias = getConfigAlias(settings);
// if no config alias was found, bypass this plugin
if (!configAlias) return {} as vite.PluginOption;
diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts
index f513771db..2eeccc886 100644
--- a/packages/astro/src/vite-plugin-env/index.ts
+++ b/packages/astro/src/vite-plugin-env/index.ts
@@ -2,10 +2,10 @@ import MagicString from 'magic-string';
import { fileURLToPath } from 'url';
import type * as vite from 'vite';
import { loadEnv } from 'vite';
-import type { AstroConfig } from '../@types/astro';
+import type { AstroConfig, AstroSettings } from '../@types/astro';
interface EnvPluginOptions {
- config: AstroConfig;
+ settings: AstroSettings;
}
function getPrivateEnv(viteConfig: vite.ResolvedConfig, astroConfig: AstroConfig) {
@@ -51,12 +51,13 @@ function getReferencedPrivateKeys(source: string, privateEnv: Record<string, any
}
export default function envVitePlugin({
- config: astroConfig,
+ settings,
}: EnvPluginOptions): vite.PluginOption {
let privateEnv: Record<string, any> | null;
let config: vite.ResolvedConfig;
let replacements: Record<string, string>;
let pattern: RegExp | undefined;
+ const { config: astroConfig } = settings;
return {
name: 'astro:vite-plugin-env',
enforce: 'pre',
diff --git a/packages/astro/src/vite-plugin-integrations-container/index.ts b/packages/astro/src/vite-plugin-integrations-container/index.ts
index f386cd055..a7967092e 100644
--- a/packages/astro/src/vite-plugin-integrations-container/index.ts
+++ b/packages/astro/src/vite-plugin-integrations-container/index.ts
@@ -1,20 +1,20 @@
import { Plugin as VitePlugin } from 'vite';
-import { AstroConfig } from '../@types/astro.js';
+import { AstroSettings } from '../@types/astro.js';
import { LogOptions } from '../core/logger/core.js';
import { runHookServerSetup } from '../integrations/index.js';
/** Connect Astro integrations into Vite, as needed. */
export default function astroIntegrationsContainerPlugin({
- config,
+ settings,
logging,
}: {
- config: AstroConfig;
+ settings: AstroSettings;
logging: LogOptions;
}): VitePlugin {
return {
name: 'astro:integration-container',
configureServer(server) {
- runHookServerSetup({ config, server, logging });
+ runHookServerSetup({ config: settings.config, server, logging });
},
};
}
diff --git a/packages/astro/src/vite-plugin-jsx/index.ts b/packages/astro/src/vite-plugin-jsx/index.ts
index de9eb3d94..ca0885343 100644
--- a/packages/astro/src/vite-plugin-jsx/index.ts
+++ b/packages/astro/src/vite-plugin-jsx/index.ts
@@ -1,7 +1,7 @@
import type { TransformResult } from 'rollup';
import type { TsConfigJson } from 'tsconfig-resolver';
import type { Plugin, ResolvedConfig } from 'vite';
-import type { AstroConfig, AstroRenderer } from '../@types/astro';
+import type { AstroSettings, AstroRenderer } from '../@types/astro';
import type { LogOptions } from '../core/logger/core.js';
import type { PluginMetadata } from '../vite-plugin-astro/types';
@@ -152,12 +152,12 @@ async function transformJSX({
}
interface AstroPluginJSXOptions {
- config: AstroConfig;
+ settings: AstroSettings;
logging: LogOptions;
}
/** Use Astro config to allow for alternate or multiple JSX renderers (by default Vite will assume React) */
-export default function jsx({ config, logging }: AstroPluginJSXOptions): Plugin {
+export default function jsx({ settings, logging }: AstroPluginJSXOptions): Plugin {
let viteConfig: ResolvedConfig;
const jsxRenderers = new Map<string, AstroRenderer>();
const jsxRenderersIntegrationOnly = new Map<string, AstroRenderer>();
@@ -172,7 +172,7 @@ export default function jsx({ config, logging }: AstroPluginJSXOptions): Plugin
enforce: 'pre', // run transforms before other plugins
async configResolved(resolvedConfig) {
viteConfig = resolvedConfig;
- const possibleRenderers = collectJSXRenderers(config._ctx.renderers);
+ const possibleRenderers = collectJSXRenderers(settings.renderers);
for (const [importSource, renderer] of possibleRenderers) {
jsxRenderers.set(importSource, renderer);
if (importSource === 'astro') {
@@ -230,7 +230,7 @@ export default function jsx({ config, logging }: AstroPluginJSXOptions): Plugin
// Check the tsconfig
if (!importSource) {
- const compilerOptions = config._ctx.tsConfig?.compilerOptions;
+ const compilerOptions = settings.tsConfig?.compilerOptions;
importSource = (compilerOptions as FixedCompilerOptions | undefined)?.jsxImportSource;
}
diff --git a/packages/astro/src/vite-plugin-markdown-legacy/index.ts b/packages/astro/src/vite-plugin-markdown-legacy/index.ts
index dd7259e2c..52ec713fb 100644
--- a/packages/astro/src/vite-plugin-markdown-legacy/index.ts
+++ b/packages/astro/src/vite-plugin-markdown-legacy/index.ts
@@ -5,7 +5,7 @@ import fs from 'fs';
import matter from 'gray-matter';
import { fileURLToPath } from 'url';
import type { Plugin, ViteDevServer } from 'vite';
-import type { AstroConfig } from '../@types/astro';
+import type { AstroSettings } from '../@types/astro';
import { pagesVirtualModuleId } from '../core/app/index.js';
import { cachedCompilation, CompileProps } from '../core/compile/index.js';
import { collectErrorMetadata } from '../core/errors.js';
@@ -19,7 +19,7 @@ import {
} from '../vite-style-transform/index.js';
interface AstroPluginOptions {
- config: AstroConfig;
+ settings: AstroSettings;
logging: LogOptions;
}
@@ -38,7 +38,8 @@ function safeMatter(source: string, id: string) {
// TODO: Clean up some of the shared logic between this Markdown plugin and the Astro plugin.
// Both end up connecting a `load()` hook to the Astro compiler, and share some copy-paste
// logic in how that is done.
-export default function markdown({ config, logging }: AstroPluginOptions): Plugin {
+export default function markdown({ settings }: AstroPluginOptions): Plugin {
+ const { config } = settings;
function normalizeFilename(filename: string) {
if (filename.startsWith('/@fs')) {
filename = filename.slice('/@fs'.length);
diff --git a/packages/astro/src/vite-plugin-markdown/index.ts b/packages/astro/src/vite-plugin-markdown/index.ts
index 6d6c1dd4b..e40fbf959 100644
--- a/packages/astro/src/vite-plugin-markdown/index.ts
+++ b/packages/astro/src/vite-plugin-markdown/index.ts
@@ -2,7 +2,7 @@ import { renderMarkdown } from '@astrojs/markdown-remark';
import fs from 'fs';
import matter from 'gray-matter';
import type { Plugin } from 'vite';
-import type { AstroConfig } from '../@types/astro';
+import type { AstroSettings } from '../@types/astro';
import { collectErrorMetadata } from '../core/errors.js';
import type { LogOptions } from '../core/logger/core.js';
import { warn } from '../core/logger/core.js';
@@ -10,7 +10,7 @@ import type { PluginMetadata } from '../vite-plugin-astro/types.js';
import { getFileInfo, safelyGetAstroData } from '../vite-plugin-utils/index.js';
interface AstroPluginOptions {
- config: AstroConfig;
+ settings: AstroSettings;
logging: LogOptions;
}
@@ -23,7 +23,7 @@ function safeMatter(source: string, id: string) {
}
}
-export default function markdown({ config, logging }: AstroPluginOptions): Plugin {
+export default function markdown({ settings, logging }: AstroPluginOptions): Plugin {
return {
enforce: 'pre',
name: 'astro:markdown',
@@ -33,11 +33,11 @@ export default function markdown({ config, logging }: AstroPluginOptions): Plugi
// to escape "import.meta.env" ourselves.
async load(id) {
if (id.endsWith('.md')) {
- const { fileId, fileUrl } = getFileInfo(id, config);
+ const { fileId, fileUrl } = getFileInfo(id, settings.config);
const rawFile = await fs.promises.readFile(fileId, 'utf-8');
const raw = safeMatter(rawFile, id);
const renderResult = await renderMarkdown(raw.content, {
- ...config.markdown,
+ ...settings.config.markdown,
fileURL: new URL(`file://${fileId}`),
isAstroFlavoredMd: false,
} as any);
diff --git a/packages/astro/src/vite-plugin-scripts/index.ts b/packages/astro/src/vite-plugin-scripts/index.ts
index d055cf59d..00cbe690f 100644
--- a/packages/astro/src/vite-plugin-scripts/index.ts
+++ b/packages/astro/src/vite-plugin-scripts/index.ts
@@ -1,5 +1,5 @@
import { ConfigEnv, Plugin as VitePlugin } from 'vite';
-import { AstroConfig, InjectedScriptStage } from '../@types/astro.js';
+import { AstroSettings, InjectedScriptStage } from '../@types/astro.js';
// NOTE: We can't use the virtual "\0" ID convention because we need to
// inject these as ESM imports into actual code, where they would not
@@ -11,7 +11,7 @@ export const BEFORE_HYDRATION_SCRIPT_ID = `${SCRIPT_ID_PREFIX}${
export const PAGE_SCRIPT_ID = `${SCRIPT_ID_PREFIX}${'page' as InjectedScriptStage}.js`;
export const PAGE_SSR_SCRIPT_ID = `${SCRIPT_ID_PREFIX}${'page-ssr' as InjectedScriptStage}.js`;
-export default function astroScriptsPlugin({ config }: { config: AstroConfig }): VitePlugin {
+export default function astroScriptsPlugin({ settings }: { settings: AstroSettings }): VitePlugin {
let env: ConfigEnv | undefined = undefined;
return {
name: 'astro:scripts',
@@ -29,19 +29,19 @@ export default function astroScriptsPlugin({ config }: { config: AstroConfig }):
async load(id) {
if (id === BEFORE_HYDRATION_SCRIPT_ID) {
- return config._ctx.scripts
+ return settings.scripts
.filter((s) => s.stage === 'before-hydration')
.map((s) => s.content)
.join('\n');
}
if (id === PAGE_SCRIPT_ID) {
- return config._ctx.scripts
+ return settings.scripts
.filter((s) => s.stage === 'page')
.map((s) => s.content)
.join('\n');
}
if (id === PAGE_SSR_SCRIPT_ID) {
- return config._ctx.scripts
+ return settings.scripts
.filter((s) => s.stage === 'page-ssr')
.map((s) => s.content)
.join('\n');
@@ -49,7 +49,7 @@ export default function astroScriptsPlugin({ config }: { config: AstroConfig }):
return null;
},
buildStart(options) {
- const hasHydrationScripts = config._ctx.scripts.some((s) => s.stage === 'before-hydration');
+ const hasHydrationScripts = settings.scripts.some((s) => s.stage === 'before-hydration');
if (hasHydrationScripts && env?.command === 'build' && !env?.ssrBuild) {
this.emitFile({
type: 'chunk',
diff --git a/packages/astro/src/vite-plugin-scripts/page-ssr.ts b/packages/astro/src/vite-plugin-scripts/page-ssr.ts
index 9aa3425f5..4307b9d42 100644
--- a/packages/astro/src/vite-plugin-scripts/page-ssr.ts
+++ b/packages/astro/src/vite-plugin-scripts/page-ssr.ts
@@ -1,17 +1,17 @@
import { Plugin as VitePlugin } from 'vite';
-import { AstroConfig } from '../@types/astro.js';
+import { AstroSettings } from '../@types/astro.js';
import { PAGE_SSR_SCRIPT_ID } from './index.js';
import ancestor from 'common-ancestor-path';
import MagicString from 'magic-string';
import { isPage } from '../core/util.js';
-export default function astroScriptsPostPlugin({ config }: { config: AstroConfig }): VitePlugin {
+export default function astroScriptsPostPlugin({ settings }: { settings: AstroSettings }): VitePlugin {
function normalizeFilename(filename: string) {
if (filename.startsWith('/@fs')) {
filename = filename.slice('/@fs'.length);
- } else if (filename.startsWith('/') && !ancestor(filename, config.root.pathname)) {
- filename = new URL('.' + filename, config.root).pathname;
+ } else if (filename.startsWith('/') && !ancestor(filename, settings.config.root.pathname)) {
+ filename = new URL('.' + filename, settings.config.root).pathname;
}
return filename;
}
@@ -23,7 +23,7 @@ export default function astroScriptsPostPlugin({ config }: { config: AstroConfig
transform(this, code, id, options) {
if (!options?.ssr) return;
- const hasInjectedScript = config._ctx.scripts.some((s) => s.stage === 'page-ssr');
+ const hasInjectedScript = settings.scripts.some((s) => s.stage === 'page-ssr');
if (!hasInjectedScript) return;
const filename = normalizeFilename(id);
@@ -35,7 +35,7 @@ export default function astroScriptsPostPlugin({ config }: { config: AstroConfig
return;
}
- const fileIsPage = isPage(fileURL, config);
+ const fileIsPage = isPage(fileURL, settings);
if (!fileIsPage) return;
const s = new MagicString(code, { filename });
diff --git a/packages/astro/test/config-mode.test.js b/packages/astro/test/config-mode.test.js
index aeb09ad2f..76c45ba48 100644
--- a/packages/astro/test/config-mode.test.js
+++ b/packages/astro/test/config-mode.test.js
@@ -3,7 +3,7 @@ import { load as cheerioLoad } from 'cheerio';
import { loadFixture } from './test-utils.js';
import testAdapter from './test-adapter.js';
-describe('AstroConfig - config.mode', () => {
+describe('AstroConfig - config.output', () => {
describe(`output: 'server'`, () => {
describe('deploy config provided', () => {
/** @type {import('./test-utils').Fixture} */
@@ -58,7 +58,7 @@ describe('AstroConfig - config.mode', () => {
});
describe(`output: 'static'`, () => {
- describe('Deploy config omitted', () => {
+ describe('Output config omitted', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
diff --git a/packages/astro/test/config.test.js b/packages/astro/test/config.test.js
deleted file mode 100644
index bd03b89bc..000000000
--- a/packages/astro/test/config.test.js
+++ /dev/null
@@ -1,126 +0,0 @@
-import { expect } from 'chai';
-import { loadFixture, cliServerLogSetup } from './test-utils.js';
-import { fileURLToPath } from 'url';
-import { isIPv4 } from 'net';
-
-describe('config', () => {
- let hostFixture;
- let portFixture;
-
- before(async () => {
- [hostFixture, portFixture] = await Promise.all([
- loadFixture({
- root: './fixtures/config-host/',
- server: {
- host: true,
- },
- }),
- loadFixture({
- root: './fixtures/config-host/',
- server: {
- port: 5006,
- },
- }),
- ]);
- });
-
- describe('host', () => {
- it('can be specified in astro.config.mjs', async () => {
- expect(hostFixture.config.server.host).to.equal(true);
- });
-
- it('can be specified via --host flag', async () => {
- const projectRootURL = new URL('./fixtures/astro-basic/', import.meta.url);
- const { network } = await cliServerLogSetup([
- '--root',
- fileURLToPath(projectRootURL),
- '--host',
- ]);
-
- const networkURL = new URL(network);
- expect(isIPv4(networkURL.hostname)).to.be.equal(
- true,
- `Expected network URL to respect --host flag`
- );
- });
- });
-
- describe('path', () => {
- it('can be passed via --config', async () => {
- const projectRootURL = new URL('./fixtures/astro-basic/', import.meta.url);
- const configFileURL = new URL('./fixtures/config-path/config/my-config.mjs', import.meta.url);
- const { network } = await cliServerLogSetup([
- '--root',
- fileURLToPath(projectRootURL),
- '--config',
- configFileURL.pathname,
- ]);
-
- const networkURL = new URL(network);
- expect(isIPv4(networkURL.hostname)).to.be.equal(
- true,
- `Expected network URL to respect --host flag`
- );
- });
- });
-
- describe('relative path', () => {
- it('can be passed via relative --config', async () => {
- const projectRootURL = new URL('./fixtures/astro-basic/', import.meta.url);
- const configFileURL = 'my-config.mjs';
- const { local } = await cliServerLogSetup([
- '--root',
- fileURLToPath(projectRootURL),
- '--config',
- configFileURL,
- ]);
-
- const localURL = new URL(local);
- expect(localURL.port).to.equal('8080');
- });
- });
-
- describe('relative path with leading ./', () => {
- it('can be passed via relative --config', async () => {
- const projectRootURL = new URL('./fixtures/astro-basic/', import.meta.url);
- const configFileURL = './my-config.mjs';
- const { local } = await cliServerLogSetup([
- '--root',
- fileURLToPath(projectRootURL),
- '--config',
- configFileURL,
- ]);
-
- const localURL = new URL(local);
- expect(localURL.port).to.equal('8080');
- });
- });
-
- describe('incorrect path', () => {
- it('fails and exits when config does not exist', async () => {
- const projectRootURL = new URL('./fixtures/astro-basic/', import.meta.url);
- const configFileURL = './does-not-exist.mjs';
- let exit = 0;
- try {
- await cliServerLogSetup([
- '--root',
- fileURLToPath(projectRootURL),
- '--config',
- configFileURL,
- ]);
- } catch (e) {
- if (e.message.includes('Unable to resolve --config')) {
- exit = 1;
- }
- }
-
- expect(exit).to.equal(1, 'Throws helpful error message when --config does not exist');
- });
- });
-
- describe('port', () => {
- it('can be specified in astro.config.mjs', async () => {
- expect(portFixture.config.server.port).to.deep.equal(5006);
- });
- });
-});
diff --git a/packages/astro/test/test-utils.js b/packages/astro/test/test-utils.js
index e1e4f73e7..b53e1acca 100644
--- a/packages/astro/test/test-utils.js
+++ b/packages/astro/test/test-utils.js
@@ -2,7 +2,8 @@ import { execa } from 'execa';
import { polyfill } from '@astrojs/webapi';
import fs from 'fs';
import { fileURLToPath } from 'url';
-import { loadConfig } from '../dist/core/config.js';
+import { loadConfig } from '../dist/core/config/config.js';
+import { createSettings, loadTSConfig } from '../dist/core/config/index.js';
import dev from '../dist/core/dev/index.js';
import build from '../dist/core/build/index.js';
import preview from '../dist/core/preview/index.js';
@@ -18,7 +19,7 @@ polyfill(globalThis, {
/**
* @typedef {import('node-fetch').Response} Response
- * @typedef {import('../src/core/dev/index').DevServer} DevServer
+ * @typedef {import('../src/core/dev/index').DedvServer} DevServer
* @typedef {import('../src/@types/astro').AstroConfig} AstroConfig
* @typedef {import('../src/core/preview/index').PreviewServer} PreviewServer
* @typedef {import('../src/core/app/index').App} App
@@ -39,6 +40,12 @@ polyfill(globalThis, {
* @property {() => Promise<void>} onNextChange
*/
+/** @type {import('../src/core/logger/core').LogOptions} */
+export const defaultLogging = {
+ dest: nodeLogDestination,
+ level: 'error',
+};
+
/**
* Load Astro fixture
* @param {AstroConfig} inlineConfig Astro config partial (note: must specify `root`)
@@ -75,10 +82,7 @@ export async function loadFixture(inlineConfig) {
}
/** @type {import('../src/core/logger/core').LogOptions} */
- const logging = {
- dest: nodeLogDestination,
- level: 'error',
- };
+ const logging = defaultLogging;
// Load the config.
let config = await loadConfig({ cwd: fileURLToPath(cwd), logging });
@@ -91,10 +95,16 @@ export async function loadFixture(inlineConfig) {
if (inlineConfig.base && !inlineConfig.base.endsWith('/')) {
config.base = inlineConfig.base + '/';
}
+ let tsconfig = loadTSConfig(fileURLToPath(cwd));
+ let settings = createSettings({
+ config,
+ tsConfig: tsconfig?.config,
+ tsConfigPath: tsconfig?.path
+ });
if (config.integrations.find((integration) => integration.name === '@astrojs/mdx')) {
// Enable default JSX integration. It needs to come first, so unshift rather than push!
const { default: jsxRenderer } = await import('astro/jsx/renderer.js');
- config._ctx.renderers.unshift(jsxRenderer);
+ settings.renderers.unshift(jsxRenderer);
}
/** @type {import('@astrojs/telemetry').AstroTelemetry} */
@@ -133,9 +143,9 @@ export async function loadFixture(inlineConfig) {
let devServer;
return {
- build: (opts = {}) => build(config, { logging, telemetry, ...opts }),
+ build: (opts = {}) => build(settings, { logging, telemetry, ...opts }),
startDevServer: async (opts = {}) => {
- devServer = await dev(config, { logging, telemetry, ...opts });
+ devServer = await dev(settings, { logging, telemetry, ...opts });
config.server.port = devServer.address.port; // update port
return devServer;
},
@@ -143,7 +153,7 @@ export async function loadFixture(inlineConfig) {
resolveUrl,
fetch: (url, init) => fetch(resolveUrl(url), init),
preview: async (opts = {}) => {
- const previewServer = await preview(config, { logging, telemetry, ...opts });
+ const previewServer = await preview(settings, { logging, telemetry, ...opts });
return previewServer;
},
readFile: (filePath, encoding) =>
diff --git a/packages/astro/test/units/config/config-server.test.js b/packages/astro/test/units/config/config-server.test.js
new file mode 100644
index 000000000..cdfe3d35d
--- /dev/null
+++ b/packages/astro/test/units/config/config-server.test.js
@@ -0,0 +1,71 @@
+import { expect } from 'chai';
+import { fileURLToPath } from 'url';
+import { defaultLogging as logging } from '../../test-utils.js';
+import { openConfig } from '../../../dist/core/config/index.js';
+
+const cwd = fileURLToPath(new URL('../../fixtures/config-host/', import.meta.url));
+
+describe('config.server', () => {
+ function openConfigWithFlags(flags) {
+ return openConfig({
+ cwd: flags.root || cwd,
+ flags,
+ cmd: 'dev',
+ logging
+ });
+ }
+
+ describe('host', () => {
+ it('can be specified via --host flag', async () => {
+ const projectRootURL = new URL('../../fixtures/astro-basic/', import.meta.url);
+ const { astroConfig } = await openConfigWithFlags({
+ root: fileURLToPath(projectRootURL),
+ host: true
+ });
+
+ expect(astroConfig.server.host).to.equal(true);
+ });
+ });
+
+ describe('config', () => {
+ describe('relative path', () => {
+ it('can be passed via relative --config', async () => {
+ const projectRootURL = new URL('../../fixtures/astro-basic/', import.meta.url);
+ const configFileURL = 'my-config.mjs';
+ const { astroConfig } = await openConfigWithFlags({
+ root: fileURLToPath(projectRootURL),
+ config: configFileURL
+ });
+ expect(astroConfig.server.port).to.equal(8080);
+ });
+ });
+
+ describe('relative path with leading ./', () => {
+ it('can be passed via relative --config', async () => {
+ const projectRootURL = new URL('../../fixtures/astro-basic/', import.meta.url);
+ const configFileURL = './my-config.mjs';
+ const { astroConfig } = await openConfigWithFlags({
+ root: fileURLToPath(projectRootURL),
+ config: configFileURL
+ });
+ expect(astroConfig.server.port).to.equal(8080);
+ });
+ });
+
+ describe('incorrect path', () => {
+ it('fails and exits when config does not exist', async () => {
+ const projectRootURL = new URL('../../fixtures/astro-basic/', import.meta.url);
+ const configFileURL = './does-not-exist.mjs';
+ try {
+ await openConfigWithFlags({
+ root: fileURLToPath(projectRootURL),
+ config: configFileURL
+ });
+ expect(false).to.equal(true, 'this should not have resolved');
+ } catch(err) {
+ expect(err.message).to.match(/Unable to resolve/);
+ }
+ });
+ });
+ });
+})
diff --git a/packages/astro/test/config-validate.test.js b/packages/astro/test/units/config/config-validate.test.js
index 6fefed9e4..fa7418c56 100644
--- a/packages/astro/test/config-validate.test.js
+++ b/packages/astro/test/units/config/config-validate.test.js
@@ -1,8 +1,8 @@
import { expect } from 'chai';
import { z } from 'zod';
import stripAnsi from 'strip-ansi';
-import { formatConfigErrorMessage } from '../dist/core/messages.js';
-import { validateConfig } from '../dist/core/config.js';
+import { formatConfigErrorMessage } from '../../../dist/core/messages.js';
+import { validateConfig } from '../../../dist/core/config/index.js';
describe('Config Validation', () => {
it('empty user config is valid', async () => {