full site update

This commit is contained in:
2025-07-24 18:46:24 +02:00
parent bfe2b90d8d
commit 37a6e0ab31
6912 changed files with 540482 additions and 361712 deletions

View File

@@ -0,0 +1,5 @@
import type { AstroSettings } from '../../types/astro.js';
import type { AstroAdapter } from '../../types/public/integrations.js';
import type { Logger } from '../logger/core.js';
export declare function warnMissingAdapter(logger: Logger, settings: AstroSettings): void;
export declare function validateSetAdapter(logger: Logger, settings: AstroSettings, adapter: AstroAdapter, maybeConflictingIntegration: string, command?: 'dev' | 'build' | string): void;

39
node_modules/astro/dist/core/dev/adapter-validation.js generated vendored Normal file
View File

@@ -0,0 +1,39 @@
import { getAdapterStaticRecommendation } from "../../integrations/features-validation.js";
import { AstroError, AstroErrorData } from "../errors/index.js";
let hasWarnedMissingAdapter = false;
function warnMissingAdapter(logger, settings) {
if (hasWarnedMissingAdapter) return;
if (settings.buildOutput === "server" && !settings.config.adapter) {
logger.warn(
"config",
"This project contains server-rendered routes, but no adapter is installed. This is fine for development, but an adapter will be required to build your site for production."
);
hasWarnedMissingAdapter = true;
}
}
function validateSetAdapter(logger, settings, adapter, maybeConflictingIntegration, command) {
if (settings.adapter && settings.adapter.name !== adapter.name) {
throw new Error(
`Integration "${maybeConflictingIntegration}" conflicts with "${settings.adapter.name}". You can only configure one deployment integration.`
);
}
if (settings.buildOutput === "server" && adapter.adapterFeatures?.buildOutput === "static") {
if (command === "build") {
const adapterRecommendation = getAdapterStaticRecommendation(adapter.name);
throw new AstroError({
...AstroErrorData.AdapterSupportOutputMismatch,
message: AstroErrorData.AdapterSupportOutputMismatch.message(adapter.name),
hint: adapterRecommendation ? adapterRecommendation : void 0
});
} else if (command === "dev") {
logger.warn(
null,
`The adapter ${adapter.name} does not support emitting a server output, but the project contain server-rendered pages. Your project will not build correctly.`
);
}
}
}
export {
validateSetAdapter,
warnMissingAdapter
};

View File

