astro 6.0.0-alpha.2 → 6.0.0-alpha.3

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.
Files changed (54) hide show
  1. package/dist/cli/add/index.js +7 -10
  2. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  3. package/dist/config/entrypoint.d.ts +1 -0
  4. package/dist/config/entrypoint.js +2 -0
  5. package/dist/config/index.d.ts +3 -2
  6. package/dist/content/content-layer.js +3 -3
  7. package/dist/core/app/base.js +1 -1
  8. package/dist/core/app/dev/app.d.ts +6 -3
  9. package/dist/core/app/dev/app.js +6 -12
  10. package/dist/core/app/dev/pipeline.d.ts +6 -3
  11. package/dist/core/app/dev/pipeline.js +4 -4
  12. package/dist/core/app/types.d.ts +8 -4
  13. package/dist/core/base-pipeline.d.ts +5 -5
  14. package/dist/core/build/plugins/plugin-manifest.js +2 -1
  15. package/dist/core/config/schemas/base.d.ts +10 -20
  16. package/dist/core/config/schemas/base.js +2 -19
  17. package/dist/core/config/schemas/relative.d.ts +26 -25
  18. package/dist/core/constants.js +1 -1
  19. package/dist/core/dev/dev.js +1 -1
  20. package/dist/core/messages.d.ts +0 -8
  21. package/dist/core/messages.js +2 -13
  22. package/dist/core/preview/index.js +2 -13
  23. package/dist/core/render-context.d.ts +1 -1
  24. package/dist/core/render-context.js +7 -6
  25. package/dist/core/routing/helpers.d.ts +3 -0
  26. package/dist/core/routing/helpers.js +9 -0
  27. package/dist/core/session/config.d.ts +27 -0
  28. package/dist/core/session/config.js +33 -0
  29. package/dist/core/session/drivers.d.ts +34 -0
  30. package/dist/core/session/drivers.js +20 -0
  31. package/dist/core/{session.d.ts → session/runtime.d.ts} +13 -6
  32. package/dist/core/{session.js → session/runtime.js} +25 -19
  33. package/dist/core/session/types.d.ts +67 -0
  34. package/dist/core/session/types.js +0 -0
  35. package/dist/core/session/utils.d.ts +7 -0
  36. package/dist/core/session/utils.js +48 -0
  37. package/dist/core/session/vite-plugin.js +22 -27
  38. package/dist/manifest/serialized.js +2 -1
  39. package/dist/prerender/routing.d.ts +2 -2
  40. package/dist/runtime/server/render/page.js +2 -1
  41. package/dist/types/public/config.d.ts +22 -49
  42. package/dist/types/public/context.d.ts +1 -1
  43. package/dist/types/public/index.d.ts +2 -1
  44. package/dist/types/public/index.js +0 -4
  45. package/dist/types/public/preview.d.ts +1 -5
  46. package/dist/vite-plugin-app/app.d.ts +4 -20
  47. package/dist/vite-plugin-app/app.js +73 -231
  48. package/dist/vite-plugin-app/pipeline.d.ts +5 -2
  49. package/dist/vite-plugin-app/pipeline.js +4 -4
  50. package/dist/vite-plugin-astro-server/plugin.js +2 -1
  51. package/dist/vite-plugin-astro-server/response.d.ts +0 -1
  52. package/dist/vite-plugin-astro-server/response.js +1 -2
  53. package/dist/vite-plugin-environment/index.js +1 -0
  54. package/package.json +3 -3
@@ -2,23 +2,22 @@ import type { OutgoingHttpHeaders } from 'node:http';
2
2
  import type { RemotePattern } from '@astrojs/internal-helpers/remote';
3
3
  import type { RehypePlugins, RemarkPlugins, RemarkRehype, ShikiConfig, SyntaxHighlightConfigType } from '@astrojs/markdown-remark';
4
4
  import type { Config as SvgoConfig } from 'svgo';
5
- import type { BuiltinDriverName, BuiltinDriverOptions, Storage } from 'unstorage';
6
5
  import type { UserConfig as OriginalViteUserConfig, SSROptions as ViteSSROptions } from 'vite';
7
6
  import type { AstroFontProvider, FontFamily } from '../../assets/fonts/types.js';
8
7
  import type { ImageFit, ImageLayout } from '../../assets/types.js';
9
8
  import type { AssetsPrefix } from '../../core/app/types.js';
10
9
  import type { AstroConfigType } from '../../core/config/schemas/index.js';
11
10
  import type { REDIRECT_STATUS_CODES } from '../../core/constants.js';
