summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--packages/astro/src/cli/index.ts5
-rw-r--r--packages/astro/src/core/config/config.ts119
-rw-r--r--packages/astro/src/core/config/index.ts1
-rw-r--r--packages/astro/src/core/config/merge.ts53
-rw-r--r--packages/astro/src/core/config/vite-load.ts61
-rw-r--r--packages/astro/src/integrations/index.ts2
6 files changed, 90 insertions, 151 deletions
diff --git a/packages/astro/src/cli/index.ts b/packages/astro/src/cli/index.ts
index 60a8f3c32..a9399aae5 100644
--- a/packages/astro/src/cli/index.ts
+++ b/packages/astro/src/cli/index.ts
@@ -102,13 +102,10 @@ async function handleConfigError(
error(logging, 'astro', `Unable to load ${path ? colors.bold(path) : 'your Astro config'}\n`);
if (e instanceof ZodError) {
console.error(formatConfigErrorMessage(e) + '\n');
+ telemetry.record(eventConfigError({ cmd, err: e, isFatal: true }));
} else if (e instanceof Error) {
console.error(formatErrorMessage(collectErrorMetadata(e)) + '\n');
}
- const telemetryPromise = telemetry.record(eventConfigError({ cmd, err: e, isFatal: true }));
- await telemetryPromise.catch((err2: Error) =>
- debug('telemetry', `record() error: ${err2.message}`)
- );
}
/**
diff --git a/packages/astro/src/core/config/config.ts b/packages/astro/src/core/config/config.ts
index 4395dceae..dc7de2bc7 100644
--- a/packages/astro/src/core/config/config.ts
+++ b/packages/astro/src/core/config/config.ts
@@ -5,9 +5,7 @@ import fs from 'fs';
import * as colors from 'kleur/colors';
import path from 'path';
import { fileURLToPath, pathToFileURL } from 'url';
-import { mergeConfig as mergeViteConfig } from 'vite';
import { AstroError, AstroErrorData } from '../errors/index.js';
-import { arraify, isObject, isURL } from '../util.js';
import { createRelativeSchema } from './schema.js';
import { loadConfigWithVite } from './vite-load.js';
@@ -210,12 +208,8 @@ interface OpenConfigResult {
export async function openConfig(configOptions: LoadConfigOptions): Promise<OpenConfigResult> {
const root = resolveRoot(configOptions.cwd);
const flags = resolveFlags(configOptions.flags || {});
- let userConfig: AstroUserConfig = {};
- const config = await tryLoadConfig(configOptions, root);
- if (config) {
- userConfig = config.value;
- }
+ const userConfig = await loadConfig(configOptions, root);
const astroConfig = await resolveConfig(userConfig, root, flags, configOptions.cmd);
return {
@@ -226,54 +220,24 @@ export async function openConfig(configOptions: LoadConfigOptions): Promise<Open
};
}
-interface TryLoadConfigResult {
- value: Record<string, any>;
- filePath?: string;
-}
-
-async function tryLoadConfig(
+async function loadConfig(
configOptions: LoadConfigOptions,
root: string
-): Promise<TryLoadConfigResult | undefined> {
+): Promise<Record<string, any>> {
const fsMod = configOptions.fsMod ?? fs;
- let finallyCleanup = async () => {};
- try {
- let configPath = await resolveConfigPath({
- cwd: configOptions.cwd,
- flags: configOptions.flags,
- fs: fsMod,
- });
- if (!configPath) return undefined;
- if (configOptions.isRestart) {
- // Hack: Write config to temporary file at project root
- // This invalidates and reloads file contents when using ESM imports or "resolve"
- const tempConfigPath = path.join(
- root,
- `.temp.${Date.now()}.config${path.extname(configPath)}`
- );
-
- const currentConfigContent = await fsMod.promises.readFile(configPath, 'utf-8');
- await fs.promises.writeFile(tempConfigPath, currentConfigContent);
- finallyCleanup = async () => {
- try {
- await fs.promises.unlink(tempConfigPath);
- } catch {
- /** file already removed */
- }
- };
- configPath = tempConfigPath;
- }
-
- // Create a vite server to load the config
- const config = await loadConfigWithVite({
- configPath,
- fs: fsMod,
- root,
- });
- return config as TryLoadConfigResult;
- } finally {
- await finallyCleanup();
- }
+ const configPath = await resolveConfigPath({
+ cwd: configOptions.cwd,
+ flags: configOptions.flags,
+ fs: fsMod,
+ });
+ if (!configPath) return {};
+
+ // Create a vite server to load the config
+ return await loadConfigWithVite({
+ configPath,
+ fs: fsMod,
+ root,
+ });
}
/** Attempt to resolve an Astro configuration object. Normalize, validate, and return. */
@@ -295,54 +259,3 @@ export function createDefaultDevConfig(
) {
return resolveConfig(userConfig, root, undefined, 'dev');
}
-
-function mergeConfigRecursively(
- defaults: Record<string, any>,
- overrides: Record<string, any>,
- rootPath: string
-) {
- const merged: Record<string, any> = { ...defaults };
- for (const key in overrides) {
- const value = overrides[key];
- if (value == null) {
- continue;
- }
-
- const existing = merged[key];
-
- if (existing == null) {
- merged[key] = value;
- continue;
- }
-
- // fields that require special handling:
- if (key === 'vite' && rootPath === '') {
- merged[key] = mergeViteConfig(existing, value);
- continue;
- }
-
- if (Array.isArray(existing) || Array.isArray(value)) {
- merged[key] = [...arraify(existing ?? []), ...arraify(value ?? [])];
- continue;
- }
- if (isURL(existing) && isURL(value)) {
- merged[key] = value;
- continue;
- }
- if (isObject(existing) && isObject(value)) {
- merged[key] = mergeConfigRecursively(existing, value, rootPath ? `${rootPath}.${key}` : key);
- continue;
- }
-
- merged[key] = value;
- }
- return merged;
-}
-
-export function mergeConfig(
- defaults: Record<string, any>,
- overrides: Record<string, any>,
- isRoot = true
-): Record<string, any> {
- return mergeConfigRecursively(defaults, overrides, isRoot ? '' : '.');
-}
diff --git a/packages/astro/src/core/config/index.ts b/packages/astro/src/core/config/index.ts
index bbc64f512..b7b616951 100644
--- a/packages/astro/src/core/config/index.ts
+++ b/packages/astro/src/core/config/index.ts
@@ -6,6 +6,7 @@ export {
resolveRoot,
validateConfig,
} from './config.js';
+export { mergeConfig } from './merge.js';
export type { AstroConfigSchema } from './schema';
export { createDefaultDevSettings, createSettings } from './settings.js';
export { loadTSConfig, updateTSConfigForFramework } from './tsconfig.js';
diff --git a/packages/astro/src/core/config/merge.ts b/packages/astro/src/core/config/merge.ts
new file mode 100644
index 000000000..3a498332b
--- /dev/null
+++ b/packages/astro/src/core/config/merge.ts
@@ -0,0 +1,53 @@
+import { mergeConfig as mergeViteConfig } from 'vite';
+import { arraify, isObject, isURL } from '../util.js';
+
+function mergeConfigRecursively(
+ defaults: Record<string, any>,
+ overrides: Record<string, any>,
+ rootPath: string
+) {
+ const merged: Record<string, any> = { ...defaults };
+ for (const key in overrides) {
+ const value = overrides[key];
+ if (value == null) {
+ continue;
+ }
+
+ const existing = merged[key];
+
+ if (existing == null) {
+ merged[key] = value;
+ continue;
+ }
+
+ // fields that require special handling:
+ if (key === 'vite' && rootPath === '') {
+ merged[key] = mergeViteConfig(existing, value);
+ continue;
+ }
+
+ if (Array.isArray(existing) || Array.isArray(value)) {
+ merged[key] = [...arraify(existing ?? []), ...arraify(value ?? [])];
+ continue;
+ }
+ if (isURL(existing) && isURL(value)) {
+ merged[key] = value;
+ continue;
+ }
+ if (isObject(existing) && isObject(value)) {
+ merged[key] = mergeConfigRecursively(existing, value, rootPath ? `${rootPath}.${key}` : key);
+ continue;
+ }
+
+ merged[key] = value;
+ }
+ return merged;
+}
+
+export function mergeConfig(
+ defaults: Record<string, any>,
+ overrides: Record<string, any>,
+ isRoot = true
+): Record<string, any> {
+ return mergeConfigRecursively(defaults, overrides, isRoot ? '' : '.');
+}
diff --git a/packages/astro/src/core/config/vite-load.ts b/packages/astro/src/core/config/vite-load.ts
index a4fc5e9a6..86e3cf80e 100644
--- a/packages/astro/src/core/config/vite-load.ts
+++ b/packages/astro/src/core/config/vite-load.ts
@@ -1,15 +1,11 @@
import type fsType from 'fs';
import { pathToFileURL } from 'url';
-import * as vite from 'vite';
+import { createServer, type ViteDevServer } from 'vite';
import loadFallbackPlugin from '../../vite-plugin-load-fallback/index.js';
+import { debug } from '../logger/core.js';
-export interface ViteLoader {
- root: string;
- viteServer: vite.ViteDevServer;
-}
-
-async function createViteLoader(root: string, fs: typeof fsType): Promise<ViteLoader> {
- const viteServer = await vite.createServer({
+async function createViteServer(root: string, fs: typeof fsType): Promise<ViteDevServer> {
+ const viteServer = await createServer({
server: { middlewareMode: true, hmr: false, watch: { ignored: ['**'] } },
optimizeDeps: { disabled: true },
clearScreen: false,
@@ -30,15 +26,12 @@ async function createViteLoader(root: string, fs: typeof fsType): Promise<ViteLo
plugins: [loadFallbackPlugin({ fs, root: pathToFileURL(root) })],
});
- return {
- root,
- viteServer,
- };
+ return viteServer;
}
interface LoadConfigWithViteOptions {
root: string;
- configPath: string | undefined;
+ configPath: string;
fs: typeof fsType;
}
@@ -46,44 +39,26 @@ export async function loadConfigWithVite({
configPath,
fs,
root,
-}: LoadConfigWithViteOptions): Promise<{
- value: Record<string, any>;
- filePath?: string;
-}> {
- // No config file found, return an empty config that will be populated with defaults
- if (!configPath) {
- return {
- value: {},
- filePath: undefined,
- };
- }
-
- // Try loading with Node import()
+}: LoadConfigWithViteOptions): Promise<Record<string, any>> {
if (/\.[cm]?js$/.test(configPath)) {
try {
- const config = await import(pathToFileURL(configPath).toString());
- return {
- value: config.default ?? {},
- filePath: configPath,
- };
- } catch {
- // We do not need to keep the error here because with fallback the error will be rethrown
- // when/if it fails in Vite.
+ const config = await import(pathToFileURL(configPath).toString() + '?t=' + Date.now());
+ return config.default ?? {};
+ } catch (e) {
+ // We do not need to throw the error here as we have a Vite fallback below
+ debug('Failed to load config with Node', e);
}
}
// Try Loading with Vite
- let loader: ViteLoader | undefined;
+ let server: ViteDevServer | undefined;
try {
- loader = await createViteLoader(root, fs);
- const mod = await loader.viteServer.ssrLoadModule(configPath);
- return {
- value: mod.default ?? {},
- filePath: configPath,
- };
+ server = await createViteServer(root, fs);
+ const mod = await server.ssrLoadModule(configPath, { fixStacktrace: true });
+ return mod.default ?? {};
} finally {
- if (loader) {
- await loader.viteServer.close();
+ if (server) {
+ await server.close();
}
}
}
diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts
index b243ba979..ba8bcc1ef 100644
--- a/packages/astro/src/integrations/index.ts
+++ b/packages/astro/src/integrations/index.ts
@@ -15,7 +15,7 @@ import type {
import type { SerializedSSRManifest } from '../core/app/types';
import type { PageBuildData } from '../core/build/types';
import { buildClientDirectiveEntrypoint } from '../core/client-directive/index.js';
-import { mergeConfig } from '../core/config/config.js';
+import { mergeConfig } from '../core/config/index.js';
import { info, type LogOptions } from '../core/logger/core.js';
import { isServerLikeOutput } from '../prerender/utils.js';