astro 4.4.0 → 4.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/@types/astro.d.ts +42 -42
- package/dist/assets/build/generate.d.ts +1 -1
- package/dist/assets/build/generate.js +1 -2
- package/dist/cli/add/babel.d.ts +1 -1
- package/dist/cli/add/index.js +1 -1
- package/dist/cli/db/index.js +2 -0
- package/dist/cli/info/index.js +2 -0
- package/dist/cli/preferences/index.js +2 -0
- package/dist/content/types-generator.js +4 -4
- package/dist/core/app/index.js +40 -123
- package/dist/core/app/pipeline.d.ts +7 -0
- package/dist/core/app/pipeline.js +39 -0
- package/dist/core/app/types.d.ts +2 -2
- package/dist/core/base-pipeline.d.ts +59 -0
- package/dist/core/base-pipeline.js +27 -0
- package/dist/core/build/generate.d.ts +1 -1
- package/dist/core/build/generate.js +41 -110
- package/dist/core/build/index.js +0 -4
- package/dist/core/build/{buildPipeline.d.ts → pipeline.d.ts} +13 -13
- package/dist/core/build/pipeline.js +180 -0
- package/dist/core/build/plugins/plugin-manifest.js +3 -2
- package/dist/core/build/types.d.ts +0 -2
- package/dist/core/config/schema.d.ts +37 -54
- package/dist/core/config/schema.js +10 -39
- package/dist/core/constants.d.ts +10 -1
- package/dist/core/constants.js +14 -4
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/dev/restart.js +1 -1
- package/dist/core/endpoint/index.d.ts +6 -5
- package/dist/core/endpoint/index.js +7 -34
- package/dist/core/errors/errors-data.d.ts +3 -3
- package/dist/core/messages.js +2 -2
- package/dist/core/middleware/callMiddleware.d.ts +1 -1
- package/dist/core/middleware/callMiddleware.js +2 -9
- package/dist/core/middleware/index.d.ts +2 -2
- package/dist/core/middleware/index.js +74 -9
- package/dist/core/module-loader/vite.js +4 -4
- package/dist/core/preview/index.js +2 -0
- package/dist/core/preview/static-preview-server.js +1 -7
- package/dist/core/redirects/helpers.d.ts +1 -3
- package/dist/core/redirects/helpers.js +0 -29
- package/dist/core/redirects/index.d.ts +2 -1
- package/dist/core/redirects/index.js +3 -3
- package/dist/core/redirects/render.d.ts +2 -0
- package/dist/core/redirects/render.js +33 -0
- package/dist/core/render/index.d.ts +7 -13
- package/dist/core/render/index.js +7 -7
- package/dist/core/render/params-and-props.d.ts +8 -3
- package/dist/core/render/params-and-props.js +24 -16
- package/dist/core/render/result.d.ts +8 -7
- package/dist/core/render/result.js +4 -5
- package/dist/core/render-context.d.ts +32 -0
- package/dist/core/render-context.js +219 -0
- package/dist/core/routing/index.d.ts +0 -1
- package/dist/core/routing/index.js +0 -2
- package/dist/core/routing/manifest/create.js +5 -3
- package/dist/core/routing/params.d.ts +1 -7
- package/dist/core/routing/params.js +0 -15
- package/dist/core/sync/index.js +3 -3
- package/dist/i18n/index.d.ts +4 -4
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/middleware.d.ts +0 -5
- package/dist/i18n/middleware.js +62 -70
- package/dist/i18n/utils.d.ts +26 -0
- package/dist/{core/render/context.js → i18n/utils.js} +32 -50
- package/dist/prerender/routing.d.ts +1 -1
- package/dist/prerender/routing.js +2 -3
- package/dist/runtime/client/dev-toolbar/apps/astro.js +13 -9
- package/dist/runtime/client/dev-toolbar/apps/audit/a11y.js +2 -2
- package/dist/runtime/server/endpoint.js +2 -2
- package/dist/virtual-modules/i18n.js +7 -5
- package/dist/vite-plugin-astro/hmr.d.ts +1 -0
- package/dist/vite-plugin-astro/hmr.js +7 -4
- package/dist/vite-plugin-astro-server/error.d.ts +2 -2
- package/dist/vite-plugin-astro-server/error.js +2 -5
- package/dist/vite-plugin-astro-server/index.d.ts +0 -6
- package/dist/vite-plugin-astro-server/index.js +0 -19
- package/dist/vite-plugin-astro-server/pipeline.d.ts +19 -0
- package/dist/vite-plugin-astro-server/pipeline.js +117 -0
- package/dist/vite-plugin-astro-server/plugin.js +5 -5
- package/dist/vite-plugin-astro-server/request.d.ts +3 -4
- package/dist/vite-plugin-astro-server/request.js +6 -9
- package/dist/vite-plugin-astro-server/route.d.ts +3 -4
- package/dist/vite-plugin-astro-server/route.js +34 -162
- package/dist/vite-plugin-dev-toolbar/vite-plugin-dev-toolbar.js +3 -3
- package/package.json +3 -8
- package/dist/core/app/ssrPipeline.d.ts +0 -3
- package/dist/core/app/ssrPipeline.js +0 -6
- package/dist/core/build/buildPipeline.js +0 -150
- package/dist/core/pipeline.d.ts +0 -39
- package/dist/core/pipeline.js +0 -107
- package/dist/core/render/context.d.ts +0 -52
- package/dist/core/render/core.d.ts +0 -10
- package/dist/core/render/core.js +0 -65
- package/dist/core/render/environment.d.ts +0 -34
- package/dist/core/render/environment.js +0 -6
- package/dist/runtime/server/consts.d.ts +0 -1
- package/dist/runtime/server/consts.js +0 -4
- package/dist/vite-plugin-astro-server/devPipeline.d.ts +0 -22
- package/dist/vite-plugin-astro-server/devPipeline.js +0 -65
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { fileURLToPath } from "node:url";
|
|
2
2
|
import { performance } from "perf_hooks";
|
|
3
|
-
import enableDestroy from "server-destroy";
|
|
4
3
|
import { preview } from "vite";
|
|
5
4
|
import * as msg from "../messages.js";
|
|
6
5
|
import { getResolvedHostForHttpServer } from "./util.js";
|
|
@@ -30,7 +29,6 @@ async function createStaticPreviewServer(settings, logger) {
|
|
|
30
29
|
}
|
|
31
30
|
throw err;
|
|
32
31
|
}
|
|
33
|
-
enableDestroy(previewServer.httpServer);
|
|
34
32
|
logger.info(
|
|
35
33
|
"SKIP_FORMAT",
|
|
36
34
|
msg.serverStart({
|
|
@@ -51,11 +49,7 @@ async function createStaticPreviewServer(settings, logger) {
|
|
|
51
49
|
port: settings.config.server.port,
|
|
52
50
|
closed,
|
|
53
51
|
server: previewServer.httpServer,
|
|
54
|
-
stop:
|
|
55
|
-
await new Promise((resolve, reject) => {
|
|
56
|
-
previewServer.httpServer.destroy((err) => err ? reject(err) : resolve(void 0));
|
|
57
|
-
});
|
|
58
|
-
}
|
|
52
|
+
stop: previewServer.close.bind(previewServer)
|
|
59
53
|
};
|
|
60
54
|
}
|
|
61
55
|
export {
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RedirectRouteData, RouteData } from '../../@types/astro.js';
|
|
2
2
|
export declare function routeIsRedirect(route: RouteData | undefined): route is RedirectRouteData;
|
|
3
3
|
export declare function routeIsFallback(route: RouteData | undefined): route is RedirectRouteData;
|
|
4
|
-
export declare function redirectRouteGenerate(redirectRoute: RouteData, data: Params): string;
|
|
5
|
-
export declare function redirectRouteStatus(redirectRoute: RouteData, method?: string): ValidRedirectStatus;
|
|
@@ -4,36 +4,7 @@ function routeIsRedirect(route) {
|
|
|
4
4
|
function routeIsFallback(route) {
|
|
5
5
|
return route?.type === "fallback";
|
|
6
6
|
}
|
|
7
|
-
function redirectRouteGenerate(redirectRoute, data) {
|
|
8
|
-
const routeData = redirectRoute.redirectRoute;
|
|
9
|
-
const route = redirectRoute.redirect;
|
|
10
|
-
if (typeof routeData !== "undefined") {
|
|
11
|
-
return routeData?.generate(data) || routeData?.pathname || "/";
|
|
12
|
-
} else if (typeof route === "string") {
|
|
13
|
-
let target = route;
|
|
14
|
-
for (const param of Object.keys(data)) {
|
|
15
|
-
const paramValue = data[param];
|
|
16
|
-
target = target.replace(`[${param}]`, paramValue);
|
|
17
|
-
target = target.replace(`[...${param}]`, paramValue);
|
|
18
|
-
}
|
|
19
|
-
return target;
|
|
20
|
-
} else if (typeof route === "undefined") {
|
|
21
|
-
return "/";
|
|
22
|
-
}
|
|
23
|
-
return route.destination;
|
|
24
|
-
}
|
|
25
|
-
function redirectRouteStatus(redirectRoute, method = "GET") {
|
|
26
|
-
const routeData = redirectRoute.redirectRoute;
|
|
27
|
-
if (routeData && typeof redirectRoute.redirect === "object") {
|
|
28
|
-
return redirectRoute.redirect.status;
|
|
29
|
-
} else if (method !== "GET") {
|
|
30
|
-
return 308;
|
|
31
|
-
}
|
|
32
|
-
return 301;
|
|
33
|
-
}
|
|
34
7
|
export {
|
|
35
|
-
redirectRouteGenerate,
|
|
36
|
-
redirectRouteStatus,
|
|
37
8
|
routeIsFallback,
|
|
38
9
|
routeIsRedirect
|
|
39
10
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { RedirectComponentInstance, RedirectSinglePageBuiltModule } from './component.js';
|
|
2
|
-
export {
|
|
2
|
+
export { routeIsRedirect } from './helpers.js';
|
|
3
3
|
export { getRedirectLocationOrThrow } from './validate.js';
|
|
4
|
+
export { renderRedirect } from './render.js';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { RedirectComponentInstance, RedirectSinglePageBuiltModule } from "./component.js";
|
|
2
|
-
import {
|
|
2
|
+
import { routeIsRedirect } from "./helpers.js";
|
|
3
3
|
import { getRedirectLocationOrThrow } from "./validate.js";
|
|
4
|
+
import { renderRedirect } from "./render.js";
|
|
4
5
|
export {
|
|
5
6
|
RedirectComponentInstance,
|
|
6
7
|
RedirectSinglePageBuiltModule,
|
|
7
8
|
getRedirectLocationOrThrow,
|
|
8
|
-
|
|
9
|
-
redirectRouteStatus,
|
|
9
|
+
renderRedirect,
|
|
10
10
|
routeIsRedirect
|
|
11
11
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
async function renderRedirect(renderContext) {
|
|
2
|
+
const {
|
|
3
|
+
request: { method },
|
|
4
|
+
routeData
|
|
5
|
+
} = renderContext;
|
|
6
|
+
const { redirect, redirectRoute } = routeData;
|
|
7
|
+
const status = redirectRoute && typeof redirect === "object" ? redirect.status : method === "GET" ? 301 : 308;
|
|
8
|
+
const headers = { location: redirectRouteGenerate(renderContext) };
|
|
9
|
+
return new Response(null, { status, headers });
|
|
10
|
+
}
|
|
11
|
+
function redirectRouteGenerate(renderContext) {
|
|
12
|
+
const {
|
|
13
|
+
params,
|
|
14
|
+
routeData: { redirect, redirectRoute }
|
|
15
|
+
} = renderContext;
|
|
16
|
+
if (typeof redirectRoute !== "undefined") {
|
|
17
|
+
return redirectRoute?.generate(params) || redirectRoute?.pathname || "/";
|
|
18
|
+
} else if (typeof redirect === "string") {
|
|
19
|
+
let target = redirect;
|
|
20
|
+
for (const param of Object.keys(params)) {
|
|
21
|
+
const paramValue = params[param];
|
|
22
|
+
target = target.replace(`[${param}]`, paramValue);
|
|
23
|
+
target = target.replace(`[...${param}]`, paramValue);
|
|
24
|
+
}
|
|
25
|
+
return target;
|
|
26
|
+
} else if (typeof redirect === "undefined") {
|
|
27
|
+
return "/";
|
|
28
|
+
}
|
|
29
|
+
return redirect.destination;
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
renderRedirect
|
|
33
|
+
};
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
export {
|
|
4
|
-
export
|
|
5
|
-
export { createEnvironment } from './environment.js';
|
|
6
|
-
export { getParamsAndProps } from './params-and-props.js';
|
|
1
|
+
import type { ComponentInstance, RouteData } from '../../@types/astro.js';
|
|
2
|
+
import type { Pipeline } from '../base-pipeline.js';
|
|
3
|
+
export { Pipeline } from '../base-pipeline.js';
|
|
4
|
+
export { getParams, getProps } from './params-and-props.js';
|
|
7
5
|
export { loadRenderer } from './renderer.js';
|
|
8
|
-
export
|
|
6
|
+
export { createResult } from './result.js';
|
|
9
7
|
export interface SSROptions {
|
|
10
|
-
/** The
|
|
11
|
-
|
|
8
|
+
/** The pipeline instance */
|
|
9
|
+
pipeline: Pipeline;
|
|
12
10
|
/** location of file on disk */
|
|
13
11
|
filePath: URL;
|
|
14
12
|
/** the web request (needed for dynamic routes) */
|
|
@@ -19,8 +17,4 @@ export interface SSROptions {
|
|
|
19
17
|
request: Request;
|
|
20
18
|
/** optional, in case we need to render something outside a dev server */
|
|
21
19
|
route: RouteData;
|
|
22
|
-
/**
|
|
23
|
-
* Optional middlewares
|
|
24
|
-
*/
|
|
25
|
-
middleware?: AstroMiddlewareInstance;
|
|
26
20
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { getParamsAndProps } from "./params-and-props.js";
|
|
1
|
+
import { Pipeline } from "../base-pipeline.js";
|
|
2
|
+
import { getParams, getProps } from "./params-and-props.js";
|
|
4
3
|
import { loadRenderer } from "./renderer.js";
|
|
4
|
+
import { createResult } from "./result.js";
|
|
5
5
|
export {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
Pipeline,
|
|
7
|
+
createResult,
|
|
8
|
+
getParams,
|
|
9
|
+
getProps,
|
|
10
10
|
loadRenderer
|
|
11
11
|
};
|
|
@@ -3,11 +3,16 @@ import type { Logger } from '../logger/core.js';
|
|
|
3
3
|
import type { RouteCache } from './route-cache.js';
|
|
4
4
|
interface GetParamsAndPropsOptions {
|
|
5
5
|
mod: ComponentInstance | undefined;
|
|
6
|
-
|
|
6
|
+
routeData?: RouteData | undefined;
|
|
7
7
|
routeCache: RouteCache;
|
|
8
8
|
pathname: string;
|
|
9
9
|
logger: Logger;
|
|
10
|
-
|
|
10
|
+
serverLike: boolean;
|
|
11
11
|
}
|
|
12
|
-
export declare function
|
|
12
|
+
export declare function getProps(opts: GetParamsAndPropsOptions): Promise<Props>;
|
|
13
|
+
/**
|
|
14
|
+
* When given a route with the pattern `/[x]/[y]/[z]/svelte`, and a pathname `/a/b/c/svelte`,
|
|
15
|
+
* returns the params object: { x: "a", y: "b", z: "c" }.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getParams(route: RouteData, pathname: string): Params;
|
|
13
18
|
export {};
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
2
2
|
import { routeIsFallback } from "../redirects/helpers.js";
|
|
3
3
|
import { routeIsRedirect } from "../redirects/index.js";
|
|
4
|
-
import { getParams } from "../routing/params.js";
|
|
5
4
|
import { callGetStaticPaths, findPathItemByKey } from "./route-cache.js";
|
|
6
|
-
async function
|
|
7
|
-
const { logger, mod, route, routeCache, pathname,
|
|
5
|
+
async function getProps(opts) {
|
|
6
|
+
const { logger, mod, routeData: route, routeCache, pathname, serverLike } = opts;
|
|
8
7
|
if (!route || route.pathname) {
|
|
9
|
-
return
|
|
8
|
+
return {};
|
|
10
9
|
}
|
|
11
|
-
const params = getRouteParams(route, pathname) ?? {};
|
|
12
10
|
if (routeIsRedirect(route) || routeIsFallback(route)) {
|
|
13
|
-
return
|
|
11
|
+
return {};
|
|
14
12
|
}
|
|
13
|
+
const params = getParams(route, pathname);
|
|
15
14
|
if (mod) {
|
|
16
15
|
validatePrerenderEndpointCollision(route, mod, params);
|
|
17
16
|
}
|
|
@@ -20,10 +19,10 @@ async function getParamsAndProps(opts) {
|
|
|
20
19
|
route,
|
|
21
20
|
routeCache,
|
|
22
21
|
logger,
|
|
23
|
-
ssr
|
|
22
|
+
ssr: serverLike
|
|
24
23
|
});
|
|
25
24
|
const matchedStaticPath = findPathItemByKey(staticPaths, params, route, logger);
|
|
26
|
-
if (!matchedStaticPath && (
|
|
25
|
+
if (!matchedStaticPath && (serverLike ? route.prerender : true)) {
|
|
27
26
|
throw new AstroError({
|
|
28
27
|
...AstroErrorData.NoMatchingStaticPathFound,
|
|
29
28
|
message: AstroErrorData.NoMatchingStaticPathFound.message(pathname),
|
|
@@ -31,15 +30,23 @@ async function getParamsAndProps(opts) {
|
|
|
31
30
|
});
|
|
32
31
|
}
|
|
33
32
|
const props = matchedStaticPath?.props ? { ...matchedStaticPath.props } : {};
|
|
34
|
-
return
|
|
33
|
+
return props;
|
|
35
34
|
}
|
|
36
|
-
function
|
|
37
|
-
if (route.params.length)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
function getParams(route, pathname) {
|
|
36
|
+
if (!route.params.length)
|
|
37
|
+
return {};
|
|
38
|
+
const paramsMatch = route.pattern.exec(decodeURIComponent(pathname));
|
|
39
|
+
if (!paramsMatch)
|
|
40
|
+
return {};
|
|
41
|
+
const params = {};
|
|
42
|
+
route.params.forEach((key, i) => {
|
|
43
|
+
if (key.startsWith("...")) {
|
|
44
|
+
params[key.slice(3)] = paramsMatch[i + 1] ? paramsMatch[i + 1] : void 0;
|
|
45
|
+
} else {
|
|
46
|
+
params[key] = paramsMatch[i + 1];
|
|
41
47
|
}
|
|
42
|
-
}
|
|
48
|
+
});
|
|
49
|
+
return params;
|
|
43
50
|
}
|
|
44
51
|
function validatePrerenderEndpointCollision(route, mod, params) {
|
|
45
52
|
if (route.type === "endpoint" && mod.getStaticPaths) {
|
|
@@ -59,5 +66,6 @@ function validatePrerenderEndpointCollision(route, mod, params) {
|
|
|
59
66
|
}
|
|
60
67
|
}
|
|
61
68
|
export {
|
|
62
|
-
|
|
69
|
+
getParams,
|
|
70
|
+
getProps
|
|
63
71
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Locales, Params, SSRElement, SSRLoadedRenderer, SSRResult } from '../../@types/astro.js';
|
|
2
2
|
import { AstroCookies } from '../cookies/index.js';
|
|
3
3
|
import type { Logger } from '../logger/core.js';
|
|
4
|
-
import type
|
|
4
|
+
import { type RoutingStrategies } from '../../i18n/utils.js';
|
|
5
5
|
export interface CreateResultArgs {
|
|
6
6
|
/**
|
|
7
7
|
* Used to provide better error messages for `Astro.clientAddress`
|
|
@@ -23,16 +23,17 @@ export interface CreateResultArgs {
|
|
|
23
23
|
* Used for `Astro.site`
|
|
24
24
|
*/
|
|
25
25
|
site: string | undefined;
|
|
26
|
-
links
|
|
27
|
-
scripts
|
|
28
|
-
styles
|
|
29
|
-
componentMetadata
|
|
26
|
+
links: Set<SSRElement>;
|
|
27
|
+
scripts: Set<SSRElement>;
|
|
28
|
+
styles: Set<SSRElement>;
|
|
29
|
+
componentMetadata: SSRResult['componentMetadata'];
|
|
30
30
|
request: Request;
|
|
31
31
|
status: number;
|
|
32
32
|
locals: App.Locals;
|
|
33
|
-
cookies
|
|
33
|
+
cookies: AstroCookies;
|
|
34
34
|
locales: Locales | undefined;
|
|
35
35
|
defaultLocale: string | undefined;
|
|
36
|
-
|
|
36
|
+
route: string;
|
|
37
|
+
strategy: RoutingStrategies | undefined;
|
|
37
38
|
}
|
|
38
39
|
export declare function createResult(args: CreateResultArgs): SSRResult;
|
|
@@ -7,9 +7,8 @@ import {
|
|
|
7
7
|
computeCurrentLocale,
|
|
8
8
|
computePreferredLocale,
|
|
9
9
|
computePreferredLocaleList
|
|
10
|
-
} from "
|
|
11
|
-
|
|
12
|
-
const responseSentSymbol = Symbol.for("astro.responseSent");
|
|
10
|
+
} from "../../i18n/utils.js";
|
|
11
|
+
import { clientAddressSymbol, responseSentSymbol } from "../constants.js";
|
|
13
12
|
function getFunctionExpression(slot) {
|
|
14
13
|
if (!slot)
|
|
15
14
|
return;
|
|
@@ -160,9 +159,9 @@ function createResult(args) {
|
|
|
160
159
|
}
|
|
161
160
|
if (args.locales) {
|
|
162
161
|
currentLocale = computeCurrentLocale(
|
|
163
|
-
|
|
162
|
+
url.pathname,
|
|
164
163
|
args.locales,
|
|
165
|
-
args.
|
|
164
|
+
args.strategy,
|
|
166
165
|
args.defaultLocale
|
|
167
166
|
);
|
|
168
167
|
if (currentLocale) {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { APIContext, ComponentInstance, MiddlewareHandler, RouteData } from '../@types/astro.js';
|
|
2
|
+
import { AstroCookies } from './cookies/index.js';
|
|
3
|
+
import { type Pipeline } from './render/index.js';
|
|
4
|
+
export declare class RenderContext {
|
|
5
|
+
#private;
|
|
6
|
+
readonly pipeline: Pipeline;
|
|
7
|
+
locals: App.Locals;
|
|
8
|
+
readonly middleware: MiddlewareHandler;
|
|
9
|
+
readonly pathname: string;
|
|
10
|
+
readonly request: Request;
|
|
11
|
+
readonly routeData: RouteData;
|
|
12
|
+
status: number;
|
|
13
|
+
readonly cookies: AstroCookies;
|
|
14
|
+
readonly params: import("../@types/astro.js").Params;
|
|
15
|
+
private constructor();
|
|
16
|
+
static create({ locals, middleware, pathname, pipeline, request, routeData, status, }: Pick<RenderContext, 'pathname' | 'pipeline' | 'request' | 'routeData'> & Partial<Pick<RenderContext, 'locals' | 'middleware' | 'status'>>): RenderContext;
|
|
17
|
+
/**
|
|
18
|
+
* The main function of the RenderContext.
|
|
19
|
+
*
|
|
20
|
+
* Use this function to render any route known to Astro.
|
|
21
|
+
* It attempts to render a route. A route can be a:
|
|
22
|
+
*
|
|
23
|
+
* - page
|
|
24
|
+
* - redirect
|
|
25
|
+
* - endpoint
|
|
26
|
+
* - fallback
|
|
27
|
+
*/
|
|
28
|
+
render(componentInstance: ComponentInstance | undefined): Promise<Response>;
|
|
29
|
+
createAPIContext(props: APIContext['props']): APIContext;
|
|
30
|
+
createResult(mod: ComponentInstance): Promise<import("../@types/astro.js").SSRResult>;
|
|
31
|
+
get i18nData(): Pick<APIContext<Record<string, any>, Record<string, string | undefined>>, "currentLocale" | "preferredLocale" | "preferredLocaleList">;
|
|
32
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { renderEndpoint } from "../runtime/server/endpoint.js";
|
|
2
|
+
import { attachCookiesToResponse } from "./cookies/index.js";
|
|
3
|
+
import { callMiddleware } from "./middleware/callMiddleware.js";
|
|
4
|
+
import { sequence } from "./middleware/index.js";
|
|
5
|
+
import { AstroCookies } from "./cookies/index.js";
|
|
6
|
+
import { createResult } from "./render/index.js";
|
|
7
|
+
import { renderPage } from "../runtime/server/index.js";
|
|
8
|
+
import {
|
|
9
|
+
ASTRO_VERSION,
|
|
10
|
+
ROUTE_TYPE_HEADER,
|
|
11
|
+
clientAddressSymbol,
|
|
12
|
+
clientLocalsSymbol
|
|
13
|
+
} from "./constants.js";
|
|
14
|
+
import { getParams, getProps } from "./render/index.js";
|
|
15
|
+
import { AstroError, AstroErrorData } from "./errors/index.js";
|
|
16
|
+
import {
|
|
17
|
+
computeCurrentLocale,
|
|
18
|
+
computePreferredLocale,
|
|
19
|
+
computePreferredLocaleList
|
|
20
|
+
} from "../i18n/utils.js";
|
|
21
|
+
import { renderRedirect } from "./redirects/render.js";
|
|
22
|
+
class RenderContext {
|
|
23
|
+
constructor(pipeline, locals, middleware, pathname, request, routeData, status, cookies = new AstroCookies(request), params = getParams(routeData, pathname)) {
|
|
24
|
+
this.pipeline = pipeline;
|
|
25
|
+
this.locals = locals;
|
|
26
|
+
this.middleware = middleware;
|
|
27
|
+
this.pathname = pathname;
|
|
28
|
+
this.request = request;
|
|
29
|
+
this.routeData = routeData;
|
|
30
|
+
this.status = status;
|
|
31
|
+
this.cookies = cookies;
|
|
32
|
+
this.params = params;
|
|
33
|
+
}
|
|
34
|
+
static create({
|
|
35
|
+
locals = {},
|
|
36
|
+
middleware,
|
|
37
|
+
pathname,
|
|
38
|
+
pipeline,
|
|
39
|
+
request,
|
|
40
|
+
routeData,
|
|
41
|
+
status = 200
|
|
42
|
+
}) {
|
|
43
|
+
return new RenderContext(
|
|
44
|
+
pipeline,
|
|
45
|
+
locals,
|
|
46
|
+
sequence(...pipeline.internalMiddleware, middleware ?? pipeline.middleware),
|
|
47
|
+
pathname,
|
|
48
|
+
request,
|
|
49
|
+
routeData,
|
|
50
|
+
status
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The main function of the RenderContext.
|
|
55
|
+
*
|
|
56
|
+
* Use this function to render any route known to Astro.
|
|
57
|
+
* It attempts to render a route. A route can be a:
|
|
58
|
+
*
|
|
59
|
+
* - page
|
|
60
|
+
* - redirect
|
|
61
|
+
* - endpoint
|
|
62
|
+
* - fallback
|
|
63
|
+
*/
|
|
64
|
+
async render(componentInstance) {
|
|
65
|
+
const { cookies, middleware, pathname, pipeline, routeData } = this;
|
|
66
|
+
const { logger, routeCache, serverLike, streaming } = pipeline;
|
|
67
|
+
const props = await getProps({
|
|
68
|
+
mod: componentInstance,
|
|
69
|
+
routeData,
|
|
70
|
+
routeCache,
|
|
71
|
+
pathname,
|
|
72
|
+
logger,
|
|
73
|
+
serverLike
|
|
74
|
+
});
|
|
75
|
+
const apiContext = this.createAPIContext(props);
|
|
76
|
+
const { type } = routeData;
|
|
77
|
+
const lastNext = type === "endpoint" ? () => renderEndpoint(componentInstance, apiContext, serverLike, logger) : type === "redirect" ? () => renderRedirect(this) : type === "page" ? async () => {
|
|
78
|
+
const result = await this.createResult(componentInstance);
|
|
79
|
+
const response2 = await renderPage(
|
|
80
|
+
result,
|
|
81
|
+
componentInstance?.default,
|
|
82
|
+
props,
|
|
83
|
+
{},
|
|
84
|
+
streaming,
|
|
85
|
+
routeData
|
|
86
|
+
);
|
|
87
|
+
response2.headers.set(ROUTE_TYPE_HEADER, "page");
|
|
88
|
+
return response2;
|
|
89
|
+
} : type === "fallback" ? () => new Response(null, { status: 500, headers: { [ROUTE_TYPE_HEADER]: "fallback" } }) : () => {
|
|
90
|
+
throw new Error("Unknown type of route: " + type);
|
|
91
|
+
};
|
|
92
|
+
const response = await callMiddleware(middleware, apiContext, lastNext);
|
|
93
|
+
if (response.headers.get(ROUTE_TYPE_HEADER)) {
|
|
94
|
+
response.headers.delete(ROUTE_TYPE_HEADER);
|
|
95
|
+
}
|
|
96
|
+
attachCookiesToResponse(response, cookies);
|
|
97
|
+
return response;
|
|
98
|
+
}
|
|
99
|
+
createAPIContext(props) {
|
|
100
|
+
const renderContext = this;
|
|
101
|
+
const { cookies, i18nData, params, pipeline, request } = this;
|
|
102
|
+
const { currentLocale, preferredLocale, preferredLocaleList } = i18nData;
|
|
103
|
+
const generator = `Astro v${ASTRO_VERSION}`;
|
|
104
|
+
const redirect = (path, status = 302) => new Response(null, { status, headers: { Location: path } });
|
|
105
|
+
const site = pipeline.site ? new URL(pipeline.site) : void 0;
|
|
106
|
+
const url = new URL(request.url);
|
|
107
|
+
return {
|
|
108
|
+
cookies,
|
|
109
|
+
currentLocale,
|
|
110
|
+
generator,
|
|
111
|
+
params,
|
|
112
|
+
preferredLocale,
|
|
113
|
+
preferredLocaleList,
|
|
114
|
+
props,
|
|
115
|
+
redirect,
|
|
116
|
+
request,
|
|
117
|
+
site,
|
|
118
|
+
url,
|
|
119
|
+
get clientAddress() {
|
|
120
|
+
if (clientAddressSymbol in request) {
|
|
121
|
+
return Reflect.get(request, clientAddressSymbol);
|
|
122
|
+
}
|
|
123
|
+
if (pipeline.adapterName) {
|
|
124
|
+
throw new AstroError({
|
|
125
|
+
...AstroErrorData.ClientAddressNotAvailable,
|
|
126
|
+
message: AstroErrorData.ClientAddressNotAvailable.message(pipeline.adapterName)
|
|
127
|
+
});
|
|
128
|
+
} else {
|
|
129
|
+
throw new AstroError(AstroErrorData.StaticClientAddressNotAvailable);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
get locals() {
|
|
133
|
+
return renderContext.locals;
|
|
134
|
+
},
|
|
135
|
+
// TODO(breaking): disallow replacing the locals object
|
|
136
|
+
set locals(val) {
|
|
137
|
+
if (typeof val !== "object") {
|
|
138
|
+
throw new AstroError(AstroErrorData.LocalsNotAnObject);
|
|
139
|
+
} else {
|
|
140
|
+
renderContext.locals = val;
|
|
141
|
+
Reflect.set(request, clientLocalsSymbol, val);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
async createResult(mod) {
|
|
147
|
+
const { cookies, locals, params, pathname, pipeline, request, routeData, status } = this;
|
|
148
|
+
const {
|
|
149
|
+
adapterName,
|
|
150
|
+
clientDirectives,
|
|
151
|
+
compressHTML,
|
|
152
|
+
i18n,
|
|
153
|
+
manifest,
|
|
154
|
+
logger,
|
|
155
|
+
renderers,
|
|
156
|
+
resolve,
|
|
157
|
+
site,
|
|
158
|
+
serverLike
|
|
159
|
+
} = pipeline;
|
|
160
|
+
const { links, scripts, styles } = await pipeline.headElements(routeData);
|
|
161
|
+
const componentMetadata = await pipeline.componentMetadata(routeData) ?? manifest.componentMetadata;
|
|
162
|
+
const { defaultLocale, locales, strategy } = i18n ?? {};
|
|
163
|
+
const partial = Boolean(mod.partial);
|
|
164
|
+
return createResult({
|
|
165
|
+
adapterName,
|
|
166
|
+
clientDirectives,
|
|
167
|
+
componentMetadata,
|
|
168
|
+
compressHTML,
|
|
169
|
+
cookies,
|
|
170
|
+
defaultLocale,
|
|
171
|
+
locales,
|
|
172
|
+
locals,
|
|
173
|
+
logger,
|
|
174
|
+
links,
|
|
175
|
+
params,
|
|
176
|
+
partial,
|
|
177
|
+
pathname,
|
|
178
|
+
renderers,
|
|
179
|
+
resolve,
|
|
180
|
+
request,
|
|
181
|
+
route: routeData.route,
|
|
182
|
+
strategy,
|
|
183
|
+
site,
|
|
184
|
+
scripts,
|
|
185
|
+
ssr: serverLike,
|
|
186
|
+
status,
|
|
187
|
+
styles
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* API Context may be created multiple times per request, i18n data needs to be computed only once.
|
|
192
|
+
* So, it is computed and saved here on creation of the first APIContext and reused for later ones.
|
|
193
|
+
*/
|
|
194
|
+
#i18nData;
|
|
195
|
+
get i18nData() {
|
|
196
|
+
if (this.#i18nData)
|
|
197
|
+
return this.#i18nData;
|
|
198
|
+
const {
|
|
199
|
+
pipeline: { i18n },
|
|
200
|
+
request,
|
|
201
|
+
routeData
|
|
202
|
+
} = this;
|
|
203
|
+
if (!i18n)
|
|
204
|
+
return {
|
|
205
|
+
currentLocale: void 0,
|
|
206
|
+
preferredLocale: void 0,
|
|
207
|
+
preferredLocaleList: void 0
|
|
208
|
+
};
|
|
209
|
+
const { defaultLocale, locales, strategy } = i18n;
|
|
210
|
+
return this.#i18nData = {
|
|
211
|
+
currentLocale: computeCurrentLocale(routeData.route, locales, strategy, defaultLocale),
|
|
212
|
+
preferredLocale: computePreferredLocale(request, locales),
|
|
213
|
+
preferredLocaleList: computePreferredLocaleList(request, locales)
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
export {
|
|
218
|
+
RenderContext
|
|
219
|
+
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { createRouteManifest } from './manifest/create.js';
|
|
2
2
|
export { deserializeRouteData, serializeRouteData } from './manifest/serialization.js';
|
|
3
3
|
export { matchAllRoutes, matchRoute } from './match.js';
|
|
4
|
-
export { getParams } from './params.js';
|
|
5
4
|
export { validateDynamicRouteModule, validateGetStaticPathsResult } from './validation.js';
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { createRouteManifest } from "./manifest/create.js";
|
|
2
2
|
import { deserializeRouteData, serializeRouteData } from "./manifest/serialization.js";
|
|
3
3
|
import { matchAllRoutes, matchRoute } from "./match.js";
|
|
4
|
-
import { getParams } from "./params.js";
|
|
5
4
|
import { validateDynamicRouteModule, validateGetStaticPathsResult } from "./validation.js";
|
|
6
5
|
export {
|
|
7
6
|
createRouteManifest,
|
|
8
7
|
deserializeRouteData,
|
|
9
|
-
getParams,
|
|
10
8
|
matchAllRoutes,
|
|
11
9
|
matchRoute,
|
|
12
10
|
serializeRouteData,
|
|
@@ -10,6 +10,7 @@ import { AstroError } from "../../errors/index.js";
|
|
|
10
10
|
import { removeLeadingForwardSlash, slash } from "../../path.js";
|
|
11
11
|
import { resolvePages } from "../../util.js";
|
|
12
12
|
import { getRouteGenerator } from "./generator.js";
|
|
13
|
+
import { toRoutingStrategy } from "../../../i18n/utils.js";
|
|
13
14
|
const require2 = createRequire(import.meta.url);
|
|
14
15
|
function countOccurrences(needle, haystack) {
|
|
15
16
|
let count = 0;
|
|
@@ -423,7 +424,8 @@ function createRouteManifest(params, logger) {
|
|
|
423
424
|
}
|
|
424
425
|
const i18n = settings.config.i18n;
|
|
425
426
|
if (i18n) {
|
|
426
|
-
|
|
427
|
+
const strategy = toRoutingStrategy(i18n);
|
|
428
|
+
if (strategy === "pathname-prefix-always") {
|
|
427
429
|
let index = routes.find((route) => route.route === "/");
|
|
428
430
|
if (!index) {
|
|
429
431
|
let relativePath = path.relative(
|
|
@@ -475,7 +477,7 @@ function createRouteManifest(params, logger) {
|
|
|
475
477
|
}
|
|
476
478
|
setRoutes.delete(route);
|
|
477
479
|
}
|
|
478
|
-
if (
|
|
480
|
+
if (strategy === "pathname-prefix-always") {
|
|
479
481
|
const defaultLocaleRoutes = routesByLocale.get(i18n.defaultLocale);
|
|
480
482
|
if (defaultLocaleRoutes) {
|
|
481
483
|
const indexDefaultRoute = defaultLocaleRoutes.find(({ route }) => route === "/") ?? defaultLocaleRoutes.find(({ route }) => route === `/${i18n.defaultLocale}`);
|
|
@@ -523,7 +525,7 @@ function createRouteManifest(params, logger) {
|
|
|
523
525
|
if (!hasRoute) {
|
|
524
526
|
let pathname;
|
|
525
527
|
let route;
|
|
526
|
-
if (fallbackToLocale === i18n.defaultLocale &&
|
|
528
|
+
if (fallbackToLocale === i18n.defaultLocale && strategy === "pathname-prefix-other-locales") {
|
|
527
529
|
if (fallbackToRoute.pathname) {
|
|
528
530
|
pathname = `/${fallbackFromLocale}${fallbackToRoute.pathname}`;
|
|
529
531
|
}
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import type { GetStaticPathsItem,
|
|
2
|
-
/**
|
|
3
|
-
* given an array of params like `['x', 'y', 'z']` for
|
|
4
|
-
* src/routes/[x]/[y]/[z]/svelte, create a function
|
|
5
|
-
* that turns a RegExpExecArray into ({ x, y, z })
|
|
6
|
-
*/
|
|
7
|
-
export declare function getParams(array: string[]): (match: RegExpExecArray) => Params;
|
|
1
|
+
import type { GetStaticPathsItem, RouteData } from '../../@types/astro.js';
|
|
8
2
|
/**
|
|
9
3
|
* given a route's Params object, validate parameter
|
|
10
4
|
* values and create a stringified key for the route
|