summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Arsh <lilnasy@users.noreply.github.com> 2024-02-20 14:41:38 +0000
committerGravatar astrobot-houston <fred+astrobot@astro.build> 2024-02-20 14:41:38 +0000
commitc1671dff22db2f9361c0d42dbf4d5dd6fb0674d0 (patch)
tree968342872b1accd4666be76921f4f0ee92bf3f31
parent5acc3135ba5309a566def466fbcbabd23f70cd68 (diff)
downloadastro-c1671dff22db2f9361c0d42dbf4d5dd6fb0674d0.tar.gz
astro-c1671dff22db2f9361c0d42dbf4d5dd6fb0674d0.tar.zst
astro-c1671dff22db2f9361c0d42dbf4d5dd6fb0674d0.zip
[ci] format
-rw-r--r--packages/astro/src/core/app/index.ts27
-rw-r--r--packages/astro/src/core/app/pipeline.ts29
-rw-r--r--packages/astro/src/core/base-pipeline.ts21
-rw-r--r--packages/astro/src/core/build/generate.ts2
-rw-r--r--packages/astro/src/core/build/pipeline.ts48
-rw-r--r--packages/astro/src/core/endpoint/index.ts10
-rw-r--r--packages/astro/src/core/middleware/index.ts19
-rw-r--r--packages/astro/src/core/redirects/helpers.ts1
-rw-r--r--packages/astro/src/core/redirects/render.ts16
-rw-r--r--packages/astro/src/core/render-context.ts180
-rw-r--r--packages/astro/src/core/render/params-and-props.ts3
-rw-r--r--packages/astro/src/i18n/middleware.ts128
-rw-r--r--packages/astro/src/runtime/server/endpoint.ts2
-rw-r--r--packages/astro/src/vite-plugin-astro-server/error.ts5
-rw-r--r--packages/astro/src/vite-plugin-astro-server/pipeline.ts57
-rw-r--r--packages/astro/src/vite-plugin-astro-server/route.ts27
-rw-r--r--packages/astro/test/units/render/head.test.js29
-rw-r--r--packages/astro/test/units/render/jsx.test.js21
-rw-r--r--packages/astro/test/units/test-utils.js6
-rw-r--r--packages/astro/test/units/vite-plugin-astro-server/request.test.js4
20 files changed, 429 insertions, 206 deletions
diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts
index 481fffb41..094ac97b5 100644
--- a/packages/astro/src/core/app/index.ts
+++ b/packages/astro/src/core/app/index.ts
@@ -1,8 +1,4 @@
-import type {
- ManifestData,
- RouteData,
- SSRManifest,
-} from '../../@types/astro.js';
+import type { ManifestData, RouteData, SSRManifest } from '../../@types/astro.js';
import type { SinglePageBuiltModule } from '../build/types.js';
import { getSetCookiesFromResponse } from '../cookies/index.js';
import { consoleLogDestination } from '../logger/console.js';
@@ -20,7 +16,13 @@ import { matchRoute } from '../routing/match.js';
import { AppPipeline } from './pipeline.js';
import { normalizeTheLocale } from '../../i18n/index.js';
import { RenderContext } from '../render-context.js';
-import { clientAddressSymbol, clientLocalsSymbol, responseSentSymbol, REROUTABLE_STATUS_CODES, REROUTE_DIRECTIVE_HEADER } from '../constants.js';
+import {
+ clientAddressSymbol,
+ clientLocalsSymbol,
+ responseSentSymbol,
+ REROUTABLE_STATUS_CODES,
+ REROUTE_DIRECTIVE_HEADER,
+} from '../constants.js';
import { AstroError, AstroErrorData } from '../errors/index.js';
export { deserializeManifest } from './common.js';
@@ -124,7 +126,7 @@ export class App {
},
serverLike: true,
streaming,
- })
+ });
}
set setManifestData(newManifestData: ManifestData) {
@@ -294,7 +296,14 @@ export class App {
let response;
try {
- const renderContext = RenderContext.create({ pipeline: this.#pipeline, locals, pathname, request, routeData, status: defaultStatus })
+ const renderContext = RenderContext.create({
+ pipeline: this.#pipeline,
+ locals,
+ pathname,
+ request,
+ routeData,
+ status: defaultStatus,
+ });
response = await renderContext.render(await mod.page());
} catch (err: any) {
this.#logger.error(null, err.stack || err.message || String(err));
@@ -386,7 +395,7 @@ export class App {
request,
routeData: errorRouteData,
status,
- })
+ });
const response = await renderContext.render(await mod.page());
return this.#mergeResponses(response, originalResponse);
} catch {
diff --git a/packages/astro/src/core/app/pipeline.ts b/packages/astro/src/core/app/pipeline.ts
index 74fa95ec6..b1c615a1e 100644
--- a/packages/astro/src/core/app/pipeline.ts
+++ b/packages/astro/src/core/app/pipeline.ts
@@ -1,14 +1,25 @@
-import type { RouteData, SSRElement, SSRResult } from "../../@types/astro.js";
-import { Pipeline } from "../base-pipeline.js";
-import { createModuleScriptElement, createStylesheetElementSet } from "../render/ssr-element.js";
+import type { RouteData, SSRElement, SSRResult } from '../../@types/astro.js';
+import { Pipeline } from '../base-pipeline.js';
+import { createModuleScriptElement, createStylesheetElementSet } from '../render/ssr-element.js';
export class AppPipeline extends Pipeline {
- static create({ logger, manifest, mode, renderers, resolve, serverLike, streaming }: Pick<AppPipeline, 'logger' | 'manifest' | 'mode' | 'renderers' | 'resolve' | 'serverLike' | 'streaming'>) {
- return new AppPipeline(logger, manifest, mode, renderers, resolve, serverLike, streaming);
- }
+ static create({
+ logger,
+ manifest,
+ mode,
+ renderers,
+ resolve,
+ serverLike,
+ streaming,
+ }: Pick<
+ AppPipeline,
+ 'logger' | 'manifest' | 'mode' | 'renderers' | 'resolve' | 'serverLike' | 'streaming'
+ >) {
+ return new AppPipeline(logger, manifest, mode, renderers, resolve, serverLike, streaming);
+ }
- headElements(routeData: RouteData): Pick<SSRResult, 'scripts' | 'styles' | 'links'> {
- const routeInfo = this.manifest.routes.find(route => route.routeData === routeData);
+ headElements(routeData: RouteData): Pick<SSRResult, 'scripts' | 'styles' | 'links'> {
+ const routeInfo = this.manifest.routes.find((route) => route.routeData === routeData);
// may be used in the future for handling rel=modulepreload, rel=icon, rel=manifest etc.
const links = new Set<never>();
const scripts = new Set<SSRElement>();
@@ -26,7 +37,7 @@ export class AppPipeline extends Pipeline {
scripts.add(createModuleScriptElement(script));
}
}
- return { links, styles, scripts }
+ return { links, styles, scripts };
}
componentMetadata() {}
diff --git a/packages/astro/src/core/base-pipeline.ts b/packages/astro/src/core/base-pipeline.ts
index 5fcf63903..139ee9485 100644
--- a/packages/astro/src/core/base-pipeline.ts
+++ b/packages/astro/src/core/base-pipeline.ts
@@ -1,4 +1,11 @@
-import type { MiddlewareHandler, RouteData, RuntimeMode, SSRLoadedRenderer, SSRManifest, SSRResult } from '../@types/astro.js';
+import type {
+ MiddlewareHandler,
+ RouteData,
+ RuntimeMode,
+ SSRLoadedRenderer,
+ SSRManifest,
+ SSRResult,
+} from '../@types/astro.js';
import type { Logger } from './logger/core.js';
import { RouteCache } from './render/route-cache.js';
import { createI18nMiddleware } from '../i18n/middleware.js';
@@ -6,7 +13,7 @@ import { createI18nMiddleware } from '../i18n/middleware.js';
/**
* The `Pipeline` represents the static parts of rendering that do not change between requests.
* These are mostly known when the server first starts up and do not change.
- *
+ *
* Thus, a `Pipeline` is created once at process start and then used by every `RenderContext`.
*/
export abstract class Pipeline {
@@ -38,13 +45,15 @@ export abstract class Pipeline {
/**
* Used for `Astro.site`.
*/
- readonly site = manifest.site,
+ readonly site = manifest.site
) {
- this.internalMiddleware = [ createI18nMiddleware(i18n, manifest.base, manifest.trailingSlash, manifest.buildFormat) ];
+ this.internalMiddleware = [
+ createI18nMiddleware(i18n, manifest.base, manifest.trailingSlash, manifest.buildFormat),
+ ];
}
- abstract headElements(routeData: RouteData): Promise<HeadElements> | HeadElements
- abstract componentMetadata(routeData: RouteData): Promise<SSRResult['componentMetadata']> | void
+ abstract headElements(routeData: RouteData): Promise<HeadElements> | HeadElements;
+ abstract componentMetadata(routeData: RouteData): Promise<SSRResult['componentMetadata']> | void;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts
index 14462a412..29a32a88b 100644
--- a/packages/astro/src/core/build/generate.ts
+++ b/packages/astro/src/core/build/generate.ts
@@ -499,7 +499,7 @@ async function generatePath(
logger,
ssr: serverLike,
});
- const renderContext = RenderContext.create({ pipeline, pathname, request, routeData: route })
+ const renderContext = RenderContext.create({ pipeline, pathname, request, routeData: route });
let body: string | Uint8Array;
let response: Response;
diff --git a/packages/astro/src/core/build/pipeline.ts b/packages/astro/src/core/build/pipeline.ts
index a2647e456..e6e51c875 100644
--- a/packages/astro/src/core/build/pipeline.ts
+++ b/packages/astro/src/core/build/pipeline.ts
@@ -4,8 +4,17 @@ import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../vite-plugin-sc
import type { SSRManifest } from '../app/types.js';
import { routeIsFallback, routeIsRedirect } from '../redirects/helpers.js';
import { Pipeline } from '../render/index.js';
-import { createAssetLink, createModuleScriptsSet, createStylesheetElementSet } from '../render/ssr-element.js';
-import { getPageDataByComponent, type BuildInternals, cssOrder, mergeInlineCss } from './internal.js';
+import {
+ createAssetLink,
+ createModuleScriptsSet,
+ createStylesheetElementSet,
+} from '../render/ssr-element.js';
+import {
+ getPageDataByComponent,
+ type BuildInternals,
+ cssOrder,
+ mergeInlineCss,
+} from './internal.js';
import {
ASTRO_PAGE_RESOLVED_MODULE_ID,
getVirtualModulePageNameFromPath,
@@ -47,10 +56,22 @@ export class BuildPipeline extends Pipeline {
}
const serverLike = isServerLikeOutput(config);
const streaming = true;
- super(options.logger, manifest, options.mode, manifest.renderers, resolve, serverLike, streaming)
+ super(
+ options.logger,
+ manifest,
+ options.mode,
+ manifest.renderers,
+ resolve,
+ serverLike,
+ streaming
+ );
}
- static create({ internals, manifest, options }: Pick<BuildPipeline, 'internals' | 'manifest' | 'options'>) {
+ static create({
+ internals,
+ manifest,
+ options,
+ }: Pick<BuildPipeline, 'internals' | 'manifest' | 'options'>) {
return new BuildPipeline(internals, manifest, options);
}
@@ -106,17 +127,24 @@ export class BuildPipeline extends Pipeline {
}
headElements(routeData: RouteData): Pick<SSRResult, 'scripts' | 'styles' | 'links'> {
- const { internals, manifest: { assetsPrefix, base }, settings } = this
+ const {
+ internals,
+ manifest: { assetsPrefix, base },
+ settings,
+ } = this;
const links = new Set<never>();
- const pageBuildData = getPageDataByComponent(internals, routeData.component)
+ const pageBuildData = getPageDataByComponent(internals, routeData.component);
const scripts = createModuleScriptsSet(
pageBuildData?.hoistedScript ? [pageBuildData.hoistedScript] : [],
base,
assetsPrefix
);
- const sortedCssAssets = pageBuildData?.styles.sort(cssOrder).map(({ sheet }) => sheet).reduce(mergeInlineCss, []);
+ const sortedCssAssets = pageBuildData?.styles
+ .sort(cssOrder)
+ .map(({ sheet }) => sheet)
+ .reduce(mergeInlineCss, []);
const styles = createStylesheetElementSet(sortedCssAssets ?? [], base, assetsPrefix);
-
+
if (settings.scripts.some((script) => script.stage === 'page')) {
const hashedFilePath = internals.entrySpecifierToBundleMap.get(PAGE_SCRIPT_ID);
if (typeof hashedFilePath !== 'string') {
@@ -128,7 +156,7 @@ export class BuildPipeline extends Pipeline {
children: '',
});
}
-
+
// Add all injected scripts to the page.
for (const script of settings.scripts) {
if (script.stage === 'head-inline') {
@@ -138,7 +166,7 @@ export class BuildPipeline extends Pipeline {
});
}
}
- return { scripts, styles, links }
+ return { scripts, styles, links };
}
componentMetadata() {}
diff --git a/packages/astro/src/core/endpoint/index.ts b/packages/astro/src/core/endpoint/index.ts
index 7a64366a3..54b5dff47 100644
--- a/packages/astro/src/core/endpoint/index.ts
+++ b/packages/astro/src/core/endpoint/index.ts
@@ -1,8 +1,4 @@
-import type {
- APIContext,
- Locales,
- Params,
-} from '../../@types/astro.js';
+import type { APIContext, Locales, Params } from '../../@types/astro.js';
import { ASTRO_VERSION, clientAddressSymbol, clientLocalsSymbol } from '../constants.js';
import type { AstroCookies } from '../cookies/index.js';
import { AstroError, AstroErrorData } from '../errors/index.js';
@@ -23,7 +19,7 @@ type CreateAPIContext = {
routingStrategy: RoutingStrategies | undefined;
defaultLocale: string | undefined;
route: string;
- cookies: AstroCookies
+ cookies: AstroCookies;
};
/**
@@ -41,7 +37,7 @@ export function createAPIContext({
routingStrategy,
defaultLocale,
route,
- cookies
+ cookies,
}: CreateAPIContext): APIContext {
let preferredLocale: string | undefined = undefined;
let preferredLocaleList: string[] | undefined = undefined;
diff --git a/packages/astro/src/core/middleware/index.ts b/packages/astro/src/core/middleware/index.ts
index b72a13f0a..138005f96 100644
--- a/packages/astro/src/core/middleware/index.ts
+++ b/packages/astro/src/core/middleware/index.ts
@@ -38,12 +38,16 @@ export type CreateContext = {
/**
* Creates a context to be passed to Astro middleware `onRequest` function.
*/
-function createContext({ request, params = {}, userDefinedLocales = [] }: CreateContext): APIContext {
+function createContext({
+ request,
+ params = {},
+ userDefinedLocales = [],
+}: CreateContext): APIContext {
let preferredLocale: string | undefined = undefined;
let preferredLocaleList: string[] | undefined = undefined;
let currentLocale: string | undefined = undefined;
const url = new URL(request.url);
- const route = url.pathname
+ const route = url.pathname;
return {
cookies: new AstroCookies(request),
@@ -61,13 +65,18 @@ function createContext({ request, params = {}, userDefinedLocales = [] }: Create
});
},
get preferredLocale(): string | undefined {
- return preferredLocale ??= computePreferredLocale(request, userDefinedLocales);
+ return (preferredLocale ??= computePreferredLocale(request, userDefinedLocales));
},
get preferredLocaleList(): string[] | undefined {
- return preferredLocaleList ??= computePreferredLocaleList(request, userDefinedLocales);
+ return (preferredLocaleList ??= computePreferredLocaleList(request, userDefinedLocales));
},
get currentLocale(): string | undefined {
- return currentLocale ??= computeCurrentLocale(route, userDefinedLocales, undefined, undefined);
+ return (currentLocale ??= computeCurrentLocale(
+ route,
+ userDefinedLocales,
+ undefined,
+ undefined
+ ));
},
url,
get clientAddress() {
diff --git a/packages/astro/src/core/redirects/helpers.ts b/packages/astro/src/core/redirects/helpers.ts
index a55eacfdf..80f18ae0f 100644
--- a/packages/astro/src/core/redirects/helpers.ts
+++ b/packages/astro/src/core/redirects/helpers.ts
@@ -7,4 +7,3 @@ export function routeIsRedirect(route: RouteData | undefined): route is Redirect
export function routeIsFallback(route: RouteData | undefined): route is RedirectRouteData {
return route?.type === 'fallback';
}
-
diff --git a/packages/astro/src/core/redirects/render.ts b/packages/astro/src/core/redirects/render.ts
index 08cf90850..120fab26e 100644
--- a/packages/astro/src/core/redirects/render.ts
+++ b/packages/astro/src/core/redirects/render.ts
@@ -1,18 +1,22 @@
import type { RenderContext } from '../render-context.js';
export async function renderRedirect(renderContext: RenderContext) {
- const { request: { method }, routeData } = renderContext;
+ const {
+ request: { method },
+ routeData,
+ } = renderContext;
const { redirect, redirectRoute } = routeData;
const status =
- redirectRoute && typeof redirect === "object" ? redirect.status
- : method === "GET" ? 301
- : 308
- const headers = { location: redirectRouteGenerate(renderContext) };
+ redirectRoute && typeof redirect === 'object' ? redirect.status : method === 'GET' ? 301 : 308;
+ const headers = { location: redirectRouteGenerate(renderContext) };
return new Response(null, { status, headers });
}
function redirectRouteGenerate(renderContext: RenderContext): string {
- const { params, routeData: { redirect, redirectRoute } } = renderContext;
+ const {
+ params,
+ routeData: { redirect, redirectRoute },
+ } = renderContext;
if (typeof redirectRoute !== 'undefined') {
return redirectRoute?.generate(params) || redirectRoute?.pathname || '/';
diff --git a/packages/astro/src/core/render-context.ts b/packages/astro/src/core/render-context.ts
index fd9ed3d1c..299c188af 100644
--- a/packages/astro/src/core/render-context.ts
+++ b/packages/astro/src/core/render-context.ts
@@ -1,4 +1,9 @@
-import type { APIContext, ComponentInstance, MiddlewareHandler, RouteData } from '../@types/astro.js';
+import type {
+ APIContext,
+ ComponentInstance,
+ MiddlewareHandler,
+ RouteData,
+} from '../@types/astro.js';
import { renderEndpoint } from '../runtime/server/endpoint.js';
import { attachCookiesToResponse } from './cookies/index.js';
import { callMiddleware } from './middleware/callMiddleware.js';
@@ -6,7 +11,12 @@ import { sequence } from './middleware/index.js';
import { AstroCookies } from './cookies/index.js';
import { createResult } from './render/index.js';
import { renderPage } from '../runtime/server/index.js';
-import { ASTRO_VERSION, ROUTE_TYPE_HEADER, clientAddressSymbol, clientLocalsSymbol } from './constants.js';
+import {
+ ASTRO_VERSION,
+ ROUTE_TYPE_HEADER,
+ clientAddressSymbol,
+ clientLocalsSymbol,
+} from './constants.js';
import { getParams, getProps, type Pipeline } from './render/index.js';
import { AstroError, AstroErrorData } from './errors/index.js';
import {
@@ -26,19 +36,36 @@ export class RenderContext {
readonly routeData: RouteData,
public status: number,
readonly cookies = new AstroCookies(request),
- readonly params = getParams(routeData, pathname),
+ readonly params = getParams(routeData, pathname)
) {}
- static create({ locals = {}, middleware, pathname, pipeline, request, routeData, status = 200 }: Pick<RenderContext, 'pathname' |'pipeline' | 'request' | 'routeData'> & Partial<Pick<RenderContext, 'locals' | 'middleware' | 'status'>>) {
- return new RenderContext(pipeline, locals, sequence(...pipeline.internalMiddleware, middleware ?? pipeline.middleware), pathname, request, routeData, status);
+ static create({
+ locals = {},
+ middleware,
+ pathname,
+ pipeline,
+ request,
+ routeData,
+ status = 200,
+ }: Pick<RenderContext, 'pathname' | 'pipeline' | 'request' | 'routeData'> &
+ Partial<Pick<RenderContext, 'locals' | 'middleware' | 'status'>>) {
+ return new RenderContext(
+ pipeline,
+ locals,
+ sequence(...pipeline.internalMiddleware, middleware ?? pipeline.middleware),
+ pathname,
+ request,
+ routeData,
+ status
+ );
}
/**
* The main function of the RenderContext.
- *
+ *
* Use this function to render any route known to Astro.
* It attempts to render a route. A route can be a:
- *
+ *
* - page
* - redirect
* - endpoint
@@ -47,25 +74,46 @@ export class RenderContext {
async render(componentInstance: ComponentInstance | undefined): Promise<Response> {
const { cookies, middleware, pathname, pipeline, routeData } = this;
const { logger, routeCache, serverLike, streaming } = pipeline;
- const props = await getProps({ mod: componentInstance, routeData, routeCache, pathname, logger, serverLike });
+ const props = await getProps({
+ mod: componentInstance,
+ routeData,
+ routeCache,
+ pathname,
+ logger,
+ serverLike,
+ });
const apiContext = this.createAPIContext(props);
const { type } = routeData;
-
+
const lastNext =
- type === 'endpoint' ? () => renderEndpoint(componentInstance as any, apiContext, serverLike, logger) :
- type === 'redirect' ? () => renderRedirect(this) :
- type === 'page' ? async () => {
- const result = await this.createResult(componentInstance!);
- const response = await renderPage(result, componentInstance?.default as any, props, {}, streaming, routeData);
- response.headers.set(ROUTE_TYPE_HEADER, "page");
- return response;
- } :
- type === 'fallback' ? () => new Response(null, { status: 500, headers: { [ROUTE_TYPE_HEADER]: "fallback" } }) :
- () => { throw new Error("Unknown type of route: " + type) }
-
+ type === 'endpoint'
+ ? () => renderEndpoint(componentInstance as any, apiContext, serverLike, logger)
+ : type === 'redirect'
+ ? () => renderRedirect(this)
+ : type === 'page'
+ ? async () => {
+ const result = await this.createResult(componentInstance!);
+ const response = await renderPage(
+ result,
+ componentInstance?.default as any,
+ props,
+ {},
+ streaming,
+ routeData
+ );
+ response.headers.set(ROUTE_TYPE_HEADER, 'page');
+ return response;
+ }
+ : type === 'fallback'
+ ? () =>
+ new Response(null, { status: 500, headers: { [ROUTE_TYPE_HEADER]: 'fallback' } })
+ : () => {
+ throw new Error('Unknown type of route: ' + type);
+ };
+
const response = await callMiddleware(middleware, apiContext, lastNext);
if (response.headers.get(ROUTE_TYPE_HEADER)) {
- response.headers.delete(ROUTE_TYPE_HEADER)
+ response.headers.delete(ROUTE_TYPE_HEADER);
}
// LEGACY: we put cookies on the response object,
// where the adapter might be expecting to read it.
@@ -79,11 +127,22 @@ export class RenderContext {
const { cookies, i18nData, params, pipeline, request } = this;
const { currentLocale, preferredLocale, preferredLocaleList } = i18nData;
const generator = `Astro v${ASTRO_VERSION}`;
- const redirect = (path: string, status = 302) => new Response(null, { status, headers: { Location: path } });
+ const redirect = (path: string, status = 302) =>
+ new Response(null, { status, headers: { Location: path } });
const site = pipeline.site ? new URL(pipeline.site) : undefined;
const url = new URL(request.url);
return {
- cookies, currentLocale, generator, params, preferredLocale, preferredLocaleList, props, redirect, request, site, url,
+ cookies,
+ currentLocale,
+ generator,
+ params,
+ preferredLocale,
+ preferredLocaleList,
+ props,
+ redirect,
+ request,
+ site,
+ url,
get clientAddress() {
if (clientAddressSymbol in request) {
return Reflect.get(request, clientAddressSymbol) as string;
@@ -110,39 +169,80 @@ export class RenderContext {
// where the adapter might be expecting to read it after the response.
Reflect.set(request, clientLocalsSymbol, val);
}
- }
- }
+ },
+ };
}
async createResult(mod: ComponentInstance) {
const { cookies, locals, params, pathname, pipeline, request, routeData, status } = this;
- const { adapterName, clientDirectives, compressHTML, i18n, manifest, logger, renderers, resolve, site, serverLike } = pipeline;
+ const {
+ adapterName,
+ clientDirectives,
+ compressHTML,
+ i18n,
+ manifest,
+ logger,
+ renderers,
+ resolve,
+ site,
+ serverLike,
+ } = pipeline;
const { links, scripts, styles } = await pipeline.headElements(routeData);
- const componentMetadata = await pipeline.componentMetadata(routeData) ?? manifest.componentMetadata;
+ const componentMetadata =
+ (await pipeline.componentMetadata(routeData)) ?? manifest.componentMetadata;
const { defaultLocale, locales, routing: routingStrategy } = i18n ?? {};
const partial = Boolean(mod.partial);
- return createResult({ adapterName, clientDirectives, componentMetadata, compressHTML, cookies, defaultLocale, locales, locals, logger, links, params, partial, pathname, renderers, resolve, request, route: routeData.route, routingStrategy, site, scripts, ssr: serverLike, status, styles });
+ return createResult({
+ adapterName,
+ clientDirectives,
+ componentMetadata,
+ compressHTML,
+ cookies,
+ defaultLocale,
+ locales,
+ locals,
+ logger,
+ links,
+ params,
+ partial,
+ pathname,
+ renderers,
+ resolve,
+ request,
+ route: routeData.route,
+ routingStrategy,
+ site,
+ scripts,
+ ssr: serverLike,
+ status,
+ styles,
+ });
}
/**
* API Context may be created multiple times per request, i18n data needs to be computed only once.
* So, it is computed and saved here on creation of the first APIContext and reused for later ones.
*/
- #i18nData?: Pick<APIContext, "currentLocale" | "preferredLocale" | "preferredLocaleList">
+ #i18nData?: Pick<APIContext, 'currentLocale' | 'preferredLocale' | 'preferredLocaleList'>;
get i18nData() {
- if (this.#i18nData) return this.#i18nData
- const { pipeline: { i18n }, request, routeData } = this;
- if (!i18n) return {
- currentLocale: undefined,
- preferredLocale: undefined,
- preferredLocaleList: undefined
- }
- const { defaultLocale, locales, routing } = i18n
- return this.#i18nData = {
+ if (this.#i18nData) return this.#i18nData;
+ const {
+ pipeline: { i18n },
+ request,
+ routeData,
+ } = this;
+ if (!i18n)
+ return {
+ currentLocale: undefined,
+ preferredLocale: undefined,
+ preferredLocaleList: undefined,
+ };
+ const { defaultLocale, locales, routing } = i18n;
+ return (this.#i18nData = {
currentLocale: computeCurrentLocale(routeData.route, locales, routing, defaultLocale),
preferredLocale: computePreferredLocale(request, locales),
- preferredLocaleList: computePreferredLocaleList(request, locales)
- }
+ preferredLocaleList: computePreferredLocaleList(request, locales),
+ });
}
}
diff --git a/packages/astro/src/core/render/params-and-props.ts b/packages/astro/src/core/render/params-and-props.ts
index ff901cd84..b0a589ab1 100644
--- a/packages/astro/src/core/render/params-and-props.ts
+++ b/packages/astro/src/core/render/params-and-props.ts
@@ -24,11 +24,10 @@ export async function getProps(opts: GetParamsAndPropsOptions): Promise<Props> {
return {};
}
-
if (routeIsRedirect(route) || routeIsFallback(route)) {
return {};
}
-
+
// This is a dynamic route, start getting the params
const params = getParams(route, pathname);
if (mod) {
diff --git a/packages/astro/src/i18n/middleware.ts b/packages/astro/src/i18n/middleware.ts
index 91091cbec..815ac2e9c 100644
--- a/packages/astro/src/i18n/middleware.ts
+++ b/packages/astro/src/i18n/middleware.ts
@@ -2,7 +2,7 @@ import { appendForwardSlash, joinPaths } from '@astrojs/internal-helpers/path';
import type { APIContext, Locales, MiddlewareHandler, SSRManifest } from '../@types/astro.js';
import { getPathByLocale, normalizeTheLocale } from './index.js';
import { shouldAppendForwardSlash } from '../core/build/util.js';
-import type { SSRManifestI18n } from '../core/app/types.js'
+import type { SSRManifestI18n } from '../core/app/types.js';
import { ROUTE_TYPE_HEADER } from '../core/constants.js';
// Checks if the pathname has any locale, exception for the defaultLocale, which is ignored on purpose.
@@ -102,100 +102,100 @@ export function createI18nMiddleware(
const type = response.headers.get(ROUTE_TYPE_HEADER);
// If the route we're processing is not a page, then we ignore it
if (type !== 'page' && type !== 'fallback') {
- return response
+ return response;
}
const { url, currentLocale } = context;
const { locales, defaultLocale, fallback, routing } = i18n;
- switch (i18n.routing) {
- case 'domains-prefix-other-locales': {
- if (localeHasntDomain(i18n, currentLocale)) {
- const result = prefixOtherLocales(url, response);
- if (result) {
- return result;
- }
- }
- break;
- }
- case 'pathname-prefix-other-locales': {
+ switch (i18n.routing) {
+ case 'domains-prefix-other-locales': {
+ if (localeHasntDomain(i18n, currentLocale)) {
const result = prefixOtherLocales(url, response);
if (result) {
return result;
}
- break;
}
-
- case 'domains-prefix-always-no-redirect': {
- if (localeHasntDomain(i18n, currentLocale)) {
- const result = prefixAlwaysNoRedirect(url, response);
- if (result) {
- return result;
- }
- }
- break;
+ break;
+ }
+ case 'pathname-prefix-other-locales': {
+ const result = prefixOtherLocales(url, response);
+ if (result) {
+ return result;
}
+ break;
+ }
- case 'pathname-prefix-always-no-redirect': {
+ case 'domains-prefix-always-no-redirect': {
+ if (localeHasntDomain(i18n, currentLocale)) {
const result = prefixAlwaysNoRedirect(url, response);
if (result) {
return result;
}
- break;
}
+ break;
+ }
+
+ case 'pathname-prefix-always-no-redirect': {
+ const result = prefixAlwaysNoRedirect(url, response);
+ if (result) {
+ return result;
+ }
+ break;
+ }
- case 'pathname-prefix-always': {
+ case 'pathname-prefix-always': {
+ const result = prefixAlways(url, response, context);
+ if (result) {
+ return result;
+ }
+ break;
+ }
+ case 'domains-prefix-always': {
+ if (localeHasntDomain(i18n, currentLocale)) {
const result = prefixAlways(url, response, context);
if (result) {
return result;
}
- break;
- }
- case 'domains-prefix-always': {
- if (localeHasntDomain(i18n, currentLocale)) {
- const result = prefixAlways(url, response, context);
- if (result) {
- return result;
- }
- }
- break;
}
+ break;
}
+ }
+
+ if (response.status >= 300 && fallback) {
+ const fallbackKeys = i18n.fallback ? Object.keys(i18n.fallback) : [];
- if (response.status >= 300 && fallback) {
- const fallbackKeys = i18n.fallback ? Object.keys(i18n.fallback) : [];
-
- // we split the URL using the `/`, and then check in the returned array we have the locale
- const segments = url.pathname.split('/');
- const urlLocale = segments.find((segment) => {
- for (const locale of locales) {
- if (typeof locale === 'string') {
- if (locale === segment) {
- return true;
- }
- } else if (locale.path === segment) {
+ // we split the URL using the `/`, and then check in the returned array we have the locale
+ const segments = url.pathname.split('/');
+ const urlLocale = segments.find((segment) => {
+ for (const locale of locales) {
+ if (typeof locale === 'string') {
+ if (locale === segment) {
return true;
}
+ } else if (locale.path === segment) {
+ return true;
}
- return false;
- });
-
- if (urlLocale && fallbackKeys.includes(urlLocale)) {
- const fallbackLocale = fallback[urlLocale];
- // the user might have configured the locale using the granular locales, so we want to retrieve its corresponding path instead
- const pathFallbackLocale = getPathByLocale(fallbackLocale, locales);
- let newPathname: string;
- // If a locale falls back to the default locale, we want to **remove** the locale because
- // the default locale doesn't have a prefix
- if (pathFallbackLocale === defaultLocale && routing === 'pathname-prefix-other-locales') {
- newPathname = url.pathname.replace(`/${urlLocale}`, ``);
- } else {
- newPathname = url.pathname.replace(`/${urlLocale}`, `/${pathFallbackLocale}`);
- }
+ }
+ return false;
+ });
- return context.redirect(newPathname);
+ if (urlLocale && fallbackKeys.includes(urlLocale)) {
+ const fallbackLocale = fallback[urlLocale];
+ // the user might have configured the locale using the granular locales, so we want to retrieve its corresponding path instead
+ const pathFallbackLocale = getPathByLocale(fallbackLocale, locales);
+ let newPathname: string;
+ // If a locale falls back to the default locale, we want to **remove** the locale because
+ // the default locale doesn't have a prefix
+ if (pathFallbackLocale === defaultLocale && routing === 'pathname-prefix-other-locales') {
+ newPathname = url.pathname.replace(`/${urlLocale}`, ``);
+ } else {
+ newPathname = url.pathname.replace(`/${urlLocale}`, `/${pathFallbackLocale}`);
}
+
+ return context.redirect(newPathname);
}
+ }
return response;
};
diff --git a/packages/astro/src/runtime/server/endpoint.ts b/packages/astro/src/runtime/server/endpoint.ts
index 2afee2f23..55dd5d0ae 100644
--- a/packages/astro/src/runtime/server/endpoint.ts
+++ b/packages/astro/src/runtime/server/endpoint.ts
@@ -1,5 +1,5 @@
import { bold } from 'kleur/colors';
-import { REROUTABLE_STATUS_CODES, REROUTE_DIRECTIVE_HEADER } from '../../core/constants.js';;
+import { REROUTABLE_STATUS_CODES, REROUTE_DIRECTIVE_HEADER } from '../../core/constants.js';
import type { APIContext, EndpointHandler } from '../../@types/astro.js';
import type { Logger } from '../../core/logger/core.js';
diff --git a/packages/astro/src/vite-plugin-astro-server/error.ts b/packages/astro/src/vite-plugin-astro-server/error.ts
index 3bfd9f5f9..d096c0422 100644
--- a/packages/astro/src/vite-plugin-astro-server/error.ts
+++ b/packages/astro/src/vite-plugin-astro-server/error.ts
@@ -29,10 +29,7 @@ export function recordServerError(
telemetry.record(eventError({ cmd: 'dev', err: errorWithMetadata, isFatal: false }));
}
- logger.error(
- null,
- formatErrorMessage(errorWithMetadata, logger.level() === 'debug')
- );
+ logger.error(null, formatErrorMessage(errorWithMetadata, logger.level() === 'debug'));
return {
error: err,
diff --git a/packages/astro/src/vite-plugin-astro-server/pipeline.ts b/packages/astro/src/vite-plugin-astro-server/pipeline.ts
index f2a6a1712..bf0a666e3 100644
--- a/packages/astro/src/vite-plugin-astro-server/pipeline.ts
+++ b/packages/astro/src/vite-plugin-astro-server/pipeline.ts
@@ -1,5 +1,13 @@
-import url from 'node:url'
-import type { AstroSettings, ComponentInstance, DevToolbarMetadata, RouteData, SSRElement, SSRLoadedRenderer, SSRManifest } from '../@types/astro.js';
+import url from 'node:url';
+import type {
+ AstroSettings,
+ ComponentInstance,
+ DevToolbarMetadata,
+ RouteData,
+ SSRElement,
+ SSRLoadedRenderer,
+ SSRManifest,
+} from '../@types/astro.js';
import type { Logger } from '../core/logger/core.js';
import type { ModuleLoader } from '../core/module-loader/index.js';
import { Pipeline, loadRenderer } from '../core/render/index.js';
@@ -19,28 +27,38 @@ import { getComponentMetadata } from './metadata.js';
export class DevPipeline extends Pipeline {
// renderers are loaded on every request,
// so it needs to be mutable here unlike in other environments
- override renderers = new Array<SSRLoadedRenderer>
+ override renderers = new Array<SSRLoadedRenderer>();
private constructor(
readonly loader: ModuleLoader,
readonly logger: Logger,
readonly manifest: SSRManifest,
readonly settings: AstroSettings,
- readonly config = settings.config,
+ readonly config = settings.config
) {
- const mode = 'development'
+ const mode = 'development';
const resolve = createResolve(loader, config.root);
const serverLike = isServerLikeOutput(config);
const streaming = true;
super(logger, manifest, mode, [], resolve, serverLike, streaming);
}
- static create({ loader, logger, manifest, settings }: Pick<DevPipeline, 'loader' | 'logger' | 'manifest' | 'settings'>) {
- return new DevPipeline(loader, logger, manifest, settings)
+ static create({
+ loader,
+ logger,
+ manifest,
+ settings,
+ }: Pick<DevPipeline, 'loader' | 'logger' | 'manifest' | 'settings'>) {
+ return new DevPipeline(loader, logger, manifest, settings);
}
async headElements(routeData: RouteData): Promise<HeadElements> {
- const { config: { root }, loader, mode, settings } = this;
+ const {
+ config: { root },
+ loader,
+ mode,
+ settings,
+ } = this;
const filePath = new URL(`./${routeData.component}`, root);
const { scripts } = await getScriptsForURL(filePath, root, loader);
@@ -55,9 +73,9 @@ export class DevPipeline extends Pipeline {
settings.config.devToolbar.enabled &&
(await settings.preferences.get('devToolbar.enabled'))
) {
- const src = await resolveIdToUrl(loader, 'astro/runtime/client/dev-toolbar/entrypoint.js')
+ const src = await resolveIdToUrl(loader, 'astro/runtime/client/dev-toolbar/entrypoint.js');
scripts.add({ props: { type: 'module', src }, children: '' });
-
+
const additionalMetadata: DevToolbarMetadata['__astro_dev_toolbar__'] = {
root: url.fileURLToPath(settings.config.root),
version: ASTRO_VERSION,
@@ -69,7 +87,7 @@ export class DevPipeline extends Pipeline {
scripts.add({ props: {}, children });
}
}
-
+
// TODO: We should allow adding generic HTML elements to the head, not just scripts
for (const script of settings.scripts) {
if (script.stage === 'head-inline') {
@@ -99,15 +117,18 @@ export class DevPipeline extends Pipeline {
// But we still want to inject the styles to avoid FOUC. The style tags
// should emulate what Vite injects so further HMR works as expected.
styles.add({ props: { 'data-vite-dev-id': id }, children: content });
- };
-
- return { scripts, styles, links }
+ }
+
+ return { scripts, styles, links };
}
componentMetadata(routeData: RouteData) {
- const { config: { root }, loader } = this;
+ const {
+ config: { root },
+ loader,
+ } = this;
const filePath = new URL(`./${routeData.component}`, root);
- return getComponentMetadata(filePath, loader)
+ return getComponentMetadata(filePath, loader);
}
async preload(filePath: URL) {
@@ -120,13 +141,13 @@ export class DevPipeline extends Pipeline {
try {
// Load the module from the Vite SSR Runtime.
- return await loader.import(viteID(filePath)) as ComponentInstance;
+ return (await loader.import(viteID(filePath))) as ComponentInstance;
} catch (error) {
// If the error came from Markdown or CSS, we already handled it and there's no need to enhance it
if (MarkdownError.is(error) || CSSError.is(error) || AggregateError.is(error)) {
throw error;
}
-
+
throw enhanceViteSSRError({ error, filePath, loader });
}
}
diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts
index ff76d4556..bc9c5de03 100644
--- a/packages/astro/src/vite-plugin-astro-server/route.ts
+++ b/packages/astro/src/vite-plugin-astro-server/route.ts
@@ -1,9 +1,5 @@
import type http from 'node:http';
-import type {
- ComponentInstance,
- ManifestData,
- RouteData,
-} from '../@types/astro.js';
+import type { ComponentInstance, ManifestData, RouteData } from '../@types/astro.js';
import { AstroErrorData, isAstroError } from '../core/errors/index.js';
import { req } from '../core/messages.js';
import { loadMiddleware } from '../core/middleware/loadMiddleware.js';
@@ -158,7 +154,7 @@ export async function handleRoute({
let options: SSROptions | undefined = undefined;
let route: RouteData;
const middleware = (await loadMiddleware(loader)).onRequest;
-
+
if (!matchedRoute) {
if (config.i18n) {
const locales = config.i18n.locales;
@@ -208,7 +204,13 @@ export async function handleRoute({
fallbackRoutes: [],
isIndex: false,
};
- renderContext = RenderContext.create({ pipeline: pipeline, pathname, middleware, request, routeData: route });
+ renderContext = RenderContext.create({
+ pipeline: pipeline,
+ pathname,
+ middleware,
+ request,
+ routeData: route,
+ });
} else {
return handle404Response(origin, incomingRequest, incomingResponse);
}
@@ -217,7 +219,7 @@ export async function handleRoute({
const { preloadedComponent } = matchedRoute;
route = matchedRoute.route;
// Allows adapters to pass in locals in dev mode.
- const locals = Reflect.get(incomingRequest, clientLocalsSymbol)
+ const locals = Reflect.get(incomingRequest, clientLocalsSymbol);
request = createRequest({
url,
// Headers are only available when using SSR.
@@ -244,7 +246,14 @@ export async function handleRoute({
};
mod = preloadedComponent;
- renderContext = RenderContext.create({ locals, pipeline, pathname, middleware, request, routeData: route });
+ renderContext = RenderContext.create({
+ locals,
+ pipeline,
+ pathname,
+ middleware,
+ request,
+ routeData: route,
+ });
}
let response = await renderContext.render(mod);
diff --git a/packages/astro/test/units/render/head.test.js b/packages/astro/test/units/render/head.test.js
index 67077c9dd..ce494336a 100644
--- a/packages/astro/test/units/render/head.test.js
+++ b/packages/astro/test/units/render/head.test.js
@@ -21,9 +21,11 @@ describe('core/render', () => {
before(async () => {
pipeline = createBasicPipeline();
pipeline.headElements = () => ({
- links: new Set([{ name: 'link', props: { rel: 'stylesheet', href: '/main.css' }, children: '' }]),
- scripts: new Set,
- styles: new Set
+ links: new Set([
+ { name: 'link', props: { rel: 'stylesheet', href: '/main.css' }, children: '' },
+ ]),
+ scripts: new Set(),
+ styles: new Set(),
});
});
@@ -95,7 +97,12 @@ describe('core/render', () => {
const PageModule = createAstroModule(Page);
const request = new Request('http://example.com/');
- const routeData = { type: 'page', pathname: '/index', component: 'src/pages/index.astro', params: {} };
+ const routeData = {
+ type: 'page',
+ pathname: '/index',
+ component: 'src/pages/index.astro',
+ params: {},
+ };
const renderContext = RenderContext.create({ pipeline, request, routeData });
const response = await renderContext.render(PageModule);
@@ -171,7 +178,12 @@ describe('core/render', () => {
const PageModule = createAstroModule(Page);
const request = new Request('http://example.com/');
- const routeData = { type: 'page', pathname: '/index', component: 'src/pages/index.astro', params: {} };
+ const routeData = {
+ type: 'page',
+ pathname: '/index',
+ component: 'src/pages/index.astro',
+ params: {},
+ };
const renderContext = RenderContext.create({ pipeline, request, routeData });
const response = await renderContext.render(PageModule);
@@ -214,7 +226,12 @@ describe('core/render', () => {
const PageModule = createAstroModule(Page);
const request = new Request('http://example.com/');
- const routeData = { type: 'page', pathname: '/index', component: 'src/pages/index.astro', params: {} };
+ const routeData = {
+ type: 'page',
+ pathname: '/index',
+ component: 'src/pages/index.astro',
+ params: {},
+ };
const renderContext = RenderContext.create({ pipeline, request, routeData });
const response = await renderContext.render(PageModule);
diff --git a/packages/astro/test/units/render/jsx.test.js b/packages/astro/test/units/render/jsx.test.js
index ca2485a45..e2df9a60d 100644
--- a/packages/astro/test/units/render/jsx.test.js
+++ b/packages/astro/test/units/render/jsx.test.js
@@ -43,7 +43,12 @@ describe('core/render', () => {
const mod = createAstroModule(Page);
const request = new Request('http://example.com/');
- const routeData = { type: 'page', pathname: '/index', component: 'src/pages/index.mdx', params: {} };
+ const routeData = {
+ type: 'page',
+ pathname: '/index',
+ component: 'src/pages/index.mdx',
+ params: {},
+ };
const renderContext = RenderContext.create({ pipeline, request, routeData });
const response = await renderContext.render(mod);
@@ -85,7 +90,12 @@ describe('core/render', () => {
const mod = createAstroModule(Page);
const request = new Request('http://example.com/');
- const routeData = { type: 'page', pathname: '/index', component: 'src/pages/index.mdx', params: {} };
+ const routeData = {
+ type: 'page',
+ pathname: '/index',
+ component: 'src/pages/index.mdx',
+ params: {},
+ };
const renderContext = RenderContext.create({ pipeline, request, routeData });
const response = await renderContext.render(mod);
@@ -111,7 +121,12 @@ describe('core/render', () => {
const mod = createAstroModule(Page);
const request = new Request('http://example.com/');
- const routeData = { type: 'page', pathname: '/index', component: 'src/pages/index.mdx', params: {} };
+ const routeData = {
+ type: 'page',
+ pathname: '/index',
+ component: 'src/pages/index.mdx',
+ params: {},
+ };
const renderContext = RenderContext.create({ pipeline, request, routeData });
const response = await renderContext.render(mod);
diff --git a/packages/astro/test/units/test-utils.js b/packages/astro/test/units/test-utils.js
index d9d7c7c4e..6133687ae 100644
--- a/packages/astro/test/units/test-utils.js
+++ b/packages/astro/test/units/test-utils.js
@@ -191,7 +191,7 @@ export function createBasicPipeline(options = {}) {
options.manifest ?? {},
options.mode ?? 'development',
options.renderers ?? [],
- options.resolve ?? (s => Promise.resolve(s)),
+ options.resolve ?? ((s) => Promise.resolve(s)),
options.serverLike ?? true,
options.streaming ?? true,
options.adapterName,
@@ -202,9 +202,9 @@ export function createBasicPipeline(options = {}) {
options.routeCache ?? new RouteCache(options.logging, mode),
options.site
);
- pipeline.headElements = () => ({ scripts: new Set, styles: new Set, links: new Set });
+ pipeline.headElements = () => ({ scripts: new Set(), styles: new Set(), links: new Set() });
pipeline.componentMetadata = () => {};
- return pipeline
+ return pipeline;
}
/**
diff --git a/packages/astro/test/units/vite-plugin-astro-server/request.test.js b/packages/astro/test/units/vite-plugin-astro-server/request.test.js
index 36f05c41a..63d2d2a5f 100644
--- a/packages/astro/test/units/vite-plugin-astro-server/request.test.js
+++ b/packages/astro/test/units/vite-plugin-astro-server/request.test.js
@@ -29,7 +29,7 @@ describe('vite-plugin-astro-server', () => {
loader: createLoader({
import(id) {
if (id === '\0astro-internal:middleware') {
- return { onRequest: (_, next) => next() }
+ return { onRequest: (_, next) => next() };
}
const Page = createComponent(() => {
return render`<div id="test">testing</div>`;
@@ -62,7 +62,7 @@ describe('vite-plugin-astro-server', () => {
controller,
incomingRequest: req,
incomingResponse: res,
- manifest: {}
+ manifest: {},
});
} catch (err) {
assert.equal(err.message, undefined);