astro 6.1.3 → 6.1.4

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 (39) hide show
  1. package/dist/assets/utils/index.d.ts +1 -1
  2. package/dist/assets/utils/index.js +1 -9
  3. package/dist/assets/utils/vendor/image-size/utils/bit-reader.d.ts +2 -2
  4. package/dist/assets/utils/vendor/image-size/utils/bit-reader.js +5 -3
  5. package/dist/cli/add/index.js +37 -44
  6. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  7. package/dist/content/content-layer.js +3 -3
  8. package/dist/content/loaders/errors.d.ts +2 -2
  9. package/dist/content/loaders/errors.js +3 -0
  10. package/dist/core/app/base.js +1 -1
  11. package/dist/core/base-pipeline.d.ts +22 -35
  12. package/dist/core/base-pipeline.js +41 -8
  13. package/dist/core/build/generate.js +9 -1
  14. package/dist/core/build/pipeline.d.ts +3 -7
  15. package/dist/core/build/pipeline.js +30 -28
  16. package/dist/core/config/schemas/refined-validators.d.ts +44 -0
  17. package/dist/core/config/schemas/refined-validators.js +168 -0
  18. package/dist/core/config/schemas/refined.js +28 -141
  19. package/dist/core/constants.js +1 -1
  20. package/dist/core/cookies/cookies.js +1 -0
  21. package/dist/core/dev/dev.js +1 -1
  22. package/dist/core/dev/restart.js +63 -68
  23. package/dist/core/messages/runtime.js +1 -1
  24. package/dist/core/render-context.d.ts +2 -2
  25. package/dist/core/render-context.js +20 -0
  26. package/dist/core/routing/create-manifest.js +12 -4
  27. package/dist/core/routing/default.d.ts +2 -3
  28. package/dist/integrations/features-validation.d.ts +3 -1
  29. package/dist/integrations/features-validation.js +2 -0
  30. package/dist/preferences/store.js +2 -1
  31. package/dist/runtime/server/transition.d.ts +2 -2
  32. package/dist/runtime/server/transition.js +4 -2
  33. package/dist/vite-plugin-app/pipeline.d.ts +4 -13
  34. package/dist/vite-plugin-app/pipeline.js +27 -12
  35. package/dist/vite-plugin-astro-server/base.d.ts +52 -0
  36. package/dist/vite-plugin-astro-server/base.js +66 -36
  37. package/dist/vite-plugin-astro-server/trailing-slash.d.ts +34 -0
  38. package/dist/vite-plugin-astro-server/trailing-slash.js +24 -11
  39. package/package.json +1 -1
