astro 4.6.0 → 4.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,7 +45,7 @@ let resultFallbackFormat = fallbackFormat ?? defaultFallbackFormat;
45
45
  if (
46
46
  !fallbackFormat &&
47
47
  isESMImportedImage(originalSrc) &&
48
- originalSrc.format in specialFormatsFallback
48
+ (specialFormatsFallback as ReadonlyArray<string>).includes(originalSrc.format)
49
49
  ) {
50
50
  resultFallbackFormat = originalSrc.format;
51
51
  }
@@ -1725,7 +1725,7 @@ export interface AstroUserConfig {
1725
1725
  * });
1726
1726
  * ```
1727
1727
  *
1728
- * Both page routes built and URLs returned by the `astro:i18n` helper functions [`getAbsoluteLocaleUrl()`](https://docs.astro.build/en/guides/internationalization/#getabsolutelocaleurl) and [`getAbsoluteLocaleUrlList()`](https://docs.astro.build/en/guides/internationalization/#getabsolutelocaleurllist) will use the options set in `i18n.domains`.
1728
+ * Both page routes built and URLs returned by the `astro:i18n` helper functions [`getAbsoluteLocaleUrl()`](https://docs.astro.build/en/reference/api-reference/#getabsolutelocaleurl) and [`getAbsoluteLocaleUrlList()`](https://docs.astro.build/en/reference/api-reference/#getabsolutelocaleurllist) will use the options set in `i18n.domains`.
1729
1729
  *
1730
1730
  * See the [Internationalization Guide](https://docs.astro.build/en/guides/internationalization/#domains-experimental) for more details, including the limitations of this experimental feature.
1731
1731
  */
@@ -4,9 +4,12 @@ import { getConfiguredImageService } from "../internal.js";
4
4
  import { etag } from "../utils/etag.js";
5
5
  import { isRemoteAllowed } from "../utils/remotePattern.js";
6
6
  import { imageConfig } from "astro:assets";
7
- async function loadRemoteImage(src) {
7
+ async function loadRemoteImage(src, headers) {
8
8
  try {
9
- const res = await fetch(src);
9
+ const res = await fetch(src, {
10
+ // Forward all headers from the original request
11
+ headers
12
+ });
10
13
  if (!res.ok) {
11
14
  return void 0;
12
15
  }
@@ -27,11 +30,12 @@ const GET = async ({ request }) => {
27
30
  throw new Error("Incorrect transform returned by `parseURL`");
28
31
  }
29
32
  let inputBuffer = void 0;
30
- const sourceUrl = isRemotePath(transform.src) ? new URL(transform.src) : new URL(transform.src, url.origin);
31
- if (isRemotePath(transform.src) && isRemoteAllowed(transform.src, imageConfig) === false) {
33
+ const isRemoteImage = isRemotePath(transform.src);
34
+ const sourceUrl = isRemoteImage ? new URL(transform.src) : new URL(transform.src, url.origin);
35
+ if (isRemoteImage && isRemoteAllowed(transform.src, imageConfig) === false) {
32
36
  return new Response("Forbidden", { status: 403 });
33
37
  }
34
- inputBuffer = await loadRemoteImage(sourceUrl);
38
+ inputBuffer = await loadRemoteImage(sourceUrl, isRemoteImage ? new Headers() : request.headers);
35
39
  if (!inputBuffer) {
36
40
  return new Response("Not Found", { status: 404 });
37
41
  }
@@ -41,7 +41,6 @@ function parseAttributes(root) {
41
41
  const viewbox = root.match(extractorRegExps.viewbox);
42
42
  return {
43
43
  height: height && parseLength(height[2]),
44
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
45
44
  viewbox: viewbox && parseViewbox(viewbox[2]),
46
45
  width: width && parseLength(width[2])
47
46
  };
@@ -823,14 +823,14 @@ async function updateTSConfig(cwd = process.cwd(), logger, integrationsInfo, fla
823
823
  inputConfig = {
824
824
  tsconfig: defaultTSConfig,
825
825
  tsconfigFile: path.join(cwd, "tsconfig.json"),
826
- rawConfig: { tsconfig: defaultTSConfig, tsconfigFile: path.join(cwd, "tsconfig.json") }
826
+ rawConfig: defaultTSConfig
827
827
  };
828
828
  } else {
829
- inputConfigText = JSON.stringify(inputConfig.rawConfig.tsconfig, null, 2);
829
+ inputConfigText = JSON.stringify(inputConfig.rawConfig, null, 2);
830
830
  }
831
831
  const configFileName = path.basename(inputConfig.tsconfigFile);
832
832
  const outputConfig = updateTSConfigForFramework(
833
- inputConfig.rawConfig.tsconfig,
833
+ inputConfig.rawConfig,
834
834
  firstIntegrationWithTSSettings
835
835
  );
836
836
  const output = JSON.stringify(outputConfig, null, 2);
@@ -76,7 +76,7 @@ function getInstallCommand(packages, packageManager) {
76
76
  }
77
77
  async function installPackage(packageNames, options, logger) {
78
78
  const cwd = options.cwd ?? process.cwd();
79
- const packageManager = (await whichPm(cwd)).name ?? "npm";
79
+ const packageManager = (await whichPm(cwd))?.name ?? "npm";
80
80
  const installCommand = getInstallCommand(packageNames, packageManager);
81
81
  if (!installCommand) {
82
82
  return false;
@@ -1,3 +1,4 @@
1
+ import pLimit from "p-limit";
1
2
  import { ZodIssueCode, string as zodString } from "zod";
2
3
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
3
4
  import { prependForwardSlash } from "../core/path.js";
@@ -58,28 +59,31 @@ function createGetCollection({
58
59
  if (!import.meta.env?.DEV && cacheEntriesByCollection.has(collection)) {
59
60
  entries = [...cacheEntriesByCollection.get(collection)];
60
61
  } else {
62
+ const limit = pLimit(10);
61
63
  entries = await Promise.all(
62
- lazyImports.map(async (lazyImport) => {
63
- const entry = await lazyImport();
64
- return type === "content" ? {
65
- id: entry.id,
66
- slug: entry.slug,
67
- body: entry.body,
68
- collection: entry.collection,
69
- data: entry.data,
70
- async render() {
71
- return render({
72
- collection: entry.collection,
73
- id: entry.id,
74
- renderEntryImport: await getRenderEntryImport(collection, entry.slug)
75
- });
76
- }
77
- } : {
78
- id: entry.id,
79
- collection: entry.collection,
80
- data: entry.data
81
- };
82
- })
64
+ lazyImports.map(
65
+ (lazyImport) => limit(async () => {
66
+ const entry = await lazyImport();
67
+ return type === "content" ? {
68
+ id: entry.id,
69
+ slug: entry.slug,
70
+ body: entry.body,
71
+ collection: entry.collection,
72
+ data: entry.data,
73
+ async render() {
74
+ return render({
75
+ collection: entry.collection,
76
+ id: entry.id,
77
+ renderEntryImport: await getRenderEntryImport(collection, entry.slug)
78
+ });
79
+ }
80
+ } : {
81
+ id: entry.id,
82
+ collection: entry.collection,
83
+ data: entry.data
84
+ };
85
+ })
86
+ )
83
87
  );
84
88
  cacheEntriesByCollection.set(collection, entries);
85
89
  }
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import os from "node:os";
3
3
  import { fileURLToPath } from "node:url";
4
- import { bgGreen, black, blue, bold, dim, green, magenta, red } from "kleur/colors";
4
+ import { bgGreen, black, blue, bold, dim, green, magenta } from "kleur/colors";
5
5
  import PQueue from "p-queue";
6
6
  import {
7
7
  generateImagesForPath,
@@ -37,7 +37,7 @@ class BuildPipeline extends Pipeline {
37
37
  return assetLink;
38
38
  }
39
39
  const serverLike = isServerLikeOutput(config);
40
- const streaming = true;
40
+ const streaming = serverLike;
41
41
  super(
42
42
  options.logger,
43
43
  manifest,
@@ -10,7 +10,7 @@ type TSConfigResult<T = {}> = Promise<(TSConfckParseResult & T) | 'invalid-confi
10
10
  * @param findUp Whether to search for the config file in parent directories, by default only the root directory is searched.
11
11
  */
12
12
  export declare function loadTSConfig(root: string | undefined, findUp?: boolean): Promise<TSConfigResult<{
13
- rawConfig: TSConfckParseResult;
13
+ rawConfig: TSConfig;
14
14
  }>>;
15
15
  export declare function updateTSConfigForFramework(target: TSConfig, framework: frameworkWithTSSettings): TSConfig;
16
16
  export type StripEnums<T extends Record<string, any>> = {
@@ -1,8 +1,10 @@
1
+ import { readFile } from "node:fs/promises";
1
2
  import { join } from "node:path";
2
3
  import {
3
4
  TSConfckParseError,
4
5
  find,
5
- parse
6
+ parse,
7
+ toJson
6
8
  } from "tsconfck";
7
9
  const defaultTSConfig = { extends: "astro/tsconfigs/base" };
8
10
  const presets = /* @__PURE__ */ new Map([
@@ -64,14 +66,16 @@ async function loadTSConfig(root, findUp = false) {
64
66
  if (typeof parsedConfig === "string") {
65
67
  return parsedConfig;
66
68
  }
67
- return { ...parsedConfig, rawConfig: parsedConfig.extended?.[0] ?? parsedConfig.tsconfig };
69
+ const rawConfig = await readFile(tsconfig, "utf-8").then(toJson).then((content) => JSON.parse(content));
70
+ return { ...parsedConfig, rawConfig };
68
71
  }
69
72
  if (jsconfig) {
70
73
  const parsedConfig = await safeParse(jsconfig, { root });
71
74
  if (typeof parsedConfig === "string") {
72
75
  return parsedConfig;
73
76
  }
74
- return { ...parsedConfig, rawConfig: parsedConfig.extended?.[0] ?? parsedConfig.tsconfig };
77
+ const rawConfig = await readFile(jsconfig, "utf-8").then(toJson).then((content) => JSON.parse(content));
78
+ return { ...parsedConfig, rawConfig };
75
79
  }
76
80
  return "missing-config";
77
81
  }
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "4.6.0";
1
+ const ASTRO_VERSION = "4.6.2";
2
2
  const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute";
3
3
  const ROUTE_TYPE_HEADER = "X-Astro-Route-Type";
4
4
  const DEFAULT_404_COMPONENT = "astro-default-404";
@@ -180,7 +180,8 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
180
180
  ssr: {
181
181
  noExternal: [...ALWAYS_NOEXTERNAL, ...astroPkgsConfig.ssr.noExternal],
182
182
  external: [...mode === "dev" ? ONLY_DEV_EXTERNAL : [], ...astroPkgsConfig.ssr.external]
183
- }
183
+ },
184
+ build: { assetsDir: settings.config.build.assets }
184
185
  };
185
186
  const assetsPrefix = settings.config.build.assetsPrefix;
186
187
  if (assetsPrefix) {
@@ -23,7 +23,7 @@ async function dev(inlineConfig) {
23
23
  base: restart.container.settings.config.base
24
24
  })
25
25
  );
26
- const currentVersion = "4.6.0";
26
+ const currentVersion = "4.6.2";
27
27
  if (currentVersion.includes("-")) {
28
28
  logger.warn("SKIP_FORMAT", msg.prerelease({ currentVersion }));
29
29
  }
@@ -340,7 +340,7 @@ const MissingIndexForInternationalization = {
340
340
  const IncorrectStrategyForI18n = {
341
341
  name: "IncorrectStrategyForI18n",
342
342
  title: "You can't use the current function with the current strategy",
343
- message: (functionName) => `The function \`${functionName}' can only be used when the \`i18n.routing.strategy\` is set to \`"manual"\`.`
343
+ message: (functionName) => `The function \`${functionName}\` can only be used when the \`i18n.routing.strategy\` is set to \`"manual"\`.`
344
344
  };