12
- import type { AstroCookieSetOptions } from '../../core/cookies/cookies.js';
13
11
  import type { CspAlgorithm, CspDirective, CspHash } from '../../core/csp/config.js';
14
12
  import type { LoggerLevel } from '../../core/logger/core.js';
13
+ import type { SessionConfig, SessionDriverConfig, SessionDriverName } from '../../core/session/types.js';
15
14
  import type { EnvSchema } from '../../env/schema.js';
16
15
  import type { AstroIntegration } from './integrations.js';
16
+ export type { AstroFontProvider as FontProvider };
17
17
  export type Locales = (string | {
18
18
  codes: [string, ...string[]];
19
19
  path: string;
20
20
  })[];
21
- export type { AstroFontProvider as FontProvider };
22
21
  export type { CspAlgorithm, CspHash };
23
22
  export type { RemotePattern };
24
23
  export type CspStyleDirective = {
@@ -114,39 +113,6 @@ export type ServerConfig = {
114
113
  */
115
114
  open?: string | boolean;
116
115
  };
117
- export type SessionDriverName = BuiltinDriverName | 'custom' | 'test';
118
- interface CommonSessionConfig {
119
- /**
120
- * Configures the session cookie. If set to a string, it will be used as the cookie name.
121
- * Alternatively, you can pass an object with additional options.
122
- */
123
- cookie?: string | (Omit<AstroCookieSetOptions, 'httpOnly' | 'expires' | 'encode'> & {
124
- name?: string;
125
- });
126
- /**
127
- * Default session duration in seconds. If not set, the session will be stored until deleted, or until the cookie expires.
128
- */
129
- ttl?: number;
130
- }
131
- interface BuiltinSessionConfig<TDriver extends keyof BuiltinDriverOptions> extends CommonSessionConfig {
132
- driver: TDriver;
133
- options?: BuiltinDriverOptions[TDriver];
134
- }
135
- interface CustomSessionConfig extends CommonSessionConfig {
136
- /** Entrypoint for a custom session driver */
137
- driver?: string;
138
- options?: Record<string, unknown>;
139
- }
140
- interface TestSessionConfig extends CommonSessionConfig {
141
- driver: 'test';
142
- options: {
143
- mockStorage: Storage;
144
- };
145
- }
146
- export type SessionConfig<TDriver extends SessionDriverName> = [
147
- TDriver
148
- ] extends [never] ? CustomSessionConfig : TDriver extends keyof BuiltinDriverOptions ? BuiltinSessionConfig<TDriver> : TDriver extends 'test' ? TestSessionConfig : CustomSessionConfig;
149
- export type ResolvedSessionConfig<TDriver extends SessionDriverName> = SessionConfig<TDriver>;
150
116
  export interface ViteUserConfig extends OriginalViteUserConfig {
151
117
  ssr?: ViteSSROptions;
152
118
  }
@@ -156,7 +122,7 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
156
122
  *
157
123
  * Generics do not follow semver and may change at any time.
158
124
  */
159
- export interface AstroUserConfig<TLocales extends Locales = never, TSession extends SessionDriverName = never> {
125
+ export interface AstroUserConfig<TLocales extends Locales = never, TDriver extends SessionDriverName | SessionDriverConfig = never> {
160
126
  /**
161
127
  * @docs
162
128
  * @kind heading
@@ -833,7 +799,7 @@ export interface AstroUserConfig<TLocales extends Locales = never, TSession exte
833
799
  * @version 6.0.0
834
800
  * @description
835
801
  *
836
- * A configuration object that allows you to override the default sources for the `script-src` directive with the [`resources`](https://v6.docs.astro.build/en/reference/configuration-reference/#resources) property, or to provide additional [hashes]((https://v6.docs.astro.build/en/reference/configuration-reference#hashes) to be rendered.
802
+ * A configuration object that allows you to override the default sources for the `script-src` directive with the [`resources`](https://v6.docs.astro.build/en/reference/configuration-reference/#resources) property, or to provide additional [hashes](https://v6.docs.astro.build/en/reference/configuration-reference#hashes) to be rendered.
837
803
  */
838
804
  scriptDirective?: {
839
805
  /**
@@ -1311,33 +1277,36 @@ export interface AstroUserConfig<TLocales extends Locales = never, TSession exte
1311
1277
  * }
1312
1278
  * ```
1313
1279
  */
1314
- session?: SessionConfig<TSession>;
1280
+ session?: SessionConfig<TDriver>;
1315
1281
  /**
1316
1282
  * @docs
1317
1283
  * @name session.driver
1318
- * @type {string | undefined}
1284
+ * @type {SessionDriverConfig | undefined}
1319
1285
  * @version 5.7.0
1320
1286
  * @description
1321
1287
  *
1322
- * The Unstorage driver to use for session storage. The [Node](https://docs.astro.build/en/guides/integrations-guide/node/#sessions),
1288
+ * The driver to use for session storage. The [Node](https://docs.astro.build/en/guides/integrations-guide/node/#sessions),
1323
1289
  * [Cloudflare](https://docs.astro.build/en/guides/integrations-guide/cloudflare/#sessions), and
1324
1290
  * [Netlify](https://docs.astro.build/en/guides/integrations-guide/netlify/#sessions) adapters automatically configure a default driver for you,
1325
1291
  * but you can specify your own if you would prefer or if you are using an adapter that does not provide one.
1326
1292
  *
1327
- * The value is the "Driver name" from the [Unstorage driver documentation](https://unstorage.unjs.io/drivers).
1293
+ * ```js title="astro.config.mjs" ins={7-9} ins=" sessionDrivers "
1294
+ * import { defineConfig, sessionDrivers } from 'astro/config'
1295
+ * import vercel from '@astrojs/vercel'
1328
1296
  *
1329
- * ```js title="astro.config.mjs" ins={4}
1330
- * {
1331
- * adapter: vercel(),
1297
+ * export default defineConfig({
1298
+ * adapter: vercel()
1332
1299
  * session: {
1333
- * driver: "redis",
1334
- * },
1335
- * }
1300
+ * driver: sessionDrivers.redis({
1301
+ * url: process.env.REDIS_URL
1302
+ * }),
1303
+ * }
1304
+ * })
1336
1305
  * ```
1306
+ *
1337
1307
  * :::note
1338
1308
  * Some drivers may need extra packages to be installed. Some drivers may also require environment variables or credentials to be set. See the [Unstorage documentation](https://unstorage.unjs.io/drivers) for more information.
1339
1309
  * :::
1340
- *
1341
1310
  */
1342
1311
  /**
1343
1312
  * @docs
@@ -1347,6 +1316,10 @@ export interface AstroUserConfig<TLocales extends Locales = never, TSession exte
1347
1316
  * @default `{}`
1348
1317
  * @description
1349
1318
  *
1319
+ * :::caution[Deprecated]
1320
+ * This is deprecated and will be removed in a future major version. Instead, pass options to the driver function.
1321
+ * :::
1322
+ *
1350
1323
  * The driver-specific options to use for session storage. The options depend on the driver you are using. See the [Unstorage documentation](https://unstorage.unjs.io/drivers)
1351
1324
  * for more information on the options available for each driver.
1352
1325
  *
@@ -1,7 +1,7 @@
1
1
  import type { ActionClient, ActionReturnType } from '../../actions/runtime/types.js';
2
2
  import type { AstroCookies } from '../../core/cookies/cookies.js';
3
3
  import type { CspDirective, CspHash } from '../../core/csp/config.js';
4
- import type { AstroSession } from '../../core/session.js';
4
+ import type { AstroSession } from '../../core/session/runtime.js';
5
5
  import type { AstroComponentFactory } from '../../runtime/server/index.js';
6
6
  import type { Params, RewritePayload } from './common.js';
7
7
  import type { ValidRedirectStatus } from './config.js';
@@ -6,9 +6,10 @@ export type { ContainerRenderer } from '../../container/index.js';
6
6
  export type { AssetsPrefix, NodeAppHeadersJson, RouteInfo, SSRManifest, } from '../../core/app/types.js';
7
7
  export type { AstroCookieGetOptions, AstroCookieSetOptions, AstroCookies, } from '../../core/cookies/index.js';
8
8
  export type { AstroIntegrationLogger } from '../../core/logger/core.js';
9
- export { AstroSession } from '../../core/session.js';
9
+ export type { AstroSession } from '../../core/session/runtime.js';
10
10
  export type { ToolbarServerHelpers } from '../../runtime/client/dev-toolbar/helpers.js';
11
11
  export type { AstroEnvironmentNames } from '../../core/constants.js';
12
+ export type { SessionDriver, SessionDriverConfig } from '../../core/session/types.js';
12
13
  export type * from './common.js';
13
14
  export type * from './config.js';
14
15
  export type * from './content.js';
@@ -1,4 +0,0 @@
1
- import { AstroSession } from "../../core/session.js";
2
- export {
3
- AstroSession
4
- };
@@ -9,17 +9,13 @@ export interface PreviewServer {
9
9
  export interface PreviewServerParams {
10
10
  outDir: URL;
11
11
  client: URL;
12
+ server: URL;
12
13
  serverEntrypoint: URL;
13
14
  host: string | undefined;
14
15
  port: number;
15
16
  base: string;
16
17
  logger: AstroIntegrationLogger;
17
18
  headers?: OutgoingHttpHeaders;
18
- /**
19
- * DO NOT USE. This is for internal use only and might be removed soon.
20
- * @deprecated
21
- */
22
- createCodegenDir: () => URL;
23
19
  root: URL;
24
20
  }
25
21
  export type CreatePreviewServer = (params: PreviewServerParams) => PreviewServer | Promise<PreviewServer>;
@@ -6,20 +6,19 @@ import type { CreateRenderContext, RenderContext } from '../core/render-context.
6
6
  import type { AstroSettings, RoutesList } from '../types/astro.js';
7
7
  import type { RouteData, SSRManifest } from '../types/public/index.js';
8
8
  import type { DevServerController } from '../vite-plugin-astro-server/controller.js';
9
- import { AstroServerPipeline } from './pipeline.js';
10
- export declare class AstroServerApp extends BaseApp<AstroServerPipeline> {
9
+ import { RunnablePipeline } from './pipeline.js';
10
+ export declare class AstroServerApp extends BaseApp<RunnablePipeline> {
11
11
  settings: AstroSettings;
12
12
  logger: Logger;
13
13
  loader: ModuleLoader;
14
14
  manifestData: RoutesList;
15
15
  currentRenderContext: RenderContext | undefined;
16
+ resolvedPathname: string | undefined;
16
17
  constructor(manifest: SSRManifest, streaming: boolean | undefined, logger: Logger, manifestData: RoutesList, loader: ModuleLoader, settings: AstroSettings, getDebugInfo: () => Promise<string>);
17
18
  static create(manifest: SSRManifest, routesList: RoutesList, logger: Logger, loader: ModuleLoader, settings: AstroSettings, getDebugInfo: () => Promise<string>): Promise<AstroServerApp>;
18
- createPipeline(_streaming: boolean, manifest: SSRManifest, settings: AstroSettings, logger: Logger, loader: ModuleLoader, manifestData: RoutesList, getDebugInfo: () => Promise<string>): AstroServerPipeline;
19
+ createPipeline(_streaming: boolean, manifest: SSRManifest, settings: AstroSettings, logger: Logger, loader: ModuleLoader, manifestData: RoutesList, getDebugInfo: () => Promise<string>): RunnablePipeline;
19
20
  createRenderContext(payload: CreateRenderContext): Promise<RenderContext>;
20
- clearRouteCache(): void;
21
21
  handleRequest({ controller, incomingRequest, incomingResponse, isHttps, }: HandleRequest): Promise<void>;
22
- handleRoute({ matchedRoute, incomingRequest, incomingResponse, body, url, pathname, }: HandleRoute): Promise<void>;
23
22
  match(request: Request, _allowPrerenderedRoutes: boolean): RouteData | undefined;
24
23
  renderError(request: Request, { locals, skipMiddleware, error, clientAddress, status }: RenderErrorOptions): Promise<Response>;
25
24
  }
@@ -29,19 +28,4 @@ type HandleRequest = {
29
28
  incomingResponse: http.ServerResponse;
30
29
  isHttps: boolean;
31
30
  };
32
- type AsyncReturnType<T extends (...args: any) => Promise<any>> = T extends (...args: any) => Promise<infer R> ? R : any;
33
- type HandleRoute = {
34
- matchedRoute: AsyncReturnType<typeof matchRoute>;
35
- url: URL;
36
- pathname: string;
37
- body: BodyInit | undefined;
38
- incomingRequest: http.IncomingMessage;
39
- incomingResponse: http.ServerResponse;
40
- };
41
- interface MatchedRoute {
42
- route: RouteData;
43
- filePath: URL;
44
- resolvedPathname: string;
45
- }
46
- declare function matchRoute(pathname: string, routesList: RoutesList, pipeline: AstroServerPipeline, manifest: SSRManifest): Promise<MatchedRoute | undefined>;
47
31
  export {};
@@ -1,41 +1,29 @@
1
1
  import { prependForwardSlash, removeTrailingForwardSlash } from "@astrojs/internal-helpers/path";
2
2
  import { BaseApp } from "../core/app/index.js";
3
3
  import { shouldAppendForwardSlash } from "../core/build/util.js";
4
- import {
5
- clientLocalsSymbol,
6
- DEFAULT_404_COMPONENT,
7
- NOOP_MIDDLEWARE_HEADER,
8
- REROUTE_DIRECTIVE_HEADER,
9
- REWRITE_DIRECTIVE_HEADER_KEY
10
- } from "../core/constants.js";
4
+ import { clientLocalsSymbol } from "../core/constants.js";
11
5
  import {
12
6
  MiddlewareNoDataOrNextCalled,
13
7
  MiddlewareNotAResponse,
14
8
  NoMatchingStaticPathFound
15
9
  } from "../core/errors/errors-data.js";
16
10
  import { createSafeError, isAstroError } from "../core/errors/index.js";
17
- import { req } from "../core/messages.js";
18
11
  import { getProps } from "../core/render/index.js";
19
12
  import { createRequest } from "../core/request.js";
20
- import { redirectTemplate } from "../core/routing/3xx.js";
21
- import { matchAllRoutes, routeIsRedirect } from "../core/routing/index.js";
22
- import { isRoute404, isRoute500 } from "../core/routing/match.js";
23
- import { PERSIST_SYMBOL } from "../core/session.js";
13
+ import { matchAllRoutes } from "../core/routing/index.js";
24
14
  import { getSortedPreloadedMatches } from "../prerender/routing.js";
25
15
  import { recordServerError } from "../vite-plugin-astro-server/error.js";
26
16
  import { runWithErrorHandling } from "../vite-plugin-astro-server/index.js";
27
- import {
28
- handle500Response,
29
- writeSSRResult,
30
- writeWebResponse
31
- } from "../vite-plugin-astro-server/response.js";
32
- import { AstroServerPipeline } from "./pipeline.js";
17
+ import { handle500Response, writeSSRResult } from "../vite-plugin-astro-server/response.js";
18
+ import { RunnablePipeline } from "./pipeline.js";
19
+ import { getCustom404Route, getCustom500Route } from "../core/routing/helpers.js";
33
20
  class AstroServerApp extends BaseApp {
34
21
  settings;
35
22
  logger;
36
23
  loader;
37
24
  manifestData;
38
25
  currentRenderContext = void 0;
26
+ resolvedPathname = void 0;
39
27
  constructor(manifest, streaming = true, logger, manifestData, loader, settings, getDebugInfo) {
40
28
  super(manifest, streaming, settings, logger, loader, manifestData, getDebugInfo);
41
29
  this.settings = settings;
@@ -47,7 +35,7 @@ class AstroServerApp extends BaseApp {
47
35
  return new AstroServerApp(manifest, true, logger, routesList, loader, settings, getDebugInfo);
48
36
  }
49
37
  createPipeline(_streaming, manifest, settings, logger, loader, manifestData, getDebugInfo) {
50
- return AstroServerPipeline.create(manifestData, {
38
+ return RunnablePipeline.create(manifestData, {
51
39
  loader,
52
40
  logger,
53
41
  manifest,
@@ -56,12 +44,12 @@ class AstroServerApp extends BaseApp {
56
44
  });
57
45
  }
58
46
  async createRenderContext(payload) {
59
- this.currentRenderContext = await super.createRenderContext(payload);
47
+ this.currentRenderContext = await super.createRenderContext({
48
+ ...payload,
49
+ pathname: this.resolvedPathname ?? payload.pathname
50
+ });
60
51
  return this.currentRenderContext;
61
52
  }
62
- clearRouteCache() {
63
- this.pipeline.clearRouteCache();
64
- }
65
53
  async handleRequest({
66
54
  controller,
67
55
  incomingRequest,
@@ -102,15 +90,30 @@ class AstroServerApp extends BaseApp {
102
90
  self.pipeline,
103
91
  self.manifest
104
92
  );
105
- const resolvedPathname = matchedRoute?.resolvedPathname ?? pathname;
106
- return await self.handleRoute({
107
- matchedRoute,
93
+ if (!matchedRoute) {
94
+ throw new Error("No route matched, and default 404 route was not found.");
95
+ }
96
+ self.resolvedPathname = matchedRoute.resolvedPathname;
97
+ const request = createRequest({
108
98
  url,
109
- pathname: resolvedPathname,
99
+ headers: incomingRequest.headers,
100
+ method: incomingRequest.method,
110
101
  body,
111
- incomingRequest,
112
- incomingResponse
102
+ logger: self.logger,
103
+ isPrerendered: matchedRoute?.route.prerender,
104
+ routePattern: matchedRoute?.route.component
105
+ });
106
+ const locals = Reflect.get(incomingRequest, clientLocalsSymbol);
107
+ for (const [name, value] of Object.entries(self.settings.config.server.headers ?? {})) {
108
+ if (value) incomingResponse.setHeader(name, value);
109
+ }
110
+ const clientAddress = incomingRequest.socket.remoteAddress;
111
+ const response = await self.render(request, {
112
+ locals,
113
+ routeData: matchedRoute.route,
114
+ clientAddress
113
115
  });
116
+ await writeSSRResult(request, response, incomingResponse);
114
117
  },
115
118
  onError(_err) {
116
119
  const error = createSafeError(_err);
@@ -127,161 +130,6 @@ class AstroServerApp extends BaseApp {
127
130
  }
128
131
  });
129
132
  }
130
- async handleRoute({
131
- matchedRoute,
132
- incomingRequest,
133
- incomingResponse,
134
- body,
135
- url,
136
- pathname
137
- }) {
138
- const timeStart = performance.now();
139
- const { logger } = this.pipeline;
140
- if (!matchedRoute) {
141
- throw new Error("No route matched, and default 404 route was not found.");
142
- }
143
- let request;
144
- let renderContext;
145
- let route = matchedRoute.route;
146
- const componentInstance = await this.pipeline.getComponentByRoute(route);
147
- const locals = Reflect.get(incomingRequest, clientLocalsSymbol);
148
- request = createRequest({
149
- url,
150
- headers: incomingRequest.headers,
151
- method: incomingRequest.method,
152
- body,
153
- logger,
154
- isPrerendered: route.prerender,
155
- routePattern: route.component
156
- });
157
- for (const [name, value] of Object.entries(this.settings.config.server.headers ?? {})) {
158
- if (value) incomingResponse.setHeader(name, value);
159
- }
160
- renderContext = await this.createRenderContext({
161
- locals,
162
- pipeline: this.pipeline,
163
- pathname,
164
- skipMiddleware: isDefaultPrerendered404(matchedRoute.route),
165
- request,
166
- routeData: route,
167
- clientAddress: incomingRequest.socket.remoteAddress,
168
- shouldInjectCspMetaTags: false
169
- });
170
- let response;
171
- let statusCode = 200;
172
- let isReroute = false;
173
- let isRewrite = false;
174
- try {
175
- response = await renderContext.render(componentInstance);
176
- isReroute = response.headers.has(REROUTE_DIRECTIVE_HEADER);
177
- isRewrite = response.headers.has(REWRITE_DIRECTIVE_HEADER_KEY);
178
- const statusCodedMatched = getStatusByMatchedRoute(route);
179
- statusCode = isRewrite ? (
180
- // Ignore `matchedRoute` status for rewrites
181
- response.status
182
- ) : (
183
- // Our internal noop middleware sets a particular header. If the header isn't present, it means that the user have
184
- // their own middleware, so we need to return what the user returns.
185
- !response.headers.has(NOOP_MIDDLEWARE_HEADER) && !isReroute ? response.status : statusCodedMatched ?? response.status
186
- );
187
- } catch (err) {
188
- response = await this.renderError(request, {
189
- skipMiddleware: false,
190
- locals,
191
- status: 500,
192
- prerenderedErrorPageFetch: fetch,
193
- clientAddress: incomingRequest.socket.remoteAddress,
194
- error: err
195
- });
196
- statusCode = 500;
197
- } finally {
198
- this.currentRenderContext?.session?.[PERSIST_SYMBOL]();
199
- }
200
- if (isLoggedRequest(pathname)) {
201
- const timeEnd = performance.now();
202
- logger.info(
203
- null,
204
- req({
205
- url: pathname,
206
- method: incomingRequest.method,
207
- statusCode,
208
- isRewrite,
209
- reqTime: timeEnd - timeStart
210
- })
211
- );
212
- }
213
- if (statusCode === 404 && // If the body isn't null, that means the user sets the 404 status
214
- // but uses the current route to handle the 404
215
- response.body === null && response.headers.get(REROUTE_DIRECTIVE_HEADER) !== "no") {
216
- const fourOhFourRoute = await matchRoute(
217
- "/404",
218
- this.manifestData,
219
- this.pipeline,
220
- this.manifest
221
- );
222
- if (fourOhFourRoute) {
223
- renderContext = await this.createRenderContext({
224
- locals,
225
- pipeline: this.pipeline,
226
- pathname,
227
- skipMiddleware: isDefaultPrerendered404(fourOhFourRoute.route),
228
- request,
229
- routeData: fourOhFourRoute.route,
230
- clientAddress: incomingRequest.socket.remoteAddress,
231
- status: 404,
232
- shouldInjectCspMetaTags: false
233
- });
234
- const component = await this.pipeline.preload(
235
- fourOhFourRoute.route,
236
- fourOhFourRoute.filePath
237
- );
238
- response = await renderContext.render(component);
239
- }
240
- }
241
- if (isReroute) {
242
- response.headers.delete(REROUTE_DIRECTIVE_HEADER);
243
- }
244
- if (isRewrite) {
245
- response.headers.delete(REROUTE_DIRECTIVE_HEADER);
246
- }
247
- if (route.type === "endpoint") {
248
- await writeWebResponse(incomingResponse, response);
249
- return;
250
- }
251
- if (isRewrite) {
252
- await writeSSRResult(request, response, incomingResponse);
253
- return;
254
- }
255
- if (response.status < 400 && response.status >= 300) {
256
- if (response.status >= 300 && response.status < 400 && routeIsRedirect(route) && !this.settings.config.build.redirects && this.settings.buildOutput === "static") {
257
- const location = response.headers.get("location");
258
- response = new Response(
259
- redirectTemplate({
260
- status: response.status,
261
- absoluteLocation: location,
262
- relativeLocation: location,
263
- from: pathname
264
- }),
265
- {
266
- status: 200,
267
- headers: {
268
- ...response.headers,
269
- "content-type": "text/html"
270
- }
271
- }
272
- );
273
- }
274
- await writeSSRResult(request, response, incomingResponse);
275
- return;
276
- }
277
- if (response.status !== statusCode) {
278
- response = new Response(response.body, {
279
- status: statusCode,
280
- headers: response.headers
281
- });
282
- }
283
- await writeSSRResult(request, response, incomingResponse);
284
- }
285
133
  match(request, _allowPrerenderedRoutes) {
286
134
  const url = new URL(request.url);
287
135
  if (this.manifest.assets.has(url.pathname)) return void 0;
@@ -294,53 +142,53 @@ class AstroServerApp extends BaseApp {
294
142
  if (isAstroError(error) && [MiddlewareNoDataOrNextCalled.name, MiddlewareNotAResponse.name].includes(error.name)) {
295
143
  throw error;
296
144
  }
145
+ const renderRoute = async (routeData) => {
146
+ try {
147
+ const preloadedComponent = await this.pipeline.getComponentByRoute(routeData);
148
+ const renderContext = await this.createRenderContext({
149
+ locals,
150
+ pipeline: this.pipeline,
151
+ pathname: this.getPathnameFromRequest(request),
152
+ skipMiddleware,
153
+ request,
154
+ routeData,
155
+ clientAddress,
156
+ status,
157
+ shouldInjectCspMetaTags: false
158
+ });
159
+ renderContext.props.error = error;
160
+ const response = await renderContext.render(preloadedComponent);
161
+ if (error) {
162
+ this.logger.error("router", error.stack || error.message);
163
+ }
164
+ return response;
165
+ } catch (_err) {
166
+ if (skipMiddleware === false) {
167
+ return this.renderError(request, {
168
+ clientAddress: void 0,
169
+ prerenderedErrorPageFetch: fetch,
170
+ status: 500,
171
+ skipMiddleware: true,
172
+ error: _err
173
+ });
174
+ }
175
+ throw _err;
176
+ }
177
+ };
178
+ if (status === 404) {
179
+ const custom404 = getCustom404Route(this.manifestData);
180
+ if (custom404) {
181
+ return renderRoute(custom404);
182
+ }
183
+ }
297
184
  const custom500 = getCustom500Route(this.manifestData);
298
185
  if (!custom500) {
299
186
  throw error;
300
- }
301
- try {
302
- const filePath500 = new URL(`./${custom500.component}`, this.manifest.rootDir);
303
- const preloaded500Component = await this.pipeline.preload(custom500, filePath500);
304
- const renderContext = await this.createRenderContext({
305
- locals,
306
- pipeline: this.pipeline,
307
- pathname: this.getPathnameFromRequest(request),
308
- skipMiddleware,
309
- request,
310
- routeData: custom500,
311
- clientAddress,
312
- status,
313
- shouldInjectCspMetaTags: false
314
- });
315
- renderContext.props.error = error;
316
- const response = await renderContext.render(preloaded500Component);
317
- this.logger.error("router", error.stack || error.message);
318
- return response;
319
- } catch (_err) {
320
- if (skipMiddleware === false) {
321
- return this.renderError(request, {
322
- clientAddress: void 0,
323
- prerenderedErrorPageFetch: fetch,
324
- status: 500,
325
- skipMiddleware: true,
326
- error: _err
327
- });
328
- }
329
- throw _err;
187
+ } else {
188
+ return renderRoute(custom500);
330
189
  }
331
190
  }
332
191
  }
333
- function getStatusByMatchedRoute(route) {
334
- if (route.route === "/404") return 404;
335
- if (route.route === "/500") return 500;
336
- return void 0;
337
- }
338
- function isDefaultPrerendered404(route) {
339
- return route.route === "/404" && route.prerender && route.component === DEFAULT_404_COMPONENT;
340
- }
341
- function isLoggedRequest(url) {
342
- return url !== "/favicon.ico";
343
- }
344
192
  async function matchRoute(pathname, routesList, pipeline, manifest) {
345
193
  const { logger, routeCache } = pipeline;
346
194
  const matches = matchAllRoutes(pathname, routesList);
@@ -399,12 +247,6 @@ ${NoMatchingStaticPathFound.hint(possibleRoutes)}`
399
247
  }
400
248
  return void 0;
401
249
  }
402
- function getCustom404Route(manifestData) {
403
- return manifestData.routes.find((r) => isRoute404(r.route));
404
- }
405
- function getCustom500Route(manifestData) {
406
- return manifestData.routes.find((r) => isRoute500(r.route));
407
- }
408
250
  export {
409
251
  AstroServerApp
410
252
  };
@@ -3,7 +3,10 @@ import type { Logger } from '../core/logger/core.js';
3
3
  import type { ModuleLoader } from '../core/module-loader/index.js';
4
4
  import type { AstroSettings, ComponentInstance, RoutesList } from '../types/astro.js';
5
5
  import type { RewritePayload, RouteData, SSRLoadedRenderer, SSRManifest } from '../types/public/index.js';
6
- export declare class AstroServerPipeline extends Pipeline {
6
+ /**
7
+ * This Pipeline is used when the Vite SSR environment is runnable.
8
+ */
9
+ export declare class RunnablePipeline extends Pipeline {
7
10
  readonly loader: ModuleLoader;
8
11
  readonly logger: Logger;
9
12
  readonly manifest: SSRManifest;
@@ -20,7 +23,7 @@ export declare class AstroServerPipeline extends Pipeline {
20
23
  routesList: RoutesList | undefined;
21
24
  componentInterner: WeakMap<RouteData, ComponentInstance>;
22
25
  private constructor();
23
- static create(manifestData: RoutesList, { loader, logger, manifest, settings, getDebugInfo, }: Pick<AstroServerPipeline, 'loader' | 'logger' | 'manifest' | 'settings' | 'getDebugInfo'>): AstroServerPipeline;
26
+ static create(manifestData: RoutesList, { loader, logger, manifest, settings, getDebugInfo, }: Pick<RunnablePipeline, 'loader' | 'logger' | 'manifest' | 'settings' | 'getDebugInfo'>): RunnablePipeline;
24
27
  headElements(routeData: RouteData): Promise<HeadElements>;
25
28
  componentMetadata(routeData: RouteData): Promise<Map<string, import("../types/public/internal.js").SSRComponentMetadata>>;
26
29
  preload(routeData: RouteData, filePath: URL): Promise<ComponentInstance>;
@@ -14,7 +14,7 @@ import { getComponentMetadata } from "../vite-plugin-astro-server/metadata.js";
14
14
  import { createResolve } from "../vite-plugin-astro-server/resolve.js";
15
15
  import { PAGE_SCRIPT_ID } from "../vite-plugin-scripts/index.js";
16
16
  import { getDevCSSModuleName } from "../vite-plugin-css/util.js";
17
- class AstroServerPipeline extends Pipeline {
17
+ class RunnablePipeline extends Pipeline {
18
18
  constructor(loader, logger, manifest, settings, getDebugInfo, defaultRoutes = createDefaultRoutes(manifest)) {
19
19
  const resolve = createResolve(loader, manifest.rootDir);
20
20
  const streaming = true;
@@ -27,7 +27,7 @@ class AstroServerPipeline extends Pipeline {
27
27
  this.defaultRoutes = defaultRoutes;
28
28
  }
29
29
  getName() {
30
- return "AstroServerPipeline";
30
+ return "RunnablePipeline";
31
31
  }
32
32
  // renderers are loaded on every request,
33
33
  // so it needs to be mutable here unlike in other environments
@@ -41,7 +41,7 @@ class AstroServerPipeline extends Pipeline {
41
41
  settings,
42
42
  getDebugInfo
43
43
  }) {
44
- const pipeline = new AstroServerPipeline(loader, logger, manifest, settings, getDebugInfo);
44
+ const pipeline = new RunnablePipeline(loader, logger, manifest, settings, getDebugInfo);
45
45
  pipeline.routesList = manifestData;
46
46
  return pipeline;
47
47
  }
@@ -162,5 +162,5 @@ class AstroServerPipeline extends Pipeline {
162
162
  }
163
163
  }
164
164
  export {
165
- AstroServerPipeline
165
+ RunnablePipeline
166
166
  };