0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-03-10 23:01:26 -05:00

chore: update adapters to better support astro v5 (#454)

Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev>
This commit is contained in:
Alexander Niebuhr 2025-01-07 16:52:23 +01:00 committed by GitHub
parent a76194514b
commit 03f15c41f1
5 changed files with 172 additions and 41 deletions

View file

@ -31,7 +31,6 @@
"@astrojs/internal-helpers": "0.4.2", "@astrojs/internal-helpers": "0.4.2",
"@astrojs/underscore-redirects": "^0.5.0", "@astrojs/underscore-redirects": "^0.5.0",
"@cloudflare/workers-types": "^4.20241230.0", "@cloudflare/workers-types": "^4.20241230.0",
"@inox-tools/astro-when": "^1.0.2",
"esbuild": "^0.24.0", "esbuild": "^0.24.0",
"estree-walker": "^3.0.3", "estree-walker": "^3.0.3",
"magic-string": "^0.30.17", "magic-string": "^0.30.17",

View file

@ -1,23 +1,12 @@
import { When, whenAmI } from '@it-astro:when';
import type { MiddlewareHandler } from 'astro'; import type { MiddlewareHandler } from 'astro';
const middlewares: Record<When, MiddlewareHandler> = { export const onRequest: MiddlewareHandler = (context, next) => {
[When.Client]: () => { if (context.isPrerendered) {
throw new Error('Client should not run a middleware!');
},
[When.DevServer]: (_, next) => next(),
[When.Server]: (_, next) => next(),
[When.Prerender]: (ctx, next) => {
// @ts-expect-error // @ts-expect-error
if (ctx.locals.runtime === undefined) { context.locals.runtime ??= {
// @ts-expect-error
ctx.locals.runtime = {
env: process.env, env: process.env,
}; };
} }
return next();
},
[When.StaticBuild]: (_, next) => next(),
};
export const onRequest = middlewares[whenAmI]; return next();
};

View file

@ -1,4 +1,10 @@
import type { AstroConfig, AstroIntegration, HookParameters, IntegrationRouteData } from 'astro'; import type {
AstroConfig,
AstroIntegration,
HookParameters,
IntegrationResolvedRoute,
IntegrationRouteData,
} from 'astro';
import type { PluginOption } from 'vite'; import type { PluginOption } from 'vite';
import { createReadStream } from 'node:fs'; import { createReadStream } from 'node:fs';
@ -10,7 +16,6 @@ import {
removeLeadingForwardSlash, removeLeadingForwardSlash,
} from '@astrojs/internal-helpers/path'; } from '@astrojs/internal-helpers/path';
import { createRedirectsFromAstroRoutes } from '@astrojs/underscore-redirects'; import { createRedirectsFromAstroRoutes } from '@astrojs/underscore-redirects';
import astroWhen from '@inox-tools/astro-when';
import { AstroError } from 'astro/errors'; import { AstroError } from 'astro/errors';
import { defaultClientConditions } from 'vite'; import { defaultClientConditions } from 'vite';
import { type GetPlatformProxyOptions, getPlatformProxy } from 'wrangler'; import { type GetPlatformProxyOptions, getPlatformProxy } from 'wrangler';
@ -86,6 +91,28 @@ function setProcessEnv(config: AstroConfig, env: Record<string, unknown>) {
} }
} }
function resolvedRouteToRouteData(
assets: HookParameters<'astro:build:done'>['assets'],
route: IntegrationResolvedRoute
): IntegrationRouteData {
return {
pattern: route.patternRegex,
component: route.entrypoint,
prerender: route.isPrerendered,
route: route.pattern,
generate: route.generate,
params: route.params,
segments: route.segments,
type: route.type,
pathname: route.pathname,
redirect: route.redirect,
distURL: assets.get(route.pattern),
redirectRoute: route.redirectRoute
? resolvedRouteToRouteData(assets, route.redirectRoute)
: undefined,
};
}
export default function createIntegration(args?: Options): AstroIntegration { export default function createIntegration(args?: Options): AstroIntegration {
let _config: AstroConfig; let _config: AstroConfig;
let finalBuildOutput: HookParameters<'astro:config:done'>['buildOutput']; let finalBuildOutput: HookParameters<'astro:config:done'>['buildOutput'];
@ -94,6 +121,8 @@ export default function createIntegration(args?: Options): AstroIntegration {
args?.cloudflareModules ?? true args?.cloudflareModules ?? true
); );
let _routes: IntegrationResolvedRoute[];
return { return {
name: '@astrojs/cloudflare', name: '@astrojs/cloudflare',
hooks: { hooks: {
@ -129,7 +158,6 @@ export default function createIntegration(args?: Options): AstroIntegration {
}, },
], ],
}, },
integrations: [astroWhen()],
image: setImageConfig(args?.imageService ?? 'compile', config.image, command, logger), image: setImageConfig(args?.imageService ?? 'compile', config.image, command, logger),
}); });
if (args?.platformProxy?.configPath) { if (args?.platformProxy?.configPath) {
@ -144,6 +172,9 @@ export default function createIntegration(args?: Options): AstroIntegration {
order: 'pre', order: 'pre',
}); });
}, },
'astro:routes:resolved': ({ routes }) => {
_routes = routes;
},
'astro:config:done': ({ setAdapter, config, buildOutput, logger }) => { 'astro:config:done': ({ setAdapter, config, buildOutput, logger }) => {
if (buildOutput === 'static') { if (buildOutput === 'static') {
logger.warn( logger.warn(
@ -167,7 +198,11 @@ export default function createIntegration(args?: Options): AstroIntegration {
hybridOutput: 'stable', hybridOutput: 'stable',
staticOutput: 'unsupported', staticOutput: 'unsupported',
i18nDomains: 'experimental', i18nDomains: 'experimental',
sharpImageService: 'limited', sharpImageService: {
support: 'limited',
message:
'Cloudflare does not support sharp. You can use the `compile` image service to compile images at build time. It will not work for any on-demand rendered images.',
},
envGetSecret: 'stable', envGetSecret: 'stable',
}, },
}); });
@ -260,7 +295,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
}; };
} }
}, },
'astro:build:done': async ({ pages, routes, dir, logger }) => { 'astro:build:done': async ({ pages, dir, logger, assets }) => {
await cloudflareModulePlugin.afterBuildCompleted(_config); await cloudflareModulePlugin.afterBuildCompleted(_config);
const PLATFORM_FILES = ['_headers', '_redirects', '_routes.json']; const PLATFORM_FILES = ['_headers', '_redirects', '_routes.json'];
if (_config.base !== '/') { if (_config.base !== '/') {
@ -285,7 +320,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
redirectsExists = false; redirectsExists = false;
} }
const redirects: IntegrationRouteData['segments'][] = []; const redirects: IntegrationResolvedRoute['segments'][] = [];
if (redirectsExists) { if (redirectsExists) {
const rl = createInterface({ const rl = createInterface({
input: createReadStream(new URL('./_redirects', _config.outDir)), input: createReadStream(new URL('./_redirects', _config.outDir)),
@ -324,7 +359,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
await createRoutesFile( await createRoutesFile(
_config, _config,
logger, logger,
routes, _routes,
pages, pages,
redirects, redirects,
args?.routes?.extend?.include, args?.routes?.extend?.include,
@ -333,8 +368,10 @@ export default function createIntegration(args?: Options): AstroIntegration {
} }
const redirectRoutes: [IntegrationRouteData, string][] = []; const redirectRoutes: [IntegrationRouteData, string][] = [];
for (const route of routes) { for (const route of _routes) {
if (route.type === 'redirect') redirectRoutes.push([route, '']); // TODO: Replace workaround after upstream @astrojs/underscore-redirects is changed, to support new IntegrationResolvedRoute type
if (route.type === 'redirect')
redirectRoutes.push([resolvedRouteToRouteData(assets, route), '']);
} }
const trueRedirects = createRedirectsFromAstroRoutes({ const trueRedirects = createRedirectsFromAstroRoutes({

View file

@ -1,4 +1,9 @@
import type { AstroConfig, AstroIntegrationLogger, IntegrationRouteData, RoutePart } from 'astro'; import type {
AstroConfig,
AstroIntegrationLogger,
IntegrationResolvedRoute,
RoutePart,
} from 'astro';
import { existsSync } from 'node:fs'; import { existsSync } from 'node:fs';
import { writeFile } from 'node:fs/promises'; import { writeFile } from 'node:fs/promises';
@ -63,7 +68,7 @@ async function writeRoutesFileToOutDir(
} }
} }
function segmentsToCfSyntax(segments: IntegrationRouteData['segments'], _config: AstroConfig) { function segmentsToCfSyntax(segments: IntegrationResolvedRoute['segments'], _config: AstroConfig) {
const pathSegments = []; const pathSegments = [];
if (removeLeadingForwardSlash(removeTrailingForwardSlash(_config.base)).length > 0) { if (removeLeadingForwardSlash(removeTrailingForwardSlash(_config.base)).length > 0) {
pathSegments.push(removeLeadingForwardSlash(removeTrailingForwardSlash(_config.base))); pathSegments.push(removeLeadingForwardSlash(removeTrailingForwardSlash(_config.base)));
@ -163,11 +168,11 @@ class PathTrie {
export async function createRoutesFile( export async function createRoutesFile(
_config: AstroConfig, _config: AstroConfig,
logger: AstroIntegrationLogger, logger: AstroIntegrationLogger,
routes: IntegrationRouteData[], routes: IntegrationResolvedRoute[],
pages: { pages: {
pathname: string; pathname: string;
}[], }[],
redirects: IntegrationRouteData['segments'][], redirects: IntegrationResolvedRoute['segments'][],
includeExtends: includeExtends:
| { | {
pattern: string; pattern: string;
@ -223,17 +228,17 @@ export async function createRoutesFile(
let hasPrerendered404 = false; let hasPrerendered404 = false;
for (const route of routes) { for (const route of routes) {
const convertedPath = segmentsToCfSyntax(route.segments, _config); const convertedPath = segmentsToCfSyntax(route.segments, _config);
if (route.pathname === '/404' && route.prerender === true) hasPrerendered404 = true; if (route.pathname === '/404' && route.isPrerendered === true) hasPrerendered404 = true;
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
switch (route.type) { switch (route.type) {
case 'page': case 'page':
if (route.prerender === false) includePaths.push(convertedPath); if (route.isPrerendered === false) includePaths.push(convertedPath);
break; break;
case 'endpoint': case 'endpoint':
if (route.prerender === false) includePaths.push(convertedPath); if (route.isPrerendered === false) includePaths.push(convertedPath);
else excludePaths.push(convertedPath); else excludePaths.push(convertedPath);
break; break;

View file

@ -23,7 +23,7 @@ describe('_routes.json generation', () => {
assert.deepEqual(routes, { assert.deepEqual(routes, {
version: 1, version: 1,
include: ['/_image', '/a/*'], include: ['/_server-islands/*', '/_image', '/a/*'],
exclude: ['/_astro/*', '/redirectme', '/public.txt', '/a', '/a/redirect', '/404', '/b'], exclude: ['/_astro/*', '/redirectme', '/public.txt', '/a', '/a/redirect', '/404', '/b'],
}); });
}); });
@ -101,7 +101,7 @@ describe('_routes.json generation', () => {
assert.deepEqual(routes, { assert.deepEqual(routes, {
version: 1, version: 1,
include: ['/_image', '/a/*', '/another'], include: ['/_server-islands/*', '/_image', '/a/*', '/another'],
exclude: ['/_astro/*', '/redirectme', '/public.txt', '/a', '/a/redirect', '/404', '/b'], exclude: ['/_astro/*', '/redirectme', '/public.txt', '/a', '/a/redirect', '/404', '/b'],
}); });
}); });
@ -131,7 +131,7 @@ describe('_routes.json generation', () => {
assert.deepEqual(routes, { assert.deepEqual(routes, {
version: 1, version: 1,
include: ['/_image', '/a/*'], include: ['/_server-islands/*', '/_image', '/a/*'],
exclude: [ exclude: [
'/_astro/*', '/_astro/*',
'/redirectme', '/redirectme',
@ -167,6 +167,7 @@ describe('_routes.json generation', () => {
version: 1, version: 1,
include: [ include: [
'/', '/',
'/_server-islands/*',
'/_image', '/_image',
'/dynamicPages/*', '/dynamicPages/*',
'/mixedPages/dynamic', '/mixedPages/dynamic',
@ -234,8 +235,108 @@ describe('_routes.json generation', () => {
assert.deepEqual(routes, { assert.deepEqual(routes, {
version: 1, version: 1,
include: ['/_image', '/dynamic'], include: ['/*'],
exclude: [], exclude: [
'/_astro/*',
'/redirectme',
'/public.txt',
'/a/*',
'/404',
'/0',
'/1',
'/2',
'/3',
'/4',
'/5',
'/6',
'/7',
'/8',
'/9',
'/10',
'/11',
'/12',
'/13',
'/14',
'/15',
'/16',
'/17',
'/18',
'/19',
'/20',
'/21',
'/22',
'/23',
'/24',
'/25',
'/26',
'/27',
'/28',
'/29',
'/30',
'/31',
'/32',
'/33',
'/34',
'/35',
'/36',
'/37',
'/38',
'/39',
'/40',
'/41',
'/42',
'/43',
'/44',
'/45',
'/46',
'/47',
'/48',
'/49',
'/50',
'/51',
'/52',
'/53',
'/54',
'/55',
'/56',
'/57',
'/58',
'/59',
'/60',
'/61',
'/62',
'/63',
'/64',
'/65',
'/66',
'/67',
'/68',
'/69',
'/70',
'/71',
'/72',
'/73',
'/74',
'/75',
'/76',
'/77',
'/78',
'/79',
'/80',
'/81',
'/82',
'/83',
'/84',
'/85',
'/86',
'/87',
'/88',
'/89',
'/90',
'/91',
'/92',
'/93',
],
}); });
}); });
}); });