@@ -1,8 +1,9 @@
import nodeFs from 'node:fs';
import type * as http from 'node:http';
import type { AddressInfo } from 'node:net';
import type { AstroInlineConfig, AstroSettings } from '../../@types/astro.js';
import nodeFs from 'node:fs';
import * as vite from 'vite';
import type { AstroSettings } from '../../types/astro.js';
import type { AstroInlineConfig } from '../../types/public/config.js';
import type { Logger } from '../logger/core.js';
export interface Container {
fs: typeof nodeFs;
@@ -14,7 +15,7 @@ export interface Container {
handle: (req: http.IncomingMessage, res: http.ServerResponse) => void;
close: () => Promise<void>;
}
export interface CreateContainerParams {
interface CreateContainerParams {
logger: Logger;
settings: AstroSettings;
inlineConfig?: AstroInlineConfig;
@@ -23,3 +24,4 @@ export interface CreateContainerParams {
}
export declare function createContainer({ isRestart, logger, inlineConfig, settings, fs, }: CreateContainerParams): Promise<Container>;
export declare function startContainer({ settings, viteServer, logger, }: Container): Promise<AddressInfo>;
export {};

View File

@@ -1,15 +1,17 @@
import nodeFs from "node:fs";
import * as vite from "vite";
import { injectImageEndpoint } from "../../assets/endpoint/config.js";
import {
runHookConfigDone,
runHookConfigSetup,
runHookServerDone,
runHookServerStart
} from "../../integrations/hooks.js";
import { createDevelopmentManifest } from "../../vite-plugin-astro-server/plugin.js";
import { createVite } from "../create-vite.js";
import { apply as applyPolyfill } from "../polyfill.js";
import { createRoutesList } from "../routing/index.js";
import { syncInternal } from "../sync/index.js";
import { warnMissingAdapter } from "./adapter-validation.js";
async function createContainer({
isRestart = false,
logger,
@@ -24,35 +26,52 @@ async function createContainer({
logger,
isRestart
});
settings = injectImageEndpoint(settings, "dev");
const {
base,
server: { host, headers, open: serverOpen }
server: { host, headers, open: serverOpen, allowedHosts }
} = settings.config;
const isServerOpenURL = typeof serverOpen == "string" && !isRestart;
const isServerOpenBoolean = serverOpen && !isRestart;
const open = isServerOpenURL ? serverOpen : isServerOpenBoolean ? base : false;
const rendererClientEntries = settings.renderers.map((r) => r.clientEntrypoint).filter(Boolean);
const routesList = await createRoutesList({ settings, fsMod: fs }, logger, { dev: true });
const manifest = createDevelopmentManifest(settings);
await runHookConfigDone({ settings, logger, command: "dev" });
warnMissingAdapter(logger, settings);
const mode = inlineConfig?.mode ?? "development";
const viteConfig = await createVite(
{
mode: "development",
server: { host, headers, open },
server: { host, headers, open, allowedHosts },
optimizeDeps: {
include: rendererClientEntries
}
},
{ settings, logger, mode: "dev", command: "dev", fs, sync: false }
{
settings,
logger,
mode,
command: "dev",
fs,
sync: false,
routesList,
manifest
}
);
await runHookConfigDone({ settings, logger });
const viteServer = await vite.createServer(viteConfig);
await syncInternal({
settings,
mode,
logger,
skip: {
content: true
content: !isRestart,
cleanup: true
},
force: inlineConfig?.force
force: inlineConfig?.force,
routesList,
manifest,
command: "dev",
watcher: viteServer.watcher
});
const viteServer = await vite.createServer(viteConfig);
const container = {
inlineConfig: inlineConfig ?? {},
fs,

View File

@@ -1,7 +1,7 @@
import type http from 'node:http';
import type { AddressInfo } from 'node:net';
import type * as vite from 'vite';
import type { AstroInlineConfig } from '../../@types/astro.js';
import type { AstroInlineConfig } from '../../types/public/config.js';
export interface DevServer {
address: AddressInfo;
handle: (req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>) => void;

View File

@@ -1,4 +1,4 @@
import fs, { existsSync } from "node:fs";
import fs from "node:fs";
import { performance } from "node:perf_hooks";
import { green } from "kleur/colors";
import { gt, major, minor, patch } from "semver";
@@ -12,8 +12,8 @@ import { ensureProcessNodeEnv } from "../util.js";
import { startContainer } from "./container.js";
import { createContainerWithAutomaticRestart } from "./restart.js";
import {
MAX_PATCH_DISTANCE,
fetchLatestAstroVersion,
MAX_PATCH_DISTANCE,
shouldCheckForUpdates
} from "./update-check.js";
async function dev(inlineConfig) {
@@ -22,7 +22,7 @@ async function dev(inlineConfig) {
await telemetry.record([]);
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
const logger = restart.container.logger;
const currentVersion = "4.16.18";
const currentVersion = "5.12.3";
const isPrerelease = currentVersion.includes("-");
if (!isPrerelease) {
try {
@@ -50,6 +50,33 @@ async function dev(inlineConfig) {
} catch {
}
}
let store;
try {
const dataStoreFile = getDataStoreFile(restart.container.settings, true);
store = await MutableDataStore.fromFile(dataStoreFile);
} catch (err) {
logger.error("content", err.message);
}
if (!store) {
logger.error("content", "Failed to create data store");
}
await attachContentServerListeners(restart.container);
const config = globalContentConfigObserver.get();
if (config.status === "error") {
logger.error("content", config.error.message);
}
if (config.status === "loaded" && store) {
const contentLayer = globalContentLayer.init({
settings: restart.container.settings,
logger,
watcher: restart.container.viteServer.watcher,
store
});
contentLayer.watchContentConfig();
await contentLayer.sync();
} else {
logger.warn("content", "Content config not loaded");
}
const devServerAddressInfo = await startContainer(restart.container);
logger.info(
"SKIP_FORMAT",
@@ -66,33 +93,6 @@ async function dev(inlineConfig) {
if (restart.container.viteServer.config.server?.fs?.strict === false) {
logger.warn("SKIP_FORMAT", msg.fsStrictWarning());
}
await attachContentServerListeners(restart.container);
let store;
try {
const dataStoreFile = getDataStoreFile(restart.container.settings);
if (existsSync(dataStoreFile)) {
store = await MutableDataStore.fromFile(dataStoreFile);
}
} catch (err) {
logger.error("content", err.message);
}
if (!store) {
store = new MutableDataStore();
}
const config = globalContentConfigObserver.get();
if (config.status === "error") {
logger.error("content", config.error.message);
}
if (config.status === "loaded") {
const contentLayer = globalContentLayer.init({
settings: restart.container.settings,
logger,
watcher: restart.container.viteServer.watcher,
store
});
contentLayer.watchContentConfig();
await contentLayer.sync();
}
logger.info(null, green("watching for file changes..."));
return {
address: devServerAddressInfo,

View File

@@ -1,3 +1,3 @@
export { createContainer, startContainer } from './container.js';
export { startContainer } from './container.js';
export { default } from './dev.js';
export { createContainerWithAutomaticRestart } from './restart.js';

View File

@@ -1,8 +1,7 @@
import { createContainer, startContainer } from "./container.js";
import { startContainer } from "./container.js";
import { default as default2 } from "./dev.js";
import { createContainerWithAutomaticRestart } from "./restart.js";
export {
createContainer,
createContainerWithAutomaticRestart,
default2 as default,
startContainer

View File

@@ -1,7 +1,7 @@
import type nodeFs from 'node:fs';
import type { AstroInlineConfig } from '../../@types/astro.js';
import type { AstroInlineConfig } from '../../types/public/config.js';
import type { Container } from './container.js';
export interface CreateContainerWithAutomaticRestart {
interface CreateContainerWithAutomaticRestart {
inlineConfig?: AstroInlineConfig;
fs: typeof nodeFs;
}

View File

@@ -1,7 +1,9 @@
import { fileURLToPath } from "node:url";
import * as vite from "vite";
import { globalContentLayer } from "../../content/content-layer.js";
import { attachContentServerListeners } from "../../content/server-listeners.js";
import { eventCliSession, telemetry } from "../../events/index.js";
import { SETTINGS_FILE } from "../../preferences/constants.js";
import { createNodeLogger, createSettings, resolveConfig } from "../config/index.js";
import { collectErrorMetadata } from "../errors/dev/utils.js";
import { isAstroConfigZodError } from "../errors/errors.js";
@@ -30,7 +32,7 @@ function shouldRestartContainer({ settings, inlineConfig, restartInFlight }, cha
} else {
shouldRestart = configRE.test(normalizedChangedFile);
const settingsPath = vite.normalizePath(
fileURLToPath(new URL("settings.json", settings.dotAstroDir))
fileURLToPath(new URL(SETTINGS_FILE, settings.dotAstroDir))
);
if (settingsPath.endsWith(normalizedChangedFile)) {
shouldRestart = settings.preferences.ignoreNextPreferenceReload ? false : true;
@@ -49,6 +51,12 @@ async function restartContainer(container) {
container.restartInFlight = true;
try {
const { astroConfig } = await resolveConfig(container.inlineConfig, "dev", container.fs);
if (astroConfig.experimental.csp) {
logger.warn(
"config",
"Astro's Content Security Policy (CSP) does not work in development mode. To verify your CSP implementation, build the project and run the preview server."
);
}
const settings = await createSettings(astroConfig, fileURLToPath(existingSettings.config.root));
await close();
return await createRestartedContainer(container, settings);
@@ -78,9 +86,20 @@ async function createContainerWithAutomaticRestart({
}) {
const logger = createNodeLogger(inlineConfig ?? {});
const { userConfig, astroConfig } = await resolveConfig(inlineConfig ?? {}, "dev", fs);
if (astroConfig.experimental.csp) {
logger.warn(
"config",
"Astro's Content Security Policy (CSP) does not work in development mode. To verify your CSP implementation, build the project and run the preview server."
);
}
telemetry.record(eventCliSession("dev", userConfig));
const settings = await createSettings(astroConfig, fileURLToPath(astroConfig.root));
const initialContainer = await createContainer({ settings, logger, inlineConfig, fs });
const initialContainer = await createContainer({
settings,
logger,
inlineConfig,
fs
});
let resolveRestart;
let restartComplete = new Promise((resolve) => {
resolveRestart = resolve;
@@ -91,7 +110,7 @@ async function createContainerWithAutomaticRestart({
return restartComplete;
}
};
async function handleServerRestart(logMsg = "") {
async function handleServerRestart(logMsg = "", server) {
logger.info(null, (logMsg + " Restarting...").trim());
const container = restart.container;
const result = await restartContainer(container);
@@ -100,6 +119,10 @@ async function createContainerWithAutomaticRestart({
} else {
restart.container = result;
setupContainer();
await attachContentServerListeners(restart.container);
if (server) {
server.resolvedUrls = result.viteServer.resolvedUrls;
}
resolveRestart(null);
}
restartComplete = new Promise((resolve) => {
@@ -119,7 +142,9 @@ async function createContainerWithAutomaticRestart({
watcher.on("unlink", handleChangeRestart("Configuration file removed."));
watcher.on("add", handleChangeRestart("Configuration file added."));
restart.container.viteServer.restart = async () => {
if (!restart.container.restartInFlight) await handleServerRestart();
if (!restart.container.restartInFlight) {
await handleServerRestart("", restart.container.viteServer);
}
};
const customShortcuts = [
// Disable default Vite shortcuts that don't work well with Astro
@@ -127,15 +152,13 @@ async function createContainerWithAutomaticRestart({
{ key: "u", description: "" },
{ key: "c", description: "" }
];
if (restart.container.settings.config.experimental.contentLayer) {
customShortcuts.push({
key: "s",
description: "sync content layer",
action: () => {
globalContentLayer.get()?.sync();
}
});
}
customShortcuts.push({
key: "s",
description: "sync content layer",
action: () => {
globalContentLayer.get()?.sync();
}
});
restart.container.viteServer.bindCLIShortcuts({
customShortcuts
});