345
345
  const NoPrerenderedRoutesWithDomains = {
346
346
  name: "NoPrerenderedRoutesWithDomains",
@@ -36,7 +36,7 @@ function serverStart({
36
36
  host,
37
37
  base
38
38
  }) {
39
- const version = "4.6.0";
39
+ const version = "4.6.2";
40
40
  const localPrefix = `${dim("\u2503")} Local `;
41
41
  const networkPrefix = `${dim("\u2503")} Network `;
42
42
  const emptyPrefix = " ".repeat(11);
@@ -261,7 +261,7 @@ function printHelp({
261
261
  message.push(
262
262
  linebreak(),
263
263
  ` ${bgGreen(black(` ${commandName} `))} ${green(
264
- `v${"4.6.0"}`
264
+ `v${"4.6.2"}`
265
265
  )} ${headline}`
266
266
  );
267
267
  }
@@ -216,7 +216,8 @@ class RenderContext {
216
216
  };
217
217
  const slots = new Slots(result, slotValues, pipeline.logger);
218
218
  const astroGlobalCombined = {
219
- ...astroGlobalPartial,
219
+ generator: astroGlobalPartial.generator,
220
+ glob: astroGlobalPartial.glob,
220
221
  cookies,
221
222
  get clientAddress() {
222
223
  return renderContext.clientAddress();
@@ -95,6 +95,6 @@ export type MiddlewarePayload = {
95
95
  export declare function redirectToDefaultLocale({ trailingSlash, format, base, defaultLocale, }: MiddlewarePayload): (context: APIContext, statusCode?: ValidRedirectStatus) => Response;
96
96
  export declare function notFound({ base, locales }: MiddlewarePayload): (context: APIContext, response?: Response) => Response | undefined;
97
97
  export type RedirectToFallback = (context: APIContext, response: Response) => Response;
98
- export declare function redirectToFallback({ fallback, locales, defaultLocale, strategy, }: MiddlewarePayload): (context: APIContext, response: Response) => Response;
98
+ export declare function redirectToFallback({ fallback, locales, defaultLocale, strategy, base, }: MiddlewarePayload): (context: APIContext, response: Response) => Response;
99
99
  export declare function createMiddleware(i18nManifest: SSRManifest['i18n'], base: SSRManifest['base'], trailingSlash: SSRManifest['trailingSlash'], format: SSRManifest['buildFormat']): import("../@types/astro.js").MiddlewareHandler;
100
100
  export {};
@@ -210,7 +210,8 @@ function redirectToFallback({
210
210
  fallback,
211
211
  locales,
212
212
  defaultLocale,
213
- strategy
213
+ strategy,
214
+ base
214
215
  }) {
215
216
  return function(context, response) {
216
217
  if (response.status >= 300 && fallback) {
@@ -233,7 +234,11 @@ function redirectToFallback({
233
234
  const pathFallbackLocale = getPathByLocale(fallbackLocale, locales);
234
235
  let newPathname;
235
236
  if (pathFallbackLocale === defaultLocale && strategy === "pathname-prefix-other-locales") {
236
- newPathname = context.url.pathname.replace(`/${urlLocale}`, ``);
237
+ if (context.url.pathname.includes(`${base}`)) {
238
+ newPathname = context.url.pathname.replace(`/${urlLocale}`, ``);
239
+ } else {
240
+ newPathname = context.url.pathname.replace(`/${urlLocale}`, `/`);
241
+ }
237
242
  } else {
238
243
  newPathname = context.url.pathname.replace(`/${urlLocale}`, `/${pathFallbackLocale}`);
239
244
  }
@@ -1,6 +1,5 @@
1
1
  import { ROUTE_TYPE_HEADER } from "../core/constants.js";
2
2
  import {
3
- getPathByLocale,
4
3
  normalizeTheLocale,
5
4
  notFound,
6
5
  redirectToDefaultLocale,
@@ -16,6 +16,9 @@ async function renderToString(result, componentFactory, props, children, isPage
16
16
  return templateResult;
17
17
  let str = "";
18
18
  let renderedFirstPageChunk = false;
19
+ if (isPage) {
20
+ await bufferHeadContent(result);
21
+ }
19
22
  const destination = {
20
23
  write(chunk) {
21
24
  if (isPage && !renderedFirstPageChunk) {
@@ -267,6 +267,7 @@ async function updateDOM(preparationEvent, options, historyState, fallback) {
267
267
  return style.animationIterationCount === "infinite";
268
268
  }
269
269
  const currentAnimations = document.getAnimations();
270
+ await new Promise((r) => setTimeout(r));
270
271
  document.documentElement.setAttribute(OLD_NEW_ATTR, phase);
271
272
  const nextAnimations = document.getAnimations();
272
273
  const newAnimations = nextAnimations.filter(
@@ -39,6 +39,11 @@ function markdown({ settings, logger }) {
39
39
  const rawFile = await fs.promises.readFile(fileId, "utf-8");
40
40
  const raw = safeParseFrontmatter(rawFile, id);
41
41
  const fileURL = pathToFileURL(fileId);
42
+ if (!processor) {
43
+ return this.error(
44
+ "MDX processor is not initialized. This is an internal error. Please file an issue."
45
+ );
46
+ }
42
47
  const renderResult = await processor.render(raw.content, {
43
48
  // @ts-expect-error passing internal prop
44
49
  fileURL,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "4.6.0",
3
+ "version": "4.6.2",
4
4
  "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
5
5
  "type": "module",
6
6
  "author": "withastro",
@@ -110,6 +110,7 @@
110
110
  "@babel/traverse": "^7.23.3",
111
111
  "@babel/types": "^7.23.3",
112
112
  "@types/babel__core": "^7.20.4",
113
+ "@types/cookie": "^0.5.4",
113
114
  "acorn": "^8.11.2",
114
115
  "aria-query": "^5.3.0",
115
116
  "axobject-query": "^4.0.0",
@@ -177,7 +178,6 @@
177
178
  "@types/chai": "^4.3.10",
178
179
  "@types/common-ancestor-path": "^1.0.2",
179
180
  "@types/connect": "^3.4.38",
180
- "@types/cookie": "^0.5.4",
181
181
  "@types/cssesc": "^3.0.2",
182
182
  "@types/debug": "^4.1.12",
183
183
  "@types/diff": "^5.0.8",