@@ -0,0 +1,44 @@
1
+ import type { AstroConfig } from '../../../types/public/config.js';
2
+ export interface ConfigValidationIssue {
3
+ message: string;
4
+ path: (string | number)[];
5
+ }
6
+ type I18nConfig = NonNullable<AstroConfig['i18n']>;
7
+ /**
8
+ * Validates that `build.assetsPrefix`, when specified as an object, includes a `fallback` key.
9
+ */
10
+ export declare function validateAssetsPrefix(config: Pick<AstroConfig, 'build'>): ConfigValidationIssue[];
11
+ /**
12
+ * Validates that remote pattern wildcards are only at the start of hostnames
13
+ * and at the end of pathnames.
14
+ */
15
+ export declare function validateRemotePatterns(remotePatterns: AstroConfig['image']['remotePatterns']): ConfigValidationIssue[];
16
+ /**
17
+ * Validates that `redirectToDefaultLocale` is not `true` when
18
+ * `prefixDefaultLocale` is `false`, which would cause infinite redirects.
19
+ */
20
+ export declare function validateI18nRedirectToDefaultLocale(i18n: AstroConfig['i18n']): ConfigValidationIssue[];
21
+ /**
22
+ * Validates that `outDir` is not inside `publicDir`, which would cause an infinite loop.
23
+ */
24
+ export declare function validateOutDirNotInPublicDir(outDir: AstroConfig['outDir'], publicDir: AstroConfig['publicDir']): ConfigValidationIssue[];
25
+ /**
26
+ * Validates that the default locale is present in the locales array.
27
+ */
28
+ export declare function validateI18nDefaultLocale(i18n: Pick<I18nConfig, 'defaultLocale' | 'locales'>): ConfigValidationIssue[];
29
+ /**
30
+ * Validates i18n fallback entries: keys and values must exist in locales,
31
+ * and the default locale cannot be used as a key.
32
+ */
33
+ export declare function validateI18nFallback(i18n: Pick<I18nConfig, 'defaultLocale' | 'locales' | 'fallback'>): ConfigValidationIssue[];
34
+ /**
35
+ * Validates i18n domain entries: locale keys must exist, domain values must be
36
+ * valid origin URLs, site must be set, and output must be 'server'.
37
+ */
38
+ export declare function validateI18nDomains(config: Pick<AstroConfig, 'site' | 'output' | 'i18n'>): ConfigValidationIssue[];
39
+ /**
40
+ * Validates that font `cssVariable` values start with `--` and don't contain
41
+ * spaces or colons.
42
+ */
43
+ export declare function validateFontsCssVariables(fonts: NonNullable<AstroConfig['fonts']>): ConfigValidationIssue[];
44
+ export {};
@@ -0,0 +1,168 @@
1
+ function validateAssetsPrefix(config) {
2
+ if (config.build.assetsPrefix && typeof config.build.assetsPrefix !== "string" && !config.build.assetsPrefix.fallback) {
3
+ return [
4
+ {
5
+ message: "The `fallback` is mandatory when defining the option as an object.",
6
+ path: ["build", "assetsPrefix"]
7
+ }
8
+ ];
9
+ }
10
+ return [];
11
+ }
12
+ function validateRemotePatterns(remotePatterns) {
13
+ const issues = [];
14
+ for (let i = 0; i < remotePatterns.length; i++) {
15
+ const { hostname, pathname } = remotePatterns[i];
16
+ if (hostname && hostname.includes("*") && !(hostname.startsWith("*.") || hostname.startsWith("**."))) {
17
+ issues.push({
18
+ message: "wildcards can only be placed at the beginning of the hostname",
19
+ path: ["image", "remotePatterns", i, "hostname"]
20
+ });
21
+ }
22
+ if (pathname && pathname.includes("*") && !(pathname.endsWith("/*") || pathname.endsWith("/**"))) {
23
+ issues.push({
24
+ message: "wildcards can only be placed at the end of a pathname",
25
+ path: ["image", "remotePatterns", i, "pathname"]
26
+ });
27
+ }
28
+ }
29
+ return issues;
30
+ }
31
+ function validateI18nRedirectToDefaultLocale(i18n) {
32
+ if (i18n && typeof i18n.routing !== "string" && i18n.routing.prefixDefaultLocale === false && i18n.routing.redirectToDefaultLocale === true) {
33
+ return [
34
+ {
35
+ message: "The option `i18n.routing.redirectToDefaultLocale` can be used only when `i18n.routing.prefixDefaultLocale` is set to `true`; otherwise, redirects might cause infinite loops. Remove the option `i18n.routing.redirectToDefaultLocale`, or change its value to `false`.",
36
+ path: ["i18n", "routing", "redirectToDefaultLocale"]
37
+ }
38
+ ];
39
+ }
40
+ return [];
41
+ }
42
+ function validateOutDirNotInPublicDir(outDir, publicDir) {
43
+ if (outDir.toString().startsWith(publicDir.toString())) {
44
+ return [
45
+ {
46
+ message: "The value of `outDir` must not point to a path within the folder set as `publicDir`, this will cause an infinite loop",
47
+ path: ["outDir"]
48
+ }
49
+ ];
50
+ }
51
+ return [];
52
+ }
53
+ function validateI18nDefaultLocale(i18n) {
54
+ const locales = i18n.locales.map((locale) => typeof locale === "string" ? locale : locale.path);
55
+ if (!locales.includes(i18n.defaultLocale)) {
56
+ return [
57
+ {
58
+ message: `The default locale \`${i18n.defaultLocale}\` is not present in the \`i18n.locales\` array.`,
59
+ path: ["i18n", "locales"]
60
+ }
61
+ ];
62
+ }
63
+ return [];
64
+ }
65
+ function validateI18nFallback(i18n) {
66
+ const issues = [];
67
+ const { defaultLocale, fallback } = i18n;
68
+ if (!fallback) return [];
69
+ const locales = i18n.locales.map((locale) => typeof locale === "string" ? locale : locale.path);
70
+ for (const [fallbackFrom, fallbackTo] of Object.entries(fallback)) {
71
+ if (!locales.includes(fallbackFrom)) {
72
+ issues.push({
73
+ message: `The locale \`${fallbackFrom}\` key in the \`i18n.fallback\` record doesn't exist in the \`i18n.locales\` array.`,
74
+ path: ["i18n", "fallbacks"]
75
+ });
76
+ }
77
+ if (fallbackFrom === defaultLocale) {
78
+ issues.push({
79
+ message: `You can't use the default locale as a key. The default locale can only be used as value.`,
80
+ path: ["i18n", "fallbacks"]
81
+ });
82
+ }
83
+ if (!locales.includes(fallbackTo)) {
84
+ issues.push({
85
+ message: `The locale \`${fallbackTo}\` value in the \`i18n.fallback\` record doesn't exist in the \`i18n.locales\` array.`,
86
+ path: ["i18n", "fallbacks"]
87
+ });
88
+ }
89
+ }
90
+ return issues;
91
+ }
92
+ function validateI18nDomains(config) {
93
+ const issues = [];
94
+ const i18n = config.i18n;
95
+ if (!i18n?.domains) return [];
96
+ const entries = Object.entries(i18n.domains);
97
+ const hasDomains = Object.keys(i18n.domains).length > 0;
98
+ if (entries.length > 0 && !hasDomains) {
99
+ issues.push({
100
+ message: `When specifying some domains, the property \`i18n.routing.strategy\` must be set to \`"domains"\`.`,
101
+ path: ["i18n", "routing", "strategy"]
102
+ });
103
+ }
104
+ if (hasDomains) {
105
+ if (!config.site) {
106
+ issues.push({
107
+ message: "The option `site` isn't set. When using the 'domains' strategy for `i18n`, `site` is required to create absolute URLs for locales that aren't mapped to a domain.",
108
+ path: ["site"]
109
+ });
110
+ }
111
+ if (config.output !== "server") {
112
+ issues.push({
113
+ message: 'Domain support is only available when `output` is `"server"`.',
114
+ path: ["output"]
115
+ });
116
+ }
117
+ }
118
+ const locales = i18n.locales.map((locale) => typeof locale === "string" ? locale : locale.path);
119
+ for (const [domainKey, domainValue] of entries) {
120
+ if (!locales.includes(domainKey)) {
121
+ issues.push({
122
+ message: `The locale \`${domainKey}\` key in the \`i18n.domains\` record doesn't exist in the \`i18n.locales\` array.`,
123
+ path: ["i18n", "domains"]
124
+ });
125
+ }
126
+ if (!domainValue.startsWith("https") && !domainValue.startsWith("http")) {
127
+ issues.push({
128
+ message: "The domain value must be a valid URL, and it has to start with 'https' or 'http'.",
129
+ path: ["i18n", "domains"]
130
+ });
131
+ } else {
132
+ try {
133
+ const domainUrl = new URL(domainValue);
134
+ if (domainUrl.pathname !== "/") {
135
+ issues.push({
136
+ message: `The URL \`${domainValue}\` must contain only the origin. A subsequent pathname isn't allowed here. Remove \`${domainUrl.pathname}\`.`,
137
+ path: ["i18n", "domains"]
138
+ });
139
+ }
140
+ } catch {
141
+ }
142
+ }
143
+ }
144
+ return issues;
145
+ }
146
+ function validateFontsCssVariables(fonts) {
147
+ const issues = [];
148
+ for (let i = 0; i < fonts.length; i++) {
149
+ const { cssVariable } = fonts[i];
150
+ if (!cssVariable.startsWith("--") || cssVariable.includes(" ") || cssVariable.includes(":")) {
151
+ issues.push({
152
+ message: `**cssVariable** property "${cssVariable}" contains invalid characters for CSS variable generation. It must start with -- and be a valid indent: https://developer.mozilla.org/en-US/docs/Web/CSS/ident.`,
153
+ path: ["fonts", i, "cssVariable"]
154
+ });
155
+ }
156
+ }
157
+ return issues;
158
+ }
159
+ export {
160
+ validateAssetsPrefix,
161
+ validateFontsCssVariables,
162
+ validateI18nDefaultLocale,
163
+ validateI18nDomains,
164
+ validateI18nFallback,
165
+ validateI18nRedirectToDefaultLocale,
166
+ validateOutDirNotInPublicDir,
167
+ validateRemotePatterns
168
+ };
@@ -1,152 +1,39 @@
1
1
  import * as z from "zod/v4";
