fix(assets): Fix endpoint not being injected when an integration would enable experimental.assets (#7829)

This commit is contained in:
Erika 2023-07-27 11:37:27 +02:00 committed by GitHub
parent 05ee09f9c2
commit b063a2d8ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 48 additions and 24 deletions

View 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)

View file

@ -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';
} }

View file

@ -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(

View file

@ -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(
{ {

View file

@ -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(

View file

@ -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);
} }

View file

@ -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

View file

@ -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),

View file

@ -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');

View file

@ -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(

View file

@ -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 });
} }

View file

@ -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 },