astro 5.1.10 → 5.2.1

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 (65) hide show
  1. package/client.d.ts +14 -0
  2. package/dist/assets/endpoint/config.d.ts +2 -2
  3. package/dist/cli/add/index.js +51 -25
  4. package/dist/config/index.js +4 -4
  5. package/dist/container/index.js +6 -0
  6. package/dist/content/content-layer.js +3 -3
  7. package/dist/core/app/index.d.ts +2 -2
  8. package/dist/core/app/index.js +33 -0
  9. package/dist/core/app/pipeline.d.ts +2 -2
  10. package/dist/core/app/types.d.ts +9 -3
  11. package/dist/core/build/generate.js +8 -2
  12. package/dist/core/build/index.js +13 -8
  13. package/dist/core/build/page-data.d.ts +2 -2
  14. package/dist/core/build/pipeline.d.ts +3 -3
  15. package/dist/core/build/pipeline.js +4 -4
  16. package/dist/core/build/plugins/plugin-manifest.js +9 -3
  17. package/dist/core/build/types.d.ts +2 -2
  18. package/dist/core/config/schema.d.ts +17 -0
  19. package/dist/core/config/schema.js +4 -2
  20. package/dist/core/constants.js +1 -1
  21. package/dist/core/create-vite.d.ts +6 -6
  22. package/dist/core/create-vite.js +6 -4
  23. package/dist/core/dev/container.js +6 -5
  24. package/dist/core/dev/dev.js +1 -1
  25. package/dist/core/errors/errors-data.d.ts +22 -0
  26. package/dist/core/errors/errors-data.js +12 -0
  27. package/dist/core/messages.js +2 -2
  28. package/dist/core/preview/index.js +2 -2
  29. package/dist/core/redirects/render.d.ts +2 -0
  30. package/dist/core/redirects/render.js +24 -5
  31. package/dist/core/routing/astro-designed-error-pages.d.ts +2 -2
  32. package/dist/core/routing/index.d.ts +1 -1
  33. package/dist/core/routing/index.js +2 -2
  34. package/dist/core/routing/manifest/create.d.ts +3 -3
  35. package/dist/core/routing/manifest/create.js +12 -10
  36. package/dist/core/routing/match.d.ts +3 -3
  37. package/dist/core/server-islands/endpoint.d.ts +2 -2
  38. package/dist/core/sync/index.d.ts +5 -3
  39. package/dist/core/sync/index.js +13 -8
  40. package/dist/i18n/utils.d.ts +2 -0
  41. package/dist/i18n/utils.js +24 -0
  42. package/dist/manifest/virtual-module.d.ts +9 -0
  43. package/dist/manifest/virtual-module.js +111 -0
  44. package/dist/template/4xx.d.ts +1 -0
  45. package/dist/template/4xx.js +14 -1
  46. package/dist/types/astro.d.ts +1 -1
  47. package/dist/types/public/config.d.ts +36 -18
  48. package/dist/types/public/index.d.ts +1 -0
  49. package/dist/types/public/manifest.d.ts +23 -0
  50. package/dist/types/public/manifest.js +0 -0
  51. package/dist/vite-plugin-astro-server/base.js +3 -13
  52. package/dist/vite-plugin-astro-server/pipeline.d.ts +4 -4
  53. package/dist/vite-plugin-astro-server/pipeline.js +5 -5
  54. package/dist/vite-plugin-astro-server/plugin.d.ts +4 -4
  55. package/dist/vite-plugin-astro-server/plugin.js +21 -10
  56. package/dist/vite-plugin-astro-server/request.d.ts +3 -3
  57. package/dist/vite-plugin-astro-server/request.js +3 -3
  58. package/dist/vite-plugin-astro-server/route.d.ts +4 -4
  59. package/dist/vite-plugin-astro-server/route.js +7 -7
  60. package/dist/vite-plugin-astro-server/trailing-slash.d.ts +3 -0
  61. package/dist/vite-plugin-astro-server/trailing-slash.js +30 -0
  62. package/dist/vite-plugin-scanner/index.d.ts +3 -3
  63. package/dist/vite-plugin-scanner/index.js +3 -3
  64. package/package.json +4 -4
  65. package/templates/content/types.d.ts +25 -24