2
+ import {
3
+ validateAssetsPrefix,
4
+ validateFontsCssVariables,
5
+ validateI18nDefaultLocale,
6
+ validateI18nDomains,
7
+ validateI18nFallback,
8
+ validateI18nRedirectToDefaultLocale,
9
+ validateOutDirNotInPublicDir,
10
+ validateRemotePatterns
11
+ } from "./refined-validators.js";
2
12
  const AstroConfigRefinedSchema = z.custom().superRefine((config, ctx) => {
3
- if (config.build.assetsPrefix && typeof config.build.assetsPrefix !== "string" && !config.build.assetsPrefix.fallback) {
4
- ctx.addIssue({
5
- code: z.ZodIssueCode.custom,
6
- message: "The `fallback` is mandatory when defining the option as an object.",
7
- path: ["build", "assetsPrefix"]
8
- });
9
- }
10
- for (let i = 0; i < config.image.remotePatterns.length; i++) {
11
- const { hostname, pathname } = config.image.remotePatterns[i];
12
- if (hostname && hostname.includes("*") && !(hostname.startsWith("*.") || hostname.startsWith("**."))) {
13
- ctx.addIssue({
14
- code: z.ZodIssueCode.custom,
15
- message: "wildcards can only be placed at the beginning of the hostname",
16
- path: ["image", "remotePatterns", i, "hostname"]
17
- });
18
- }
19
- if (pathname && pathname.includes("*") && !(pathname.endsWith("/*") || pathname.endsWith("/**"))) {
20
- ctx.addIssue({
21
- code: z.ZodIssueCode.custom,
22
- message: "wildcards can only be placed at the end of a pathname",
23
- path: ["image", "remotePatterns", i, "pathname"]
24
- });
25
- }
13
+ let issues = [];
14
+ issues = issues.concat(
15
+ validateAssetsPrefix(config),
16
+ validateRemotePatterns(config.image.remotePatterns),
17
+ validateI18nRedirectToDefaultLocale(config.i18n),
18
+ validateOutDirNotInPublicDir(config.outDir, config.publicDir)
19
+ );
20
+ if (config.i18n) {
21
+ issues = issues.concat(
22
+ validateI18nDefaultLocale(config.i18n),
23
+ validateI18nFallback(config.i18n),
24
+ validateI18nDomains(config)
25
+ );
26
26
  }
27
- if (config.i18n && typeof config.i18n.routing !== "string" && config.i18n.routing.prefixDefaultLocale === false && config.i18n.routing.redirectToDefaultLocale === true) {
28
- ctx.addIssue({
29
- code: z.ZodIssueCode.custom,
30
- message: "The option `i18n.routing.redirectToDefaultLocale` can be used only when `i18n.routing.prefixDefaultLocale` is set to `true`; otherwise, redirects might cause infinite loops. Remove the option `i18n.routing.redirectToDefaultLocale`, or change its value to `false`.",
31
- path: ["i18n", "routing", "redirectToDefaultLocale"]
32
- });
27
+ if (config.fonts && config.fonts.length > 0) {
28
+ issues = issues.concat(validateFontsCssVariables(config.fonts));
33
29
  }
34
- if (config.outDir.toString().startsWith(config.publicDir.toString())) {
30
+ for (const issue of issues) {
35
31
  ctx.addIssue({
36
32
  code: z.ZodIssueCode.custom,
37
- message: "The value of `outDir` must not point to a path within the folder set as `publicDir`, this will cause an infinite loop",
38
- path: ["outDir"]
33
+ message: issue.message,
34
+ path: issue.path
39
35
  });
40
36
  }
41
- if (config.i18n) {
42
- const { defaultLocale, locales: _locales, fallback, domains } = config.i18n;
43
- const locales = _locales.map((locale) => {
44
- if (typeof locale === "string") {
45
- return locale;
46
- } else {
47
- return locale.path;
48
- }
49
- });
50
- if (!locales.includes(defaultLocale)) {
51
- ctx.addIssue({
52
- code: z.ZodIssueCode.custom,
53
- message: `The default locale \`${defaultLocale}\` is not present in the \`i18n.locales\` array.`,
54
- path: ["i18n", "locales"]
55
- });
56
- }
57
- if (fallback) {
58
- for (const [fallbackFrom, fallbackTo] of Object.entries(fallback)) {
59
- if (!locales.includes(fallbackFrom)) {
60
- ctx.addIssue({
61
- code: z.ZodIssueCode.custom,
62
- message: `The locale \`${fallbackFrom}\` key in the \`i18n.fallback\` record doesn't exist in the \`i18n.locales\` array.`,
63
- path: ["i18n", "fallbacks"]
64
- });
65
- }
66
- if (fallbackFrom === defaultLocale) {
67
- ctx.addIssue({
68
- code: z.ZodIssueCode.custom,
69
- message: `You can't use the default locale as a key. The default locale can only be used as value.`,
70
- path: ["i18n", "fallbacks"]
71
- });
72
- }
73
- if (!locales.includes(fallbackTo)) {
74
- ctx.addIssue({
75
- code: z.ZodIssueCode.custom,
76
- message: `The locale \`${fallbackTo}\` value in the \`i18n.fallback\` record doesn't exist in the \`i18n.locales\` array.`,
77
- path: ["i18n", "fallbacks"]
78
- });
79
- }
80
- }
81
- }
82
- if (domains) {
83
- const entries = Object.entries(domains);
84
- const hasDomains = domains ? Object.keys(domains).length > 0 : false;
85
- if (entries.length > 0 && !hasDomains) {
86
- ctx.addIssue({
87
- code: z.ZodIssueCode.custom,
88
- message: `When specifying some domains, the property \`i18n.routing.strategy\` must be set to \`"domains"\`.`,
89
- path: ["i18n", "routing", "strategy"]
90
- });
91
- }
92
- if (hasDomains) {
93
- if (!config.site) {
94
- ctx.addIssue({
95
- code: z.ZodIssueCode.custom,
96
- message: "The option `site` isn't set. When using the 'domains' strategy for `i18n`, `site` is required to create absolute URLs for locales that aren't mapped to a domain.",
97
- path: ["site"]
98
- });
99
- }
100
- if (config.output !== "server") {
101
- ctx.addIssue({
102
- code: z.ZodIssueCode.custom,
103
- message: 'Domain support is only available when `output` is `"server"`.',
104
- path: ["output"]
105
- });
106
- }
107
- }
108
- for (const [domainKey, domainValue] of entries) {
109
- if (!locales.includes(domainKey)) {
110
- ctx.addIssue({
111
- code: z.ZodIssueCode.custom,
112
- message: `The locale \`${domainKey}\` key in the \`i18n.domains\` record doesn't exist in the \`i18n.locales\` array.`,
113
- path: ["i18n", "domains"]
114
- });
115
- }
116
- if (!domainValue.startsWith("https") && !domainValue.startsWith("http")) {
117
- ctx.addIssue({
118
- code: z.ZodIssueCode.custom,
119
- message: "The domain value must be a valid URL, and it has to start with 'https' or 'http'.",
120
- path: ["i18n", "domains"]
121
- });
122
- } else {
123
- try {
124
- const domainUrl = new URL(domainValue);
125
- if (domainUrl.pathname !== "/") {
126
- ctx.addIssue({
127
- code: z.ZodIssueCode.custom,
128
- message: `The URL \`${domainValue}\` must contain only the origin. A subsequent pathname isn't allowed here. Remove \`${domainUrl.pathname}\`.`,
129
- path: ["i18n", "domains"]
130
- });
131
- }
132
- } catch {
133
- }
134
- }
135
- }
136
- }
137
- }
138
- if (config.fonts && config.fonts.length > 0) {
139
- for (let i = 0; i < config.fonts.length; i++) {
140
- const { cssVariable } = config.fonts[i];
141
- if (!cssVariable.startsWith("--") || cssVariable.includes(" ") || cssVariable.includes(":")) {
142
- ctx.addIssue({
143
- code: "custom",
144
- message: `**cssVariable** property "${cssVariable}" contains invalid characters for CSS variable generation. It must start with -- and be a valid indent: https://developer.mozilla.org/en-US/docs/Web/CSS/ident.`,
145
- path: ["fonts", i, "cssVariable"]
146
- });
147
- }
148
- }
149
- }
150
37
  });
151
38
  export {
152
39
  AstroConfigRefinedSchema
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "6.1.3";
1
+ const ASTRO_VERSION = "6.1.4";
2
2
  const ASTRO_GENERATOR = `Astro v${ASTRO_VERSION}`;
3
3
  const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute";
4
4
  const REWRITE_DIRECTIVE_HEADER_KEY = "X-Astro-Rewrite";
@@ -5,6 +5,7 @@ const DELETED_VALUE = "deleted";
5
5
  const responseSentSymbol = /* @__PURE__ */ Symbol.for("astro.responseSent");
6
6
  const identity = (value) => value;
7
7
  class AstroCookie {
8
+ value;
8
9
  constructor(value) {
9
10
  this.value = value;
10
11
  }
@@ -37,7 +37,7 @@ async function dev(inlineConfig) {
37
37
  await telemetry.record([]);
38
38
  const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
39
39
  const logger = restart.container.logger;
40
- const currentVersion = "6.1.3";
40
+ const currentVersion = "6.1.4";
41
41
  const isPrerelease = currentVersion.includes("-");
42
42
  if (!isPrerelease) {
43
43
  try {
@@ -3,26 +3,18 @@ import * as vite from "vite";
3
3
  import { globalContentLayer } from "../../content/instance.js";
4
4
  import { attachContentServerListeners } from "../../content/server-listeners.js";
5
5
  import { eventCliSession, telemetry } from "../../events/index.js";
6
+ import { runHookConfigDone, runHookConfigSetup } from "../../integrations/hooks.js";
6
7
  import { SETTINGS_FILE } from "../../preferences/constants.js";
8
+ import { getPrerenderDefault } from "../../prerender/utils.js";
7
9
  import { createSettings, resolveConfig } from "../config/index.js";
8
- import { createNodeLogger } from "../logger/node.js";
10
+ import { createVite } from "../create-vite.js";
9
11
  import { collectErrorMetadata } from "../errors/dev/utils.js";
10
12
  import { isAstroConfigZodError } from "../errors/errors.js";
11
13
  import { createSafeError } from "../errors/index.js";
14
+ import { createNodeLogger } from "../logger/node.js";
12
15
  import { formatErrorMessage, warnIfCspWithShiki } from "../messages/runtime.js";
13
- import { createContainer, startContainer } from "./container.js";
14
- async function createRestartedContainer(container, settings) {
15
- const { logger, fs, inlineConfig } = container;
16
- const newContainer = await createContainer({
17
- isRestart: true,
18
- logger,
19
- settings,
20
- inlineConfig,
21
- fs
22
- });
23
- await startContainer(newContainer);
24
- return newContainer;
25
- }
16
+ import { createRoutesList } from "../routing/create-manifest.js";
17
+ import { createContainer } from "./container.js";
26
18
  const configRE = /.*astro.config.(?:mjs|mts|cjs|cts|js|ts)$/;
27
19
  function shouldRestartContainer({ settings, inlineConfig, restartInFlight }, changedFile) {
28
20
  if (restartInFlight) return false;
@@ -47,25 +39,41 @@ function shouldRestartContainer({ settings, inlineConfig, restartInFlight }, cha
47
39
  }
48
40
  return shouldRestart;
49
41
  }
50
- async function restartContainer(container) {
51
- const { logger, close, settings: existingSettings } = container;
42
+ async function restartContainerInPlace(container) {
43
+ const { logger, settings: existingSettings, inlineConfig, fs } = container;
52
44
  container.restartInFlight = true;
53
45
  try {
54
- const { astroConfig } = await resolveConfig(container.inlineConfig, "dev", container.fs);
55
- if (astroConfig.security.csp) {
56
- logger.warn(
57
- "config",
58
- "Astro's Content Security Policy (CSP) does not work in development mode. To verify your CSP implementation, build the project and run the preview server."
59
- );
60
- }
46
+ const { astroConfig } = await resolveConfig(inlineConfig, "dev", fs);
61
47
  warnIfCspWithShiki(astroConfig, logger);
62
- const settings = await createSettings(
48
+ let settings = await createSettings(
63
49
  astroConfig,
64
- container.inlineConfig.logLevel,
50
+ inlineConfig.logLevel,
65
51
  fileURLToPath(existingSettings.config.root)
66
52
  );
67
- await close();
68
- return await createRestartedContainer(container, settings);
53
+ settings = await runHookConfigSetup({ settings, command: "dev", logger, isRestart: true });
54
+ if (!settings.adapter?.adapterFeatures?.buildOutput) {
55
+ settings.buildOutput = getPrerenderDefault(settings.config) ? "static" : "server";
56
+ }
57
+ await runHookConfigDone({ settings, logger, command: "dev" });
58
+ const mode = inlineConfig?.mode ?? "development";
59
+ const {
60
+ server: { host, headers, allowedHosts }
61
+ } = settings.config;
62
+ const rendererClientEntries = settings.renderers.map((r) => r.clientEntrypoint).filter(Boolean);
63
+ const routesList = await createRoutesList({ settings, fsMod: fs }, logger, { dev: true });
64
+ const address = container.viteServer.httpServer?.address();
65
+ const port = address !== null && typeof address === "object" ? address.port : void 0;
66
+ const newViteConfig = await createVite(
67
+ {
68
+ server: { host, headers, allowedHosts, port },
69
+ optimizeDeps: { include: rendererClientEntries }
70
+ },
71
+ { settings, logger, mode, command: "dev", fs, sync: false, routesList }
72
+ );
73
+ container.viteServer.config = await vite.resolveConfig(newViteConfig, "serve");
74
+ await container.viteServer.restart();
75
+ container.settings = settings;
76
+ return settings;
69
77
  } catch (_err) {
70
78
  const error = createSafeError(_err);
71
79
  if (!isAstroConfigZodError(_err)) {
@@ -74,16 +82,14 @@ async function restartContainer(container) {
74
82
  formatErrorMessage(collectErrorMetadata(error), logger.level() === "debug") + "\n"
75
83
  );
76
84
  }
77
- container.viteServer.environments.client.hot.send({
85
+ container.viteServer.environments?.client?.hot?.send({
78
86
  type: "error",
79
- err: {
80
- message: error.message,
81
- stack: error.stack || ""
82
- }
87
+ err: { message: error.message, stack: error.stack || "" }
83
88
  });
84
- container.restartInFlight = false;
85
89
  logger.error(null, "Continuing with previous valid configuration\n");
86
90
  return error;
91
+ } finally {
92
+ container.restartInFlight = false;
87
93
  }
88
94
  }
89
95
  async function createContainerWithAutomaticRestart({
@@ -92,12 +98,6 @@ async function createContainerWithAutomaticRestart({
92
98
  }) {
93
99
  const logger = createNodeLogger(inlineConfig ?? {});
94
100
  const { userConfig, astroConfig } = await resolveConfig(inlineConfig ?? {}, "dev", fs);
95
- if (astroConfig.security.csp) {
96
- logger.warn(
97
- "config",
98
- "Astro's Content Security Policy (CSP) does not work in development mode. To verify your CSP implementation, build the project and run the preview server."
99
- );
100
- }
101
101
  warnIfCspWithShiki(astroConfig, logger);
102
102
  telemetry.record(eventCliSession("dev", userConfig));
103
103
  const settings = await createSettings(
@@ -119,7 +119,6 @@ async function createContainerWithAutomaticRestart({
119
119
  container: initialContainer,
120
120
  bindCLIShortcuts() {
121
121
  const customShortcuts = [
122
- // Disable default Vite shortcuts that don't work well with Astro
123
122
  { key: "r", description: "" },
124
123
  { key: "u", description: "" },
125
124
  { key: "c", description: "" }
@@ -139,42 +138,38 @@ async function createContainerWithAutomaticRestart({
139
138
  return restartComplete;
140
139
  }
141
140
  };
142
- async function handleServerRestart(logMsg = "", server) {
143
- logger.info(null, (logMsg + " Restarting...").trim());
144
- const container = restart.container;
145
- const result = await restartContainer(container);
146
- if (result instanceof Error) {
147
- resolveRestart(result);
148
- } else {
149
- restart.container = result;
150
- setupContainer();
151
- await attachContentServerListeners(restart.container);
152
- if (server) {
153
- server.resolvedUrls = result.viteServer.resolvedUrls;
154
- }
155
- resolveRestart(null);
156
- }
157
- restartComplete = new Promise((resolve) => {
158
- resolveRestart = resolve;
159
- });
160
- }
161
141
  function handleChangeRestart(logMsg) {
162
142
  return async function(changedFile) {
163
143
  if (shouldRestartContainer(restart.container, changedFile)) {
164
- handleServerRestart(logMsg);
144
+ logger.info(null, (logMsg + " Restarting...").trim());
145
+ const result = await restartContainerInPlace(restart.container);
146
+ if (result instanceof Error) {
147
+ resolveRestart(result);
148
+ } else {
149
+ setupContainer();
150
+ await attachContentServerListeners(restart.container);
151
+ resolveRestart(null);
152
+ }
153
+ restartComplete = new Promise((resolve) => {
154
+ resolveRestart = resolve;
155
+ });
165
156
  }
166
157
  };
167
158
  }
159
+ let changeHandler;
160
+ let unlinkHandler;
161
+ let addHandler;
168
162
  function setupContainer() {
169
163
  const watcher = restart.container.viteServer.watcher;
170
- watcher.on("change", handleChangeRestart("Configuration file updated."));
171
- watcher.on("unlink", handleChangeRestart("Configuration file removed."));
172
- watcher.on("add", handleChangeRestart("Configuration file added."));
173
- restart.container.viteServer.restart = async () => {
174
- if (!restart.container.restartInFlight) {
175
- await handleServerRestart("", restart.container.viteServer);
176
- }
177
- };
164
+ if (changeHandler) watcher.off("change", changeHandler);
165
+ if (unlinkHandler) watcher.off("unlink", unlinkHandler);
166
+ if (addHandler) watcher.off("add", addHandler);
167
+ changeHandler = handleChangeRestart("Configuration file updated.");
168
+ unlinkHandler = handleChangeRestart("Configuration file removed.");
169
+ addHandler = handleChangeRestart("Configuration file added.");
170
+ watcher.on("change", changeHandler);
171
+ watcher.on("unlink", unlinkHandler);
172
+ watcher.on("add", addHandler);
178
173
  }
179
174
  setupContainer();
180
175
  return restart;
@@ -276,7 +276,7 @@ function printHelp({
276
276
  message.push(
277
277
  linebreak(),
278
278
  ` ${bgGreen(black(` ${commandName} `))} ${green(
279
- `v${"6.1.3"}`
279
+ `v${"6.1.4"}`
280
280
  )} ${headline}`
281
281
  );
282
282
  }
@@ -1,6 +1,6 @@
1
1
  import type { ActionAPIContext } from '../actions/runtime/types.js';
2
2
  import type { ComponentInstance } from '../types/astro.js';
3
- import type { MiddlewareHandler, Props } from '../types/public/common.js';
3
+ import type { MiddlewareHandler, Params, Props } from '../types/public/common.js';
4
4
  import type { APIContext, AstroGlobal } from '../types/public/context.js';
5
5
  import type { RouteData, SSRResult } from '../types/public/internal.js';
6
6
  import type { ServerIslandMappings, SSRActions } from './app/types.js';
@@ -26,7 +26,7 @@ export declare class RenderContext {
26
26
  status: number;
27
27
  clientAddress: string | undefined;
28
28
  protected cookies: AstroCookies;
29
- params: import("../types/public/common.js").Params;
29
+ params: Params;
30
30
  protected url: URL;
31
31
  props: Props;
32
32
  partial: undefined | boolean;
@@ -38,6 +38,26 @@ import { AstroSession } from "./session/runtime.js";
38
38
  import { collapseDuplicateSlashes } from "@astrojs/internal-helpers/path";
39
39
  import { validateAndDecodePathname } from "./util/pathname.js";
40
40
  class RenderContext {
41
+ pipeline;
42
+ locals;
43
+ middleware;
44
+ actions;
45
+ serverIslands;
46
+ // It must be a DECODED pathname
47
+ pathname;
48
+ request;
49
+ routeData;
50
+ status;
51
+ clientAddress;
52
+ cookies;
53
+ params;
54
+ url;
55
+ props;
56
+ partial;
57
+ shouldInjectCspMetaTags;
58
+ session;
59
+ cache;
60
+ skipMiddleware;
41
61
  constructor(pipeline, locals, middleware, actions, serverIslands, pathname, request, routeData, status, clientAddress, cookies = new AstroCookies(request), params = getParams(routeData, pathname), url = RenderContext.#createNormalizedUrl(request.url), props = {}, partial = void 0, shouldInjectCspMetaTags = pipeline.manifest.shouldInjectCspMetaTags, session = void 0, cache, skipMiddleware = false) {
42
62
  this.pipeline = pipeline;
43
63
  this.locals = locals;