fix(assets): Fix endpoint not being injected when an integration would enable experimental.assets
(#7829)
This commit is contained in:
parent
05ee09f9c2
commit
b063a2d8ae
12 changed files with 48 additions and 24 deletions
5
.changeset/neat-balloons-doubt.md
Normal file
5
.changeset/neat-balloons-doubt.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix `astro:assets` endpoint not working in dev and SSR if `experimental.assets` was enabled by an integration (such as Starlight)
|
|
@ -1,7 +1,18 @@
|
||||||
|
import type { AstroSettings } from '../@types/astro.js';
|
||||||
import { AstroError, AstroErrorData } from '../core/errors/index.js';
|
import { AstroError, AstroErrorData } from '../core/errors/index.js';
|
||||||
import { isLocalService, type ImageService } from './services/service.js';
|
import { isLocalService, type ImageService } from './services/service.js';
|
||||||
import type { GetImageResult, ImageMetadata, ImageTransform } from './types.js';
|
import type { GetImageResult, ImageMetadata, ImageTransform } from './types.js';
|
||||||
|
|
||||||
|
export function injectImageEndpoint(settings: AstroSettings) {
|
||||||
|
settings.injectedRoutes.push({
|
||||||
|
pattern: '/_image',
|
||||||
|
entryPoint: 'astro/assets/image-endpoint',
|
||||||
|
prerender: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
export function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata {
|
export function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata {
|
||||||
return typeof src === 'object';
|
return typeof src === 'object';
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,9 @@ export async function loadSettings({ cmd, flags, logging }: LoadSettingsOptions)
|
||||||
return {} as any;
|
return {} as any;
|
||||||
});
|
});
|
||||||
|
|
||||||
const mode = cmd === 'build' ? 'build' : 'dev';
|
|
||||||
if (!initialAstroConfig) return;
|
if (!initialAstroConfig) return;
|
||||||
telemetry.record(event.eventCliSession(cmd, initialUserConfig, flags));
|
telemetry.record(event.eventCliSession(cmd, initialUserConfig, flags));
|
||||||
return createSettings(initialAstroConfig, mode, root);
|
return createSettings(initialAstroConfig, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleConfigError(
|
export async function handleConfigError(
|
||||||
|
|
|
@ -35,7 +35,7 @@ export function getViteConfig(inlineConfig: UserConfig) {
|
||||||
level: 'info',
|
level: 'info',
|
||||||
};
|
};
|
||||||
const { astroConfig: config } = await openConfig({ cmd });
|
const { astroConfig: config } = await openConfig({ cmd });
|
||||||
const settings = createSettings(config, cmd, inlineConfig.root);
|
const settings = createSettings(config, inlineConfig.root);
|
||||||
await runHookConfigSetup({ settings, command: cmd, logging });
|
await runHookConfigSetup({ settings, command: cmd, logging });
|
||||||
const viteConfig = await createVite(
|
const viteConfig = await createVite(
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,12 +4,14 @@ import { performance } from 'node:perf_hooks';
|
||||||
import type * as vite from 'vite';
|
import type * as vite from 'vite';
|
||||||
import type yargs from 'yargs-parser';
|
import type yargs from 'yargs-parser';
|
||||||
import type { AstroConfig, AstroSettings, ManifestData, RuntimeMode } from '../../@types/astro';
|
import type { AstroConfig, AstroSettings, ManifestData, RuntimeMode } from '../../@types/astro';
|
||||||
|
import { injectImageEndpoint } from '../../assets/internal.js';
|
||||||
import {
|
import {
|
||||||
runHookBuildDone,
|
runHookBuildDone,
|
||||||
runHookBuildStart,
|
runHookBuildStart,
|
||||||
runHookConfigDone,
|
runHookConfigDone,
|
||||||
runHookConfigSetup,
|
runHookConfigSetup,
|
||||||
} from '../../integrations/index.js';
|
} from '../../integrations/index.js';
|
||||||
|
import { isServerLikeOutput } from '../../prerender/utils.js';
|
||||||
import { createVite } from '../create-vite.js';
|
import { createVite } from '../create-vite.js';
|
||||||
import { debug, info, levels, timerMessage, warn, type LogOptions } from '../logger/core.js';
|
import { debug, info, levels, timerMessage, warn, type LogOptions } from '../logger/core.js';
|
||||||
import { printHelp } from '../messages.js';
|
import { printHelp } from '../messages.js';
|
||||||
|
@ -89,6 +91,13 @@ class AstroBuilder {
|
||||||
command: 'build',
|
command: 'build',
|
||||||
logging,
|
logging,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// HACK: Since we only inject the endpoint if `experimental.assets` is on and it's possible for an integration to
|
||||||
|
// add that flag, we need to only check and inject the endpoint after running the config setup hook.
|
||||||
|
if (this.settings.config.experimental.assets && isServerLikeOutput(this.settings.config)) {
|
||||||
|
this.settings = injectImageEndpoint(this.settings);
|
||||||
|
}
|
||||||
|
|
||||||
this.manifest = createRouteManifest({ settings: this.settings }, this.logging);
|
this.manifest = createRouteManifest({ settings: this.settings }, this.logging);
|
||||||
|
|
||||||
const viteConfig = await createVite(
|
const viteConfig = await createVite(
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
||||||
import type { AstroConfig, AstroSettings, AstroUserConfig } from '../../@types/astro';
|
import type { AstroConfig, AstroSettings, AstroUserConfig } from '../../@types/astro';
|
||||||
import { getContentPaths } from '../../content/index.js';
|
import { getContentPaths } from '../../content/index.js';
|
||||||
import jsxRenderer from '../../jsx/renderer.js';
|
import jsxRenderer from '../../jsx/renderer.js';
|
||||||
import { isServerLikeOutput } from '../../prerender/utils.js';
|
|
||||||
import { markdownContentEntryType } from '../../vite-plugin-markdown/content-entry-type.js';
|
import { markdownContentEntryType } from '../../vite-plugin-markdown/content-entry-type.js';
|
||||||
import { getDefaultClientDirectives } from '../client-directive/index.js';
|
import { getDefaultClientDirectives } from '../client-directive/index.js';
|
||||||
import { AstroError, AstroErrorData } from '../errors/index.js';
|
import { AstroError, AstroErrorData } from '../errors/index.js';
|
||||||
|
@ -14,7 +13,7 @@ import { createDefaultDevConfig } from './config.js';
|
||||||
import { AstroTimer } from './timer.js';
|
import { AstroTimer } from './timer.js';
|
||||||
import { loadTSConfig } from './tsconfig.js';
|
import { loadTSConfig } from './tsconfig.js';
|
||||||
|
|
||||||
export function createBaseSettings(config: AstroConfig, mode: 'build' | 'dev'): AstroSettings {
|
export function createBaseSettings(config: AstroConfig): AstroSettings {
|
||||||
const { contentDir } = getContentPaths(config);
|
const { contentDir } = getContentPaths(config);
|
||||||
return {
|
return {
|
||||||
config,
|
config,
|
||||||
|
@ -22,10 +21,7 @@ export function createBaseSettings(config: AstroConfig, mode: 'build' | 'dev'):
|
||||||
tsConfigPath: undefined,
|
tsConfigPath: undefined,
|
||||||
|
|
||||||
adapter: undefined,
|
adapter: undefined,
|
||||||
injectedRoutes:
|
injectedRoutes: [],
|
||||||
config.experimental.assets && (isServerLikeOutput(config) || mode === 'dev')
|
|
||||||
? [{ pattern: '/_image', entryPoint: 'astro/assets/image-endpoint', prerender: false }]
|
|
||||||
: [],
|
|
||||||
pageExtensions: ['.astro', '.html', ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS],
|
pageExtensions: ['.astro', '.html', ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS],
|
||||||
contentEntryTypes: [markdownContentEntryType],
|
contentEntryTypes: [markdownContentEntryType],
|
||||||
dataEntryTypes: [
|
dataEntryTypes: [
|
||||||
|
@ -108,13 +104,9 @@ export function createBaseSettings(config: AstroConfig, mode: 'build' | 'dev'):
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createSettings(
|
export function createSettings(config: AstroConfig, cwd?: string): AstroSettings {
|
||||||
config: AstroConfig,
|
|
||||||
mode: 'build' | 'dev',
|
|
||||||
cwd?: string
|
|
||||||
): AstroSettings {
|
|
||||||
const tsconfig = loadTSConfig(cwd);
|
const tsconfig = loadTSConfig(cwd);
|
||||||
const settings = createBaseSettings(config, mode);
|
const settings = createBaseSettings(config);
|
||||||
|
|
||||||
const watchFiles = tsconfig?.exists ? [tsconfig.path, ...tsconfig.extendedPaths] : [];
|
const watchFiles = tsconfig?.exists ? [tsconfig.path, ...tsconfig.extendedPaths] : [];
|
||||||
|
|
||||||
|
@ -136,5 +128,5 @@ export async function createDefaultDevSettings(
|
||||||
root = fileURLToPath(root);
|
root = fileURLToPath(root);
|
||||||
}
|
}
|
||||||
const config = await createDefaultDevConfig(userConfig, root);
|
const config = await createDefaultDevConfig(userConfig, root);
|
||||||
return createBaseSettings(config, 'dev');
|
return createBaseSettings(config);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import type { AstroSettings, AstroUserConfig } from '../../@types/astro';
|
||||||
|
|
||||||
import nodeFs from 'node:fs';
|
import nodeFs from 'node:fs';
|
||||||
import * as vite from 'vite';
|
import * as vite from 'vite';
|
||||||
|
import { injectImageEndpoint } from '../../assets/internal.js';
|
||||||
import {
|
import {
|
||||||
runHookConfigDone,
|
runHookConfigDone,
|
||||||
runHookConfigSetup,
|
runHookConfigSetup,
|
||||||
|
@ -64,6 +65,13 @@ export async function createContainer(params: CreateContainerParams = {}): Promi
|
||||||
logging,
|
logging,
|
||||||
isRestart,
|
isRestart,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// HACK: Since we only inject the endpoint if `experimental.assets` is on and it's possible for an integration to
|
||||||
|
// add that flag, we need to only check and inject the endpoint after running the config setup hook.
|
||||||
|
if (settings.config.experimental.assets) {
|
||||||
|
settings = injectImageEndpoint(settings);
|
||||||
|
}
|
||||||
|
|
||||||
const { host, headers, open } = settings.config.server;
|
const { host, headers, open } = settings.config.server;
|
||||||
|
|
||||||
// The client entrypoint for renderers. Since these are imported dynamically
|
// The client entrypoint for renderers. Since these are imported dynamically
|
||||||
|
|
|
@ -92,7 +92,7 @@ export async function restartContainer({
|
||||||
});
|
});
|
||||||
info(logging, 'astro', logMsg + '\n');
|
info(logging, 'astro', logMsg + '\n');
|
||||||
let astroConfig = newConfig.astroConfig;
|
let astroConfig = newConfig.astroConfig;
|
||||||
const settings = createSettings(astroConfig, 'dev', resolvedRoot);
|
const settings = createSettings(astroConfig, resolvedRoot);
|
||||||
await close();
|
await close();
|
||||||
return {
|
return {
|
||||||
container: await createRestartedContainer(container, settings, needsStart),
|
container: await createRestartedContainer(container, settings, needsStart),
|
||||||
|
|
|
@ -138,8 +138,8 @@ export async function loadFixture(inlineConfig) {
|
||||||
* the `AstroSettings`. This function helps to create a fresh settings object that is used by the
|
* the `AstroSettings`. This function helps to create a fresh settings object that is used by the
|
||||||
* command functions below to prevent tests from polluting each other.
|
* command functions below to prevent tests from polluting each other.
|
||||||
*/
|
*/
|
||||||
const getSettings = async (mode) => {
|
const getSettings = async () => {
|
||||||
let settings = createSettings(config, mode, fileURLToPath(cwd));
|
let settings = createSettings(config, fileURLToPath(cwd));
|
||||||
if (config.integrations.find((integration) => integration.name === '@astrojs/mdx')) {
|
if (config.integrations.find((integration) => integration.name === '@astrojs/mdx')) {
|
||||||
// Enable default JSX integration. It needs to come first, so unshift rather than push!
|
// Enable default JSX integration. It needs to come first, so unshift rather than push!
|
||||||
const { default: jsxRenderer } = await import('astro/jsx/renderer.js');
|
const { default: jsxRenderer } = await import('astro/jsx/renderer.js');
|
||||||
|
|
|
@ -27,7 +27,7 @@ describe('Astro config formats', () => {
|
||||||
logging: defaultLogging,
|
logging: defaultLogging,
|
||||||
fsMod: fs,
|
fsMod: fs,
|
||||||
});
|
});
|
||||||
const settings = createSettings(astroConfig, 'dev');
|
const settings = createSettings(astroConfig);
|
||||||
|
|
||||||
await runInContainer({ fs, root, settings }, () => {
|
await runInContainer({ fs, root, settings }, () => {
|
||||||
expect(true).to.equal(
|
expect(true).to.equal(
|
||||||
|
|
|
@ -10,7 +10,7 @@ const logging = defaultLogging;
|
||||||
|
|
||||||
async function sync({ fs, config = {} }) {
|
async function sync({ fs, config = {} }) {
|
||||||
const astroConfig = await validateConfig(config, fileURLToPath(root), 'prod');
|
const astroConfig = await validateConfig(config, fileURLToPath(root), 'prod');
|
||||||
const settings = createSettings(astroConfig, 'build', fileURLToPath(root));
|
const settings = createSettings(astroConfig, fileURLToPath(root));
|
||||||
|
|
||||||
return _sync(settings, { logging, fs });
|
return _sync(settings, { logging, fs });
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ describe('dev container restarts', () => {
|
||||||
cmd: 'dev',
|
cmd: 'dev',
|
||||||
logging: defaultLogging,
|
logging: defaultLogging,
|
||||||
});
|
});
|
||||||
const settings = createSettings(astroConfig, 'dev');
|
const settings = createSettings(astroConfig);
|
||||||
|
|
||||||
let restart = await createContainerWithAutomaticRestart({
|
let restart = await createContainerWithAutomaticRestart({
|
||||||
params: { fs, root, settings },
|
params: { fs, root, settings },
|
||||||
|
@ -167,7 +167,7 @@ describe('dev container restarts', () => {
|
||||||
cmd: 'dev',
|
cmd: 'dev',
|
||||||
logging: defaultLogging,
|
logging: defaultLogging,
|
||||||
});
|
});
|
||||||
const settings = createSettings(astroConfig, 'dev', fileURLToPath(root));
|
const settings = createSettings(astroConfig, fileURLToPath(root));
|
||||||
|
|
||||||
let restart = await createContainerWithAutomaticRestart({
|
let restart = await createContainerWithAutomaticRestart({
|
||||||
params: { fs, root, settings },
|
params: { fs, root, settings },
|
||||||
|
@ -199,7 +199,7 @@ describe('dev container restarts', () => {
|
||||||
cmd: 'dev',
|
cmd: 'dev',
|
||||||
logging: defaultLogging,
|
logging: defaultLogging,
|
||||||
});
|
});
|
||||||
const settings = createSettings(astroConfig, 'dev', fileURLToPath(root));
|
const settings = createSettings(astroConfig, fileURLToPath(root));
|
||||||
|
|
||||||
let restart = await createContainerWithAutomaticRestart({
|
let restart = await createContainerWithAutomaticRestart({
|
||||||
params: { fs, root, settings },
|
params: { fs, root, settings },
|
||||||
|
|
Loading…
Reference in a new issue