@@ -13,6 +13,7 @@ import { syncAstroEnv } from "../../env/sync.js";
13
13
  import { telemetry } from "../../events/index.js";
14
14
  import { eventCliSession } from "../../events/session.js";
15
15
  import { runHookConfigDone, runHookConfigSetup } from "../../integrations/hooks.js";
16
+ import { createDevelopmentManifest } from "../../vite-plugin-astro-server/plugin.js";
16
17
  import { getTimeStat } from "../build/util.js";
17
18
  import { resolveConfig } from "../config/config.js";
18
19
  import { createNodeLogger } from "../config/logging.js";
@@ -25,7 +26,7 @@ import {
25
26
  createSafeError,
26
27
  isAstroError
27
28
  } from "../errors/index.js";
28
- import { createRouteManifest } from "../routing/index.js";
29
+ import { createRoutesList } from "../routing/index.js";
29
30
  import { ensureProcessNodeEnv } from "../util.js";
30
31
  import { normalizePath } from "../viteUtils.js";
31
32
  async function sync(inlineConfig, { fs, telemetry: _telemetry = false } = {}) {
@@ -41,7 +42,8 @@ async function sync(inlineConfig, { fs, telemetry: _telemetry = false } = {}) {
41
42
  settings,
42
43
  logger
43
44
  });
44
- const manifest = await createRouteManifest({ settings, fsMod: fs }, logger);
45
+ const routesList = await createRoutesList({ settings, fsMod: fs }, logger);
46
+ const manifest = createDevelopmentManifest(settings);
45
47
  await runHookConfigDone({ settings, logger });
46
48
  return await syncInternal({
47
49
  settings,
@@ -49,8 +51,9 @@ async function sync(inlineConfig, { fs, telemetry: _telemetry = false } = {}) {
49
51
  mode: "production",
50
52
  fs,
51
53
  force: inlineConfig.force,
52
- manifest,
53
- command: "sync"
54
+ routesList,
55
+ command: "sync",
56
+ manifest
54
57
  });
55
58
  }
56
59
  async function clearContentLayerCache({
@@ -73,9 +76,10 @@ async function syncInternal({
73
76
  settings,
74
77
  skip,
75
78
  force,
76
- manifest,
79
+ routesList,
77
80
  command,
78
- watcher
81
+ watcher,
82
+ manifest
79
83
  }) {
80
84
  const isDev = command === "dev";
81
85
  if (force) {
@@ -83,7 +87,7 @@ async function syncInternal({
83
87
  }
84
88
  const timerStart = performance.now();
85
89
  if (!skip?.content) {
86
- await syncContentCollections(settings, { mode, fs, logger, manifest });
90
+ await syncContentCollections(settings, { mode, fs, logger, routesList, manifest });
87
91
  settings.timer.start("Sync content layer");
88
92
  let store;
89
93
  try {
@@ -152,6 +156,7 @@ async function syncContentCollections(settings, {
152
156
  mode,
153
157
  logger,
154
158
  fs,
159
+ routesList,
155
160
  manifest
156
161
  }) {
157
162
  const tempViteServer = await createServer(
@@ -162,7 +167,7 @@ async function syncContentCollections(settings, {
162
167
  ssr: { external: [] },
163
168
  logLevel: "silent"
164
169
  },
165
- { settings, logger, mode, command: "build", fs, sync: true, manifest }
170
+ { settings, logger, mode, command: "build", fs, sync: true, routesList, manifest }
166
171
  )
167
172
  );
168
173
  const hotSend = tempViteServer.hot.send;
@@ -1,3 +1,4 @@
1
+ import type { SSRManifest } from '../core/app/types.js';
1
2
  import type { AstroConfig, Locales } from '../types/public/config.js';
2
3
  type BrowserLocale = {
3
4
  locale: string;
@@ -23,5 +24,6 @@ export declare function computePreferredLocaleList(request: Request, locales: Lo
23
24
  export declare function computeCurrentLocale(pathname: string, locales: Locales, defaultLocale: string): string | undefined;
24
25
  export type RoutingStrategies = 'manual' | 'pathname-prefix-always' | 'pathname-prefix-other-locales' | 'pathname-prefix-always-no-redirect' | 'domains-prefix-always' | 'domains-prefix-other-locales' | 'domains-prefix-always-no-redirect';
25
26
  export declare function toRoutingStrategy(routing: NonNullable<AstroConfig['i18n']>['routing'], domains: NonNullable<AstroConfig['i18n']>['domains']): RoutingStrategies;
27
+ export declare function fromRoutingStrategy(strategy: RoutingStrategies, fallbackType: NonNullable<SSRManifest['i18n']>['fallbackType']): NonNullable<AstroConfig['i18n']>['routing'];
26
28
  export declare function toFallbackType(routing: NonNullable<AstroConfig['i18n']>['routing']): 'redirect' | 'rewrite';
27
29
  export {};
@@ -168,6 +168,29 @@ function toRoutingStrategy(routing, domains) {
168
168
  }
169
169
  return strategy;
170
170
  }
171
+ const PREFIX_DEFAULT_LOCALE = /* @__PURE__ */ new Set([
172
+ "pathname-prefix-always",
173
+ "domains-prefix-always",
174
+ "pathname-prefix-always-no-redirect",
175
+ "domains-prefix-always-no-redirect"
176
+ ]);
177
+ const REDIRECT_TO_DEFAULT_LOCALE = /* @__PURE__ */ new Set([
178
+ "pathname-prefix-always-no-redirect",
179
+ "domains-prefix-always-no-redirect"
180
+ ]);
181
+ function fromRoutingStrategy(strategy, fallbackType) {
182
+ let routing;
183
+ if (strategy === "manual") {
184
+ routing = "manual";
185
+ } else {
186
+ routing = {
187
+ prefixDefaultLocale: PREFIX_DEFAULT_LOCALE.has(strategy),
188
+ redirectToDefaultLocale: !REDIRECT_TO_DEFAULT_LOCALE.has(strategy),
189
+ fallbackType
190
+ };
191
+ }
192
+ return routing;
193
+ }
171
194
  function toFallbackType(routing) {
172
195
  if (routing === "manual") {
173
196
  return "rewrite";
@@ -178,6 +201,7 @@ export {
178
201
  computeCurrentLocale,
179
202
  computePreferredLocale,
180
203
  computePreferredLocaleList,
204
+ fromRoutingStrategy,
181
205
  parseLocale,
182
206
  toFallbackType,
183
207
  toRoutingStrategy
@@ -0,0 +1,9 @@
1
+ import type { Plugin } from 'vite';
2
+ import type { Logger } from '../core/logger/core.js';
3
+ import type { AstroSettings } from '../types/astro.js';
4
+ import type { SSRManifest } from '../types/public/index.js';
5
+ export default function virtualModulePlugin({ settings, manifest, logger: _logger, }: {
6
+ settings: AstroSettings;
7
+ manifest: SSRManifest;
8
+ logger: Logger;
9
+ }): Plugin;
@@ -0,0 +1,111 @@
1
+ import { CantUseAstroConfigModuleError } from "../core/errors/errors-data.js";
2
+ import { AstroError, AstroErrorData } from "../core/errors/index.js";
3
+ import { fromRoutingStrategy } from "../i18n/utils.js";
4
+ const VIRTUAL_SERVER_ID = "astro:config/server";
5
+ const RESOLVED_VIRTUAL_SERVER_ID = "\0" + VIRTUAL_SERVER_ID;
6
+ const VIRTUAL_CLIENT_ID = "astro:config/client";
7
+ const RESOLVED_VIRTUAL_CLIENT_ID = "\0" + VIRTUAL_CLIENT_ID;
8
+ function virtualModulePlugin({
9
+ settings,
10
+ manifest,
11
+ logger: _logger
12
+ }) {
13
+ return {
14
+ enforce: "pre",
15
+ name: "astro-manifest-plugin",
16
+ resolveId(id) {
17
+ if (VIRTUAL_SERVER_ID === id) {
18
+ return RESOLVED_VIRTUAL_SERVER_ID;
19
+ } else if (VIRTUAL_CLIENT_ID === id) {
20
+ return RESOLVED_VIRTUAL_CLIENT_ID;
21
+ }
22
+ },
23
+ load(id, opts) {
24
+ if (id === RESOLVED_VIRTUAL_CLIENT_ID) {
25
+ if (!settings.config.experimental.serializeConfig) {
26
+ throw new AstroError({
27
+ ...CantUseAstroConfigModuleError,
28
+ message: CantUseAstroConfigModuleError.message(VIRTUAL_CLIENT_ID)
29
+ });
30
+ }
31
+ return `${serializeClientConfig(manifest)};`;
32
+ } else if (id == RESOLVED_VIRTUAL_SERVER_ID) {
33
+ if (!settings.config.experimental.serializeConfig) {
34
+ throw new AstroError({
35
+ ...CantUseAstroConfigModuleError,
36
+ message: CantUseAstroConfigModuleError.message(VIRTUAL_SERVER_ID)
37
+ });
38
+ }
39
+ if (!opts?.ssr) {
40
+ throw new AstroError({
41
+ ...AstroErrorData.ServerOnlyModule,
42
+ message: AstroErrorData.ServerOnlyModule.message(VIRTUAL_SERVER_ID)
43
+ });
44
+ }
45
+ return `${serializeServerConfig(manifest)};`;
46
+ }
47
+ }
48
+ };
49
+ }
50
+ function serializeClientConfig(manifest) {
51
+ let i18n = void 0;
52
+ if (manifest.i18n) {
53
+ i18n = {
54
+ defaultLocale: manifest.i18n.defaultLocale,
55
+ locales: manifest.i18n.locales,
56
+ routing: fromRoutingStrategy(manifest.i18n.strategy, manifest.i18n.fallbackType),
57
+ fallback: manifest.i18n.fallback
58
+ };
59
+ }
60
+ const serClientConfig = {
61
+ base: manifest.base,
62
+ i18n,
63
+ build: {
64
+ format: manifest.buildFormat
65
+ },
66
+ trailingSlash: manifest.trailingSlash,
67
+ compressHTML: manifest.compressHTML,
68
+ site: manifest.site
69
+ };
70
+ const output = [];
71
+ for (const [key, value] of Object.entries(serClientConfig)) {
72
+ output.push(`export const ${key} = ${JSON.stringify(value)};`);
73
+ }
74
+ return output.join("\n") + "\n";
75
+ }
76
+ function serializeServerConfig(manifest) {
77
+ let i18n = void 0;
78
+ if (manifest.i18n) {
79
+ i18n = {
80
+ defaultLocale: manifest.i18n.defaultLocale,
81
+ routing: fromRoutingStrategy(manifest.i18n.strategy, manifest.i18n.fallbackType),
82
+ locales: manifest.i18n.locales,
83
+ fallback: manifest.i18n.fallback
84
+ };
85
+ }
86
+ const serverConfig = {
87
+ build: {
88
+ server: new URL(manifest.buildServerDir),
89
+ client: new URL(manifest.buildClientDir),
90
+ format: manifest.buildFormat
91
+ },
92
+ cacheDir: new URL(manifest.cacheDir),
93
+ outDir: new URL(manifest.outDir),
94
+ publicDir: new URL(manifest.publicDir),
95
+ srcDir: new URL(manifest.srcDir),
96
+ root: new URL(manifest.hrefRoot),
97
+ base: manifest.base,
98
+ i18n,
99
+ trailingSlash: manifest.trailingSlash,
100
+ site: manifest.site,
101
+ compressHTML: manifest.compressHTML
102
+ };
103
+ const output = [];
104
+ for (const [key, value] of Object.entries(serverConfig)) {
105
+ output.push(`export const ${key} = ${JSON.stringify(value)};`);
106
+ }
107
+ return output.join("\n") + "\n";
108
+ }
109
+ export {
110
+ virtualModulePlugin as default
111
+ };
@@ -13,5 +13,6 @@ interface ErrorTemplateOptions {
13
13
  /** Display all errors */
14
14
  export default function template({ title, pathname, statusCode, tabTitle, body, }: ErrorTemplateOptions): string;
15
15
  export declare function subpathNotUsedTemplate(base: string, pathname: string): string;
16
+ export declare function trailingSlashMismatchTemplate(pathname: string, trailingSlash: 'always' | 'never' | 'ignore'): string;
16
17
  export declare function notFoundTemplate(pathname: string, message?: string): string;
17
18
  export {};
@@ -1,3 +1,4 @@
1
+ import { appendForwardSlash, removeTrailingForwardSlash } from "@astrojs/internal-helpers/path";
1
2
  import { escape } from "html-escaper";
2
3
  function template({
3
4
  title,
@@ -107,6 +108,17 @@ function subpathNotUsedTemplate(base, pathname) {
107
108
  <p>Come to our <a href="https://astro.build/chat">Discord</a> if you need help.</p>`
108
109
  });
109
110
  }
111
+ function trailingSlashMismatchTemplate(pathname, trailingSlash) {
112
+ const corrected = trailingSlash === "always" ? appendForwardSlash(pathname) : removeTrailingForwardSlash(pathname);
113
+ return template({
114
+ pathname,
115
+ statusCode: 404,
116
+ title: "Not found",
117
+ tabTitle: "404: Not Found",
118
+ body: `<p>Your site is configured with <code>trailingSlash</code> set to <code>${trailingSlash}</code>. Do you want to go to <a href="${corrected}">${corrected}</a> instead?</p>
119
+ <p>See <a href=https://docs.astro.build/en/reference/configuration-reference/#trailingslash">the documentation for <code>trailingSlash</code></a> if you need help.</p>`
120
+ });
121
+ }
110
122
  function notFoundTemplate(pathname, message = "Not found") {
111
123
  return template({
112
124
  pathname,
@@ -118,5 +130,6 @@ function notFoundTemplate(pathname, message = "Not found") {
118
130
  export {
119
131
  template as default,
120
132
  notFoundTemplate,
121
- subpathNotUsedTemplate
133
+ subpathNotUsedTemplate,
134
+ trailingSlashMismatchTemplate
122
135
  };
@@ -72,7 +72,7 @@ export interface ComponentInstance {
72
72
  prerender?: boolean;
73
73
  getStaticPaths?: (options: GetStaticPathsOptions) => GetStaticPathsResult;
74
74
  }
75
- export interface ManifestData {
75
+ export interface RoutesList {
76
76
  routes: RouteData[];
77
77
  }
78
78
  export interface AstroPluginOptions {
@@ -13,7 +13,7 @@ import type { LoggerLevel } from '../../core/logger/core.js';
13
13
  import type { EnvSchema } from '../../env/schema.js';
14
14
  import type { AstroIntegration } from './integrations.js';
15
15
  export type Locales = (string | {
16
- codes: string[];
16
+ codes: [string, ...string[]];
17
17
  path: string;
18
18
  })[];
19
19
  type NormalizeLocales<T extends Locales> = {
@@ -193,14 +193,15 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
193
193
  * @see build.format
194
194
  * @description
195
195
  *
196
- * Set the route matching behavior of the dev server. Choose from the following options:
197
- * - `'always'` - Only match URLs that include a trailing slash (ex: "/foo/")
198
- * - `'never'` - Never match URLs that include a trailing slash (ex: "/foo")
199
- * - `'ignore'` - Match URLs regardless of whether a trailing "/" exists
196
+ * Set the route matching behavior for trailing slashes in the dev server and on-demand rendered pages. Choose from the following options:
197
+ * - `'ignore'` - Match URLs regardless of whether a trailing "/" exists. Requests for "/about" and "/about/" will both match the same route.
198
+ * - `'always'` - Only match URLs that include a trailing slash (e.g: "/about/"). In production, requests for on-demand rendered URLs without a trailing slash will be redirected to the correct URL for your convenience. However, in development, they will display a warning page reminding you that you have `always` configured.
199
+ * - `'never'` - Only match URLs that do not include a trailing slash (e.g: "/about"). In production, requests for on-demand rendered URLs with a trailing slash will be redirected to the correct URL for your convenience. However, in development, they will display a warning page reminding you that you have `never` configured.
200
200
  *
201
- * Use this configuration option if your production host has strict handling of how trailing slashes work or do not work.
201
+ * When redirects occur in production for GET requests, the redirect will be a 301 (permanent) redirect. For all other request methods, it will be a 308 (permanent, and preserve the request method) redirect.
202
202
  *
203
- * You can also set this if you prefer to be more strict yourself, so that URLs with or without trailing slashes won't work during development.
203
+ * Trailing slashes on prerendered pages are handled by the hosting platform, and may not respect your chosen configuration.
204
+ * See your hosting platform's documentation for more information.
204
205
  *
205
206
  * ```js
206
207
  * {
@@ -220,16 +221,21 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
220
221
  * and the value is the path to redirect to.
221
222
  *
222
223
  * You can redirect both static and dynamic routes, but only to the same kind of route.
223
- * For example you cannot have a `'/article': '/blog/[...slug]'` redirect.
224
+ * For example, you cannot have a `'/article': '/blog/[...slug]'` redirect.
224
225
  *
225
226
  *
226
227
  * ```js
227
- * {
228
+ * export default defineConfig({
228
229
  * redirects: {
229
- * '/old': '/new',
230
- * '/blog/[...slug]': '/articles/[...slug]',
231
- * }
232
- * }
230
+ * '/old': '/new',
231
+ * '/blog/[...slug]': '/articles/[...slug]',
232
+ * '/about': 'https://example.com/about',
233
+ * '/news': {
234
+ * status: 302,
235
+ * destination: 'https://example.com/news'
236
+ * }
237
+ * }
238
+ * })
233
239
  * ```
234
240
  *
235
241
  *
@@ -243,14 +249,14 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
243
249
  * You can customize the [redirection status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages) using an object in the redirect config:
244
250
  *
245
251
  * ```js
246
- * {
252
+ * export default defineConfig({
247
253
  * redirects: {
248
254
  * '/other': {
249
255
  * status: 302,
250
256
  * destination: '/place',
251
257
  * },
252
258
  * }
253
- * }
259
+ * })
254
260
  * ```
255
261
  */
256
262
  redirects?: Record<string, RedirectConfig>;
@@ -308,10 +314,10 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
308
314
  *
309
315
  * ```js
310
316
  * import react from '@astrojs/react';
311
- * import tailwind from '@astrojs/tailwind';
317
+ * import mdx from '@astrojs/mdx';
312
318
  * {
313
- * // Example: Add React + Tailwind support to Astro
314
- * integrations: [react(), tailwind()]
319
+ * // Example: Add React + MDX support to Astro
320
+ * integrations: [react(), mdx()]
315
321
  * }
316
322
  * ```
317
323
  */
@@ -1954,6 +1960,18 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
1954
1960
  */
1955
1961
  mode: SvgRenderMode;
1956
1962
  };
1963
+ /**
1964
+ * @name experimental.serializeConfig
1965
+ * @type {boolean}
1966
+ * @default `false`
1967
+ * @version 5.x
1968
+ * @description
1969
+ *
1970
+ * Enables the use of the experimental virtual modules `astro:config/server` and `astro:config/client`.
1971
+ *
1972
+ * These two virtual modules contain a serializable subset of the Astro configuration.
1973
+ */
1974
+ serializeConfig?: boolean;
1957
1975
  };
1958
1976
  }
1959
1977
  /**
@@ -9,6 +9,7 @@ export type * from './context.js';
9
9
  export type * from './preview.js';
10
10
  export type * from './content.js';
11
11
  export type * from './common.js';
12
+ export type * from './manifest.js';
12
13
  export type { AstroIntegrationLogger } from '../../core/logger/core.js';
13
14
  export type { ToolbarServerHelpers } from '../../runtime/client/dev-toolbar/helpers.js';
14
15
  export type { MarkdownHeading, RehypePlugins, RemarkPlugins, ShikiConfig, } from '@astrojs/markdown-remark';
@@ -0,0 +1,23 @@
1
+ /**
2
+ * **IMPORTANT**: use the `Pick` interface to select only the properties that we want to expose
3
+ * to the users. Using blanket types could expose properties that we don't want. So if we decide to expose
4
+ * properties, we need to be good at justifying them. For example: why you need this config? can't you use an integration?
5
+ * why do you need access to the shiki config? (very low-level confiig)
6
+ */
7
+ import type { SSRManifest } from '../../core/app/types.js';
8
+ import type { AstroConfig } from './config.js';
9
+ type Extend<T, U> = {
10
+ [K in keyof T]: T[K] | U;
11
+ };
12
+ type Dirs = Pick<SSRManifest, 'cacheDir' | 'outDir' | 'publicDir' | 'srcDir'>;
13
+ type DeserializedDirs = Extend<Dirs, URL>;
14
+ export type ServerDeserializedManifest = Pick<SSRManifest, 'base' | 'trailingSlash' | 'compressHTML' | 'site'> & DeserializedDirs & {
15
+ i18n: AstroConfig['i18n'];
16
+ build: Pick<AstroConfig['build'], 'server' | 'client' | 'format'>;
17
+ root: URL;
18
+ };
19
+ export type ClientDeserializedManifest = Pick<SSRManifest, 'base' | 'trailingSlash' | 'compressHTML' | 'site'> & {
20
+ i18n: AstroConfig['i18n'];
21
+ build: Pick<AstroConfig['build'], 'format'>;
22
+ };
23
+ export {};
File without changes
@@ -2,9 +2,8 @@ import * as fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { appendForwardSlash } from "@astrojs/internal-helpers/path";
4
4
  import { bold } from "kleur/colors";
5
- import notFoundTemplate, { subpathNotUsedTemplate } from "../template/4xx.js";
6
- import { writeHtmlResponse, writeRedirectResponse } from "./response.js";
7
- const manySlashes = /\/{2,}$/;
5
+ import { notFoundTemplate, subpathNotUsedTemplate } from "../template/4xx.js";
6
+ import { writeHtmlResponse } from "./response.js";
8
7
  function baseMiddleware(settings, logger) {
9
8
  const { config } = settings;
10
9
  const site = config.site ? new URL(config.base, config.site) : void 0;
@@ -13,10 +12,6 @@ function baseMiddleware(settings, logger) {
13
12
  const devRootReplacement = devRoot.endsWith("/") ? "/" : "";
14
13
  return function devBaseMiddleware(req, res, next) {
15
14
  const url = req.url;
16
- if (manySlashes.test(url)) {
17
- const destination = url.replace(manySlashes, "/");
18
- return writeRedirectResponse(res, 301, destination);
19
- }
20
15
  let pathname;
21
16
  try {
22
17
  pathname = decodeURI(new URL(url, "http://localhost").pathname);
@@ -32,12 +27,7 @@ function baseMiddleware(settings, logger) {
32
27
  return writeHtmlResponse(res, 404, html);
33
28
  }
34
29
  if (req.headers.accept?.includes("text/html")) {
35
- const html = notFoundTemplate({
36
- statusCode: 404,
37
- title: "Not found",
38
- tabTitle: "404: Not Found",
39
- pathname
40
- });
30
+ const html = notFoundTemplate(pathname);
41
31
  return writeHtmlResponse(res, 404, html);
42
32
  }
43
33
  const publicPath = new URL("." + req.url, config.publicDir);
@@ -2,7 +2,7 @@ import type { HeadElements, TryRewriteResult } from '../core/base-pipeline.js';
2
2
  import type { Logger } from '../core/logger/core.js';
3
3
  import type { ModuleLoader } from '../core/module-loader/index.js';
4
4
  import { Pipeline } from '../core/render/index.js';
5
- import type { AstroSettings, ComponentInstance, ManifestData } from '../types/astro.js';
5
+ import type { AstroSettings, ComponentInstance, RoutesList } from '../types/astro.js';
6
6
  import type { RewritePayload } from '../types/public/common.js';
7
7
  import type { RouteData, SSRLoadedRenderer, SSRManifest } from '../types/public/internal.js';
8
8
  export declare class DevPipeline extends Pipeline {
@@ -18,16 +18,16 @@ export declare class DevPipeline extends Pipeline {
18
18
  component: string;
19
19
  }[];
20
20
  renderers: SSRLoadedRenderer[];
21
- manifestData: ManifestData | undefined;
21
+ routesList: RoutesList | undefined;
22
22
  componentInterner: WeakMap<RouteData, ComponentInstance>;
23
23
  private constructor();
24
- static create(manifestData: ManifestData, { loader, logger, manifest, settings, }: Pick<DevPipeline, 'loader' | 'logger' | 'manifest' | 'settings'>): DevPipeline;
24
+ static create(manifestData: RoutesList, { loader, logger, manifest, settings, }: Pick<DevPipeline, 'loader' | 'logger' | 'manifest' | 'settings'>): DevPipeline;
25
25
  headElements(routeData: RouteData): Promise<HeadElements>;
26
26
  componentMetadata(routeData: RouteData): Promise<Map<string, import("../types/public/internal.js").SSRComponentMetadata>>;
27
27
  preload(routeData: RouteData, filePath: URL): Promise<ComponentInstance>;
28
28
  clearRouteCache(): void;
29
29
  getComponentByRoute(routeData: RouteData): Promise<ComponentInstance>;
30
30
  tryRewrite(payload: RewritePayload, request: Request): Promise<TryRewriteResult>;
31
- setManifestData(manifestData: ManifestData): void;
31
+ setManifestData(manifestData: RoutesList): void;
32
32
  rewriteKnownRoute(route: string, sourceRoute: RouteData): ComponentInstance;
33
33
  }
@@ -30,7 +30,7 @@ class DevPipeline extends Pipeline {
30
30
  // renderers are loaded on every request,
31
31
  // so it needs to be mutable here unlike in other environments
32
32
  renderers = new Array();
33
- manifestData;
33
+ routesList;
34
34
  componentInterner = /* @__PURE__ */ new WeakMap();
35
35
  static create(manifestData, {
36
36
  loader,
@@ -39,7 +39,7 @@ class DevPipeline extends Pipeline {
39
39
  settings
40
40
  }) {
41
41
  const pipeline = new DevPipeline(loader, logger, manifest, settings);
42
- pipeline.manifestData = manifestData;
42
+ pipeline.routesList = manifestData;
43
43
  return pipeline;
44
44
  }
45
45
  async headElements(routeData) {
@@ -137,13 +137,13 @@ class DevPipeline extends Pipeline {
137
137
  }
138
138
  }
139
139
  async tryRewrite(payload, request) {
140
- if (!this.manifestData) {
140
+ if (!this.routesList) {
141
141
  throw new Error("Missing manifest data. This is an internal error, please file an issue.");
142
142
  }
143
143
  const { routeData, pathname, newUrl } = findRouteToRewrite({
144
144
  payload,
145
145
  request,
146
- routes: this.manifestData?.routes,
146
+ routes: this.routesList?.routes,
147
147
  trailingSlash: this.config.trailingSlash,
148
148
  buildFormat: this.config.build.format,
149
149
  base: this.config.base
@@ -152,7 +152,7 @@ class DevPipeline extends Pipeline {
152
152
  return { newUrl, pathname, componentInstance, routeData };
153
153
  }
154
154
  setManifestData(manifestData) {
155
- this.manifestData = manifestData;
155
+ this.routesList = manifestData;
156
156
  }
157
157
  rewriteKnownRoute(route, sourceRoute) {
158
158
  if (this.serverLike && sourceRoute.prerender) {
@@ -2,15 +2,15 @@ import type fs from 'node:fs';
2
2
  import type * as vite from 'vite';
3
3
  import type { SSRManifest } from '../core/app/types.js';
4
4
  import type { Logger } from '../core/logger/core.js';
5
- import type { AstroSettings, ManifestData } from '../types/astro.js';
5
+ import type { AstroSettings, RoutesList } from '../types/astro.js';
6
6
  export interface AstroPluginOptions {
7
7
  settings: AstroSettings;
8
8
  logger: Logger;
9
9
  fs: typeof fs;
10
- manifest: ManifestData;
11
- ssrManifest: SSRManifest;
10
+ routesList: RoutesList;
11
+ manifest: SSRManifest;
12
12
  }
13
- export default function createVitePluginAstroServer({ settings, logger, fs: fsMod, manifest: routeManifest, ssrManifest: devSSRManifest, }: AstroPluginOptions): vite.Plugin;
13
+ export default function createVitePluginAstroServer({ settings, logger, fs: fsMod, routesList, manifest, }: AstroPluginOptions): vite.Plugin;
14
14
  /**
15
15
  * It creates a `SSRManifest` from the `AstroSettings`.
16
16
  *