astro 4.15.0 → 4.15.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.
@@ -1546,7 +1546,7 @@ export interface AstroUserConfig {
1546
1546
  *
1547
1547
  * When `i18n.routing.fallback: "rewrite"` is configured, Astro will create pages that render the contents of the fallback page on the original, requested URL.
1548
1548
  *
1549
- * With the following configuration, if you have the file `src/pages/en/about.astro` but not `src/pages/fr/about.astro`, the `astro build` command will generate `dist/fr/about.html` with the same content as the `dist/en/index.html` page.
1549
+ * With the following configuration, if you have the file `src/pages/en/about.astro` but not `src/pages/fr/about.astro`, the `astro build` command will generate `dist/fr/about.html` with the same content as the `dist/en/about.html` page.
1550
1550
  * Your site visitor will see the English version of the page at `https://example.com/fr/about/` and will not be redirected.
1551
1551
  *
1552
1552
  * ```js
@@ -1566,7 +1566,7 @@ export interface AstroUserConfig {
1566
1566
  * })
1567
1567
  * ```
1568
1568
  */
1569
- fallbackType: 'redirect' | 'rewrite';
1569
+ fallbackType?: 'redirect' | 'rewrite';
1570
1570
  /**
1571
1571
  * @name i18n.routing.strategy
1572
1572
  * @type {"pathname"}
@@ -2947,6 +2947,10 @@ export interface SSRLoadedRendererValue {
2947
2947
  export interface SSRLoadedRenderer extends Pick<AstroRenderer, 'name' | 'clientEntrypoint'> {
2948
2948
  ssr: SSRLoadedRendererValue;
2949
2949
  }
2950
+ export interface RefreshContentOptions {
2951
+ loaders?: Array<string>;
2952
+ context?: Record<string, any>;
2953
+ }
2950
2954
  export type HookParameters<Hook extends keyof AstroIntegration['hooks'], Fn = AstroIntegration['hooks'][Hook]> = Fn extends (...args: any) => any ? Parameters<Fn>[0] : never;
2951
2955
  declare global {
2952
2956
  namespace Astro {
@@ -358,7 +358,11 @@ function addIntegration(mod, integration) {
358
358
  const config = getDefaultExportOptions(mod);
359
359
  const integrationId = toIdent(integration.id);
360
360
  if (!mod.imports.$items.some((imp) => imp.local === integrationId)) {
361
- mod.imports.$append({ imported: integrationId, from: integration.packageName });
361
+ mod.imports.$append({
362
+ imported: "default",
363
+ local: integrationId,
364
+ from: integration.packageName
365
+ });
362
366
  }
363
367
  config.integrations ??= [];
364
368
  if (!config.integrations.$ast.elements.some(
@@ -371,7 +375,11 @@ function setAdapter(mod, adapter) {
371
375
  const config = getDefaultExportOptions(mod);
372
376
  const adapterId = toIdent(adapter.id);
373
377
  if (!mod.imports.$items.some((imp) => imp.local === adapterId)) {
374
- mod.imports.$append({ imported: adapterId, from: adapter.packageName });
378
+ mod.imports.$append({
379
+ imported: "default",
380
+ local: adapterId,
381
+ from: adapter.packageName
382
+ });
375
383
  }
376
384
  if (!config.output) {
377
385
  config.output = "server";
@@ -1,5 +1,5 @@
1
1
  import type { FSWatcher } from 'vite';
2
- import type { AstroSettings } from '../@types/astro.js';
2
+ import type { AstroSettings, RefreshContentOptions } from '../@types/astro.js';
3
3
  import type { Logger } from '../core/logger/core.js';
4
4
  import type { LoaderContext } from './loaders/types.js';
5
5
  import type { MutableDataStore } from './mutable-data-store.js';
@@ -22,19 +22,19 @@ export declare class ContentLayer {
22
22
  watchContentConfig(): void;
23
23
  unwatchContentConfig(): void;
24
24
  /**
25
- * Run the `load()` method of each collection's loader, which will load the data and save it in the data store.
25
+ * Enqueues a sync job that runs the `load()` method of each collection's loader, which will load the data and save it in the data store.
26
26
  * The loader itself is responsible for deciding whether this will clear and reload the full collection, or
27
- * perform an incremental update. After the data is loaded, the data store is written to disk.
27
+ * perform an incremental update. After the data is loaded, the data store is written to disk. Jobs are queued,
28
+ * so that only one sync can run at a time. The function returns a promise that resolves when this sync job is complete.
28
29
  */
29
- sync(): Promise<void>;
30
+ sync(options?: RefreshContentOptions): Promise<void>;
30
31
  regenerateCollectionFileManifest(): Promise<void>;
31
32
  }
32
33
  export declare function simpleLoader<TData extends {
33
34
  id: string;
34
35
  }>(handler: () => Array<TData> | Promise<Array<TData>>, context: LoaderContext): Promise<void>;
35
36
  export declare const globalContentLayer: {
36
- initialized: () => boolean;
37
37
  init: (options: ContentLayerOptions) => ContentLayer;
38
- get: () => ContentLayer;
38
+ get: () => ContentLayer | null;
39
39
  dispose: () => void;
40
40
  };
@@ -1,6 +1,5 @@
1
1
  import { promises as fs, existsSync } from "node:fs";
2
- import { isAbsolute } from "node:path";
3
- import { fileURLToPath } from "node:url";
2
+ import * as fastq from "fastq";
4
3
  import xxhash from "xxhash-wasm";
5
4
  import { AstroUserError } from "../core/errors/errors.js";
6
5
  import {
@@ -12,8 +11,7 @@ import {
12
11
  import {
13
12
  getEntryConfigByExtMap,
14
13
  getEntryDataAndImages,
15
- globalContentConfigObserver,
16
- posixRelative
14
+ globalContentConfigObserver
17
15
  } from "./utils.js";
18
16
  class ContentLayer {
19
17
  #logger;
@@ -23,19 +21,20 @@ class ContentLayer {
23
21
  #lastConfigDigest;
24
22
  #unsubscribe;
25
23
  #generateDigest;
26
- #loading = false;
24
+ #queue;
27
25
  constructor({ settings, logger, store, watcher }) {
28
26
  watcher?.setMaxListeners(50);
29
27
  this.#logger = logger;
30
28
  this.#store = store;
31
29
  this.#settings = settings;
32
30
  this.#watcher = watcher;
31
+ this.#queue = fastq.promise(this.#doSync.bind(this), 1);
33
32
  }
34
33
  /**
35
34
  * Whether the content layer is currently loading content
36
35
  */
37
36
  get loading() {
38
- return this.#loading;
37
+ return !this.#queue.idle();
39
38
  }
40
39
  /**
41
40
  * Watch for changes to the content config and trigger a sync when it changes.
@@ -43,7 +42,7 @@ class ContentLayer {
43
42
  watchContentConfig() {
44
43
  this.#unsubscribe?.();
45
44
  this.#unsubscribe = globalContentConfigObserver.subscribe(async (ctx) => {
46
- if (!this.#loading && ctx.status === "loaded" && ctx.config.digest !== this.#lastConfigDigest) {
45
+ if (ctx.status === "loaded" && ctx.config.digest !== this.#lastConfigDigest) {
47
46
  this.sync();
48
47
  }
49
48
  });
@@ -51,22 +50,6 @@ class ContentLayer {
51
50
  unwatchContentConfig() {
52
51
  this.#unsubscribe?.();
53
52
  }
54
- /**
55
- * Run the `load()` method of each collection's loader, which will load the data and save it in the data store.
56
- * The loader itself is responsible for deciding whether this will clear and reload the full collection, or
57
- * perform an incremental update. After the data is loaded, the data store is written to disk.
58
- */
59
- async sync() {
60
- if (this.#loading) {
61
- return;
62
- }
63
- this.#loading = true;
64
- try {
65
- await this.#doSync();
66
- } finally {
67
- this.#loading = false;
68
- }
69
- }
70
53
  async #getGenerateDigest() {
71
54
  if (this.#generateDigest) {
72
55
  return this.#generateDigest;
@@ -81,7 +64,8 @@ class ContentLayer {
81
64
  async #getLoaderContext({
82
65
  collectionName,
83
66
  loaderName = "content",
84
- parseData
67
+ parseData,
68
+ refreshContextData
85
69
  }) {
86
70
  return {
87
71
  collection: collectionName,
@@ -92,13 +76,23 @@ class ContentLayer {
92
76
  parseData,
93
77
  generateDigest: await this.#getGenerateDigest(),
94
78
  watcher: this.#watcher,
79
+ refreshContextData,
95
80
  entryTypes: getEntryConfigByExtMap([
96
81
  ...this.#settings.contentEntryTypes,
97
82
  ...this.#settings.dataEntryTypes
98
83
  ])
99
84
  };
100
85
  }
101
- async #doSync() {
86
+ /**
87
+ * Enqueues a sync job that runs the `load()` method of each collection's loader, which will load the data and save it in the data store.
88
+ * The loader itself is responsible for deciding whether this will clear and reload the full collection, or
89
+ * perform an incremental update. After the data is loaded, the data store is written to disk. Jobs are queued,
90
+ * so that only one sync can run at a time. The function returns a promise that resolves when this sync job is complete.
91
+ */
92
+ sync(options = {}) {
93
+ return this.#queue.push(options);
94
+ }
95
+ async #doSync(options) {
102
96
  const contentConfig = globalContentConfigObserver.get();
103
97
  const logger = this.#logger.forkIntegrationLogger("content");
104
98
  if (contentConfig?.status !== "loaded") {
@@ -138,9 +132,12 @@ class ContentLayer {
138
132
  schema = await schema();
139
133
  }
140
134
  }
135
+ if (options?.loaders && (typeof collection.loader !== "object" || !options.loaders.includes(collection.loader.name))) {
136
+ return;
137
+ }
141
138
  const collectionWithResolvedSchema = { ...collection, schema };
142
139
  const parseData = async ({ id, data, filePath = "" }) => {
143
- const { imageImports, data: parsedData } = await getEntryDataAndImages(
140
+ const { data: parsedData } = await getEntryDataAndImages(
144
141
  {
145
142
  id,
146
143
  collection: name,
@@ -153,19 +150,13 @@ class ContentLayer {
153
150
  collectionWithResolvedSchema,
154
151
  false
155
152
  );
156
- if (imageImports?.length) {
157
- this.#store.addAssetImports(
158
- imageImports,
159
- // This path may already be relative, if we're re-parsing an existing entry
160
- isAbsolute(filePath) ? posixRelative(fileURLToPath(this.#settings.config.root), filePath) : filePath
161
- );
162
- }
163
153
  return parsedData;
164
154
  };
165
155
  const context = await this.#getLoaderContext({
166
156
  collectionName: name,
167
157
  parseData,
168
- loaderName: collection.loader.name
158
+ loaderName: collection.loader.name,
159
+ refreshContextData: options?.context
169
160
  });
170
161
  if (typeof collection.loader === "function") {
171
162
  return simpleLoader(collection.loader, context);
@@ -236,18 +227,12 @@ async function simpleLoader(handler, context) {
236
227
  function contentLayerSingleton() {
237
228
  let instance = null;
238
229
  return {
239
- initialized: () => Boolean(instance),
240
230
  init: (options) => {
241
231
  instance?.unwatchContentConfig();
242
232
  instance = new ContentLayer(options);
243
233
  return instance;
244
234
  },
245
- get: () => {
246
- if (!instance) {
247
- throw new Error("Content layer not initialized");
248
- }
249
- return instance;
250
- },
235
+ get: () => instance,
251
236
  dispose: () => {
252
237
  instance?.unwatchContentConfig();
253
238
  instance = null;
@@ -30,6 +30,7 @@ export interface DataEntry<TData extends Record<string, unknown> = Record<string
30
30
  * If an entry is a deferred, its rendering phase is delegated to a virtual module during the runtime phase when calling `renderEntry`.
31
31
  */
32
32
  deferredRender?: boolean;
33
+ assetImports?: Array<string>;
33
34
  }
34
35
  /**
35
36
  * A read-only data store for content collections. This is used to retrieve data from the content layer at runtime.
@@ -61,13 +61,9 @@ function glob(globOptions) {
61
61
  if (existingEntry.deferredRender) {
62
62
  store.addModuleImport(existingEntry.filePath);
63
63
  }
64
- if (existingEntry.rendered?.metadata?.imagePaths?.length) {
65
- store.addAssetImports(
66
- existingEntry.rendered.metadata.imagePaths,
67
- existingEntry.filePath
68
- );
64
+ if (existingEntry.assetImports?.length) {
65
+ store.addAssetImports(existingEntry.assetImports, existingEntry.filePath);
69
66
  }
70
- await parseData(existingEntry);
71
67
  return;
72
68
  }
73
69
  const filePath = fileURLToPath(fileUrl);
@@ -101,11 +97,9 @@ function glob(globOptions) {
101
97
  body,
102
98
  filePath: relativePath,
103
99
  digest,
104
- rendered
100
+ rendered,
101
+ assetImports: rendered?.metadata?.imagePaths
105
102
  });
106
- if (rendered?.metadata?.imagePaths?.length) {
107
- store.addAssetImports(rendered.metadata.imagePaths, relativePath);
108
- }
109
103
  } else if ("contentModuleTypes" in entryType) {
110
104
  store.set({
111
105
  id,
@@ -26,6 +26,7 @@ export interface LoaderContext {
26
26
  generateDigest(data: Record<string, unknown> | string): string;
27
27
  /** When running in dev, this is a filesystem watcher that can be used to trigger updates */
28
28
  watcher?: FSWatcher;
29
+ refreshContextData?: Record<string, unknown>;
29
30
  entryTypes: Map<string, ContentEntryType>;
30
31
  }
31
32
  export interface Loader {
@@ -10,8 +10,8 @@ export declare class MutableDataStore extends DataStore {
10
10
  delete(collectionName: string, key: string): void;
11
11
  clear(collectionName: string): void;
12
12
  clearAll(): void;
13
- addAssetImport(assetImport: string, filePath: string): void;
14
- addAssetImports(assets: Array<string>, filePath: string): void;
13
+ addAssetImport(assetImport: string, filePath?: string): void;
14
+ addAssetImports(assets: Array<string>, filePath?: string): void;
15
15
  addModuleImport(fileName: string): void;
16
16
  writeAssetImports(filePath: PathLike): Promise<void>;
17
17
  writeModuleImports(filePath: PathLike): Promise<void>;
@@ -1,7 +1,9 @@
1
1
  import { promises as fs, existsSync } from "node:fs";
2
2
  import * as devalue from "devalue";
3
+ import { Traverse } from "neotraverse/modern";
3
4
  import { imageSrcToImportId, importIdToSymbolName } from "../assets/utils/resolveImports.js";
4
5
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
6
+ import { IMAGE_IMPORT_PREFIX } from "./consts.js";
5
7
  import { DataStore } from "./data-store.js";
6
8
  import { contentModuleToId } from "./utils.js";
7
9
  const SAVE_DEBOUNCE_MS = 500;
@@ -157,7 +159,7 @@ ${lines.join(",\n")}]);
157
159
  entries: () => this.entries(collectionName),
158
160
  values: () => this.values(collectionName),
159
161
  keys: () => this.keys(collectionName),
160
- set: ({ id: key, data, body, filePath, deferredRender, digest, rendered }) => {
162
+ set: ({ id: key, data, body, filePath, deferredRender, digest, rendered, assetImports }) => {
161
163
  if (!key) {
162
164
  throw new Error(`ID must be a non-empty string`);
163
165
  }
@@ -168,6 +170,13 @@ ${lines.join(",\n")}]);
168
170
  return false;
169
171
  }
170
172
  }
173
+ const foundAssets = new Set(assetImports);
174
+ new Traverse(data).forEach((_, val) => {
175
+ if (typeof val === "string" && val.startsWith(IMAGE_IMPORT_PREFIX)) {
176
+ const src = val.replace(IMAGE_IMPORT_PREFIX, "");
177
+ foundAssets.add(src);
178
+ }
179
+ });
171
180
  const entry = {
172
181
  id,
173
182
  data
@@ -181,6 +190,10 @@ ${lines.join(",\n")}]);
181
190
  }
182
191
  entry.filePath = filePath;
183
192
  }
193
+ if (foundAssets.size) {
194
+ entry.assetImports = Array.from(foundAssets);
195
+ this.addAssetImports(entry.assetImports, filePath);
196
+ }
184
197
  if (digest) {
185
198
  entry.digest = digest;
186
199
  }
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "4.15.0";
1
+ const ASTRO_VERSION = "4.15.2";
2
2
  const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute";
3
3
  const REWRITE_DIRECTIVE_HEADER_KEY = "X-Astro-Rewrite";
4
4
  const REWRITE_DIRECTIVE_HEADER_VALUE = "yes";
@@ -23,7 +23,7 @@ async function dev(inlineConfig) {
23
23
  await telemetry.record([]);
24
24
  const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
25
25
  const logger = restart.container.logger;
26
- const currentVersion = "4.15.0";
26
+ const currentVersion = "4.15.2";
27
27
  const isPrerelease = currentVersion.includes("-");
28
28
  if (!isPrerelease) {
29
29
  try {
@@ -130,9 +130,7 @@ async function createContainerWithAutomaticRestart({
130
130
  key: "s",
131
131
  description: "sync content layer",
132
132
  action: () => {
133
- if (globalContentLayer.initialized()) {
134
- globalContentLayer.get().sync();
135
- }
133
+ globalContentLayer.get()?.sync();
136
134
  }
137
135
  });
138
136
  }
@@ -26,23 +26,6 @@ export declare const UnknownCompilerError: {
26
26
  title: string;
27
27
  hint: string;
28
28
  };
29
- /**
30
- * @docs
31
- * @see
32
- * - [Enabling SSR in Your Project](https://docs.astro.build/en/guides/server-side-rendering/)
33
- * - [Astro.redirect](https://docs.astro.build/en/reference/api-reference/#astroredirect)
34
- * @description
35
- * The `Astro.redirect` function is only available when [Server-side rendering](/en/guides/server-side-rendering/) is enabled.
36
- *
37
- * To redirect on a static website, the [meta refresh attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta) can be used. Certain hosts also provide config-based redirects (ex: [Netlify redirects](https://docs.netlify.com/routing/redirects/)).
38
- * @deprecated Deprecated since version 2.6.
39
- */
40
- export declare const StaticRedirectNotAvailable: {
41
- name: string;
42
- title: string;
43
- message: string;
44
- hint: string;
45
- };
46
29
  /**
47
30
  * @docs
48
31
  * @see
@@ -260,20 +243,6 @@ export declare const InvalidGetStaticPathsReturn: {
260
243
  message: (returnType: any) => string;
261
244
  hint: string;
262
245
  };
263
- /**
264
- * @docs
265
- * @deprecated Deprecated since Astro 4.0. The RSS helper no longer exists with an error fallback.
266
- * @see
267
- * - [RSS Guide](https://docs.astro.build/en/guides/rss/)
268
- * @description
269
- * `getStaticPaths` no longer expose an helper for generating a RSS feed. We recommend migrating to the [@astrojs/rss](https://docs.astro.build/en/guides/rss/#setting-up-astrojsrss)integration instead.
270
- */
271
- export declare const GetStaticPathsRemovedRSSHelper: {
272
- name: string;
273
- title: string;
274
- message: string;
275
- hint: string;
276
- };
277
246
  /**
278
247
  * @docs
279
248
  * @see
@@ -650,24 +619,6 @@ export declare const NoImageMetadata: {
650
619
  message: (imagePath: string | undefined) => string;
651
620
  hint: string;
652
621
  };
653
- /**
654
- * @docs
655
- * @deprecated This error is no longer Markdown specific and as such, as been replaced by `ImageNotFound`
656
- * @message
657
- * Could not find requested image `IMAGE_PATH` at `FULL_IMAGE_PATH`.
658
- * @see
659
- * - [Images](https://docs.astro.build/en/guides/images/)
660
- * @description
661
- * Astro could not find an image you included in your Markdown content. Usually, this is simply caused by a typo in the path.
662
- *
663
- * Images in Markdown are relative to the current file. To refer to an image that is located in the same folder as the `.md` file, the path should start with `./`
664
- */
665
- export declare const MarkdownImageNotFound: {
666
- name: string;
667
- title: string;
668
- message: (imagePath: string, fullImagePath: string | undefined) => string;
669
- hint: string;
670
- };
671
622
  /**
672
623
  * @docs
673
624
  * @see
@@ -1020,17 +971,6 @@ export declare const MissingMiddlewareForInternationalization: {
1020
971
  title: string;
1021
972
  message: string;
1022
973
  };
1023
- /**
1024
- * @deprecated
1025
- * @docs
1026
- * @description
1027
- * The user tried to rewrite using a route that doesn't exist, or it emitted a runtime error during its rendering phase.
1028
- */
1029
- export declare const RewriteEncounteredAnError: {
1030
- name: string;
1031
- title: string;
1032
- message: (route: string, stack?: string) => string;
1033
- };
1034
974
  /**
1035
975
  * @docs
1036
976
  * @description
@@ -1387,19 +1327,6 @@ export declare const ContentSchemaContainsSlugError: {
1387
1327
  message: (collectionName: string) => string;
1388
1328
  hint: string;
1389
1329
  };
1390
- /**
1391
- * @docs
1392
- * @message A collection queried via `getCollection()` does not exist.
1393
- * @deprecated Collections that do not exist no longer result in an error. A warning is given instead.
1394
- * @description
1395
- * When querying a collection, ensure a collection directory with the requested name exists under `src/content/`.
1396
- */
1397
- export declare const CollectionDoesNotExistError: {
1398
- name: string;
1399
- title: string;
1400
- message: (collectionName: string) => string;
1401
- hint: string;
1402
- };
1403
1330
  /**
1404
1331
  * @docs
1405
1332
  * @see
@@ -3,12 +3,6 @@ const UnknownCompilerError = {
3
3
  title: "Unknown compiler error.",
4
4
  hint: "This is almost always a problem with the Astro compiler, not your code. Please open an issue at https://astro.build/issues/compiler."
5
5
  };
6
- const StaticRedirectNotAvailable = {
7
- name: "StaticRedirectNotAvailable",
8
- title: "`Astro.redirect` is not available in static mode.",
9
- message: "Redirects are only available when using `output: 'server'` or `output: 'hybrid'`. Update your Astro config if you need SSR features.",
10
- hint: "See https://docs.astro.build/en/guides/server-side-rendering/ for more information on how to enable SSR."
11
- };
12
6
  const ClientAddressNotAvailable = {
13
7
  name: "ClientAddressNotAvailable",
14
8
  title: "`Astro.clientAddress` is not available in current adapter.",
@@ -83,12 +77,6 @@ const InvalidGetStaticPathsReturn = {
83
77
  message: (returnType) => `Invalid type returned by \`getStaticPaths\`. Expected an \`array\`, got \`${returnType}\``,
84
78
  hint: "See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths."
85
79
  };
86
- const GetStaticPathsRemovedRSSHelper = {
87
- name: "GetStaticPathsRemovedRSSHelper",
88
- title: "getStaticPaths RSS helper is not available anymore.",
89
- message: "The RSS helper has been removed from `getStaticPaths`. Try the new @astrojs/rss package instead.",
90
- hint: "See https://docs.astro.build/en/guides/rss/ for more information."
91
- };
92
80
  const GetStaticPathsExpectedParams = {
93
81
  name: "GetStaticPathsExpectedParams",
94
82
  title: "Missing params property on `getStaticPaths` route.",
@@ -233,12 +221,6 @@ const NoImageMetadata = {
233
221
  message: (imagePath) => `Could not process image metadata${imagePath ? ` for \`${imagePath}\`` : ""}.`,
234
222
  hint: "This is often caused by a corrupted or malformed image. Re-exporting the image from your image editor may fix this issue."
235
223
  };
236
- const MarkdownImageNotFound = {
237
- name: "MarkdownImageNotFound",
238
- title: "Image not found.",
239
- message: (imagePath, fullImagePath) => `Could not find requested image \`${imagePath}\`${fullImagePath ? ` at \`${fullImagePath}\`.` : "."}`,
240
- hint: "This is often caused by a typo in the image path. Please make sure the file exists, and is spelled correctly."
241
- };
242
224
  const CouldNotTransformImage = {
243
225
  name: "CouldNotTransformImage",
244
226
  title: "Could not transform image.",
@@ -362,11 +344,6 @@ const MissingMiddlewareForInternationalization = {
362
344
  title: "Enabled manual internationalization routing without having a middleware.",
363
345
  message: "Your configuration setting `i18n.routing: 'manual'` requires you to provide your own i18n `middleware` file."
364
346
  };
365
- const RewriteEncounteredAnError = {
366
- name: "RewriteEncounteredAnError",
367
- title: "Astro couldn't find the route to rewrite, or if was found but it emitted an error during the rendering phase.",
368
- message: (route, stack) => `The route ${route} that you tried to render doesn't exist, or it emitted an error during the rendering phase. ${stack ? stack : ""}.`
369
- };
370
347
  const CantRenderPage = {
371
348
  name: "CantRenderPage",
372
349
  title: "Astro can't render the route.",
@@ -516,12 +493,6 @@ const ContentSchemaContainsSlugError = {
516
493
  message: (collectionName) => `A content collection schema should not contain \`slug\` since it is reserved for slug generation. Remove this from your ${collectionName} collection schema.`,
517
494
  hint: "See https://docs.astro.build/en/guides/content-collections/ for more on the `slug` field."
518
495
  };
519
- const CollectionDoesNotExistError = {
520
- name: "CollectionDoesNotExistError",
521
- title: "Collection does not exist",
522
- message: (collectionName) => `The collection **${collectionName}** does not exist. Ensure a collection directory with this name exists.`,
523
- hint: "See https://docs.astro.build/en/guides/content-collections/ for more on creating collections."
524
- };
525
496
  const MixedContentDataCollectionError = {
526
497
  name: "MixedContentDataCollectionError",
527
498
  title: "Content and data cannot be in same collection.",
@@ -595,7 +566,6 @@ export {
595
566
  CSSSyntaxError,
596
567
  CantRenderPage,
597
568
  ClientAddressNotAvailable,
598
- CollectionDoesNotExistError,
599
569
  ConfigLegacyKey,
600
570
  ConfigNotFound,
601
571
  ContentCollectionTypeMismatchError,
@@ -616,7 +586,6 @@ export {
616
586
  GetEntryDeprecationError,
617
587
  GetStaticPathsExpectedParams,
618
588
  GetStaticPathsInvalidRouteParam,
619
- GetStaticPathsRemovedRSSHelper,
620
589
  GetStaticPathsRequired,
621
590
  ImageMissingAlt,
622
591
  ImageNotFound,
@@ -636,7 +605,6 @@ export {
636
605
  LocalImageUsedWrongly,
637
606
  LocalsNotAnObject,
638
607
  MarkdownFrontmatterParseError,
639
- MarkdownImageNotFound,
640
608
  MdxIntegrationMissingError,
641
609
  MiddlewareCantBeLoaded,
642
610
  MiddlewareNoDataOrNextCalled,
@@ -663,12 +631,10 @@ export {
663
631
  RedirectWithNoLocation,
664
632
  ReservedSlotName,
665
633
  ResponseSentError,
666
- RewriteEncounteredAnError,
667
634
  RewriteWithBodyUsed,
668
635
  RouteNotFound,
669
636
  ServerOnlyModule,
670
637
  StaticClientAddressNotAvailable,
671
- StaticRedirectNotAvailable,
672
638
  UnhandledRejection,
673
639
  UnknownCLIError,
674
640
  UnknownCSSError,
@@ -38,7 +38,7 @@ function serverStart({
38
38
  host,
39
39
  base
40
40
  }) {
41
- const version = "4.15.0";
41
+ const version = "4.15.2";
42
42
  const localPrefix = `${dim("\u2503")} Local `;
43
43
  const networkPrefix = `${dim("\u2503")} Network `;
44
44
  const emptyPrefix = " ".repeat(11);
@@ -270,7 +270,7 @@ function printHelp({
270
270
  message.push(
271
271
  linebreak(),
272
272
  ` ${bgGreen(black(` ${commandName} `))} ${green(
273
- `v${"4.15.0"}`
273
+ `v${"4.15.2"}`
274
274
  )} ${headline}`
275
275
  );
276
276
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "4.15.0",
3
+ "version": "4.15.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",
@@ -111,7 +111,7 @@
111
111
  "@astrojs/compiler": "^2.10.3",
112
112
  "@babel/core": "^7.25.2",
113
113
  "@babel/plugin-transform-react-jsx": "^7.25.2",
114
- "@babel/types": "^7.25.4",
114
+ "@babel/types": "^7.25.6",
115
115
  "@oslojs/encoding": "^0.4.1",
116
116
  "@rollup/pluginutils": "^5.1.0",
117
117
  "@types/babel__core": "^7.20.5",
@@ -135,6 +135,7 @@
135
135
  "esbuild": "^0.21.5",
136
136
  "estree-walker": "^3.0.3",
137
137
  "fast-glob": "^3.3.2",
138
+ "fastq": "^1.17.1",
138
139
  "flattie": "^1.1.1",
139
140
  "github-slugger": "^2.0.0",
140
141
  "gray-matter": "^4.0.3",
@@ -155,11 +156,11 @@
155
156
  "prompts": "^2.4.2",
156
157
  "rehype": "^13.0.1",
157
158
  "semver": "^7.6.3",
158
- "shiki": "^1.14.1",
159
+ "shiki": "^1.16.1",
159
160
  "string-width": "^7.2.0",
160
161
  "strip-ansi": "^7.1.0",
161
162
  "tinyexec": "^0.3.0",
162
- "tsconfck": "^3.1.1",
163
+ "tsconfck": "^3.1.3",
163
164
  "unist-util-visit": "^5.0.0",
164
165
  "vfile": "^6.0.3",
165
166
  "vite": "^5.4.2",
@@ -170,9 +171,9 @@
170
171
  "zod": "^3.23.8",
171
172
  "zod-to-json-schema": "^3.23.2",
172
173
  "zod-to-ts": "^1.2.0",
174
+ "@astrojs/internal-helpers": "0.4.1",
173
175
  "@astrojs/markdown-remark": "5.2.0",
174
- "@astrojs/telemetry": "3.1.0",
175
- "@astrojs/internal-helpers": "0.4.1"
176
+ "@astrojs/telemetry": "3.1.0"
176
177
  },
177
178
  "optionalDependencies": {
178
179
  "sharp": "^0.33.3"
@@ -186,7 +187,7 @@
186
187
  "@types/common-ancestor-path": "^1.0.2",
187
188
  "@types/cssesc": "^3.0.2",
188
189
  "@types/debug": "^4.1.12",
189
- "@types/diff": "^5.2.1",
190
+ "@types/diff": "^5.2.2",
190
191
  "@types/dlv": "^1.1.4",
191
192
  "@types/dom-view-transitions": "^1.0.5",
192
193
  "@types/hast": "^3.0.4",
@@ -198,7 +199,7 @@
198
199
  "@types/semver": "^7.5.8",
199
200
  "@types/yargs-parser": "^21.0.3",
200
201
  "cheerio": "1.0.0",
201
- "eol": "^0.9.1",
202
+ "eol": "^0.10.0",
202
203
  "execa": "^8.0.1",
203
204
  "expect-type": "^0.20.0",
204
205
  "mdast-util-mdx": "^3.0.0",
@@ -210,7 +211,7 @@
210
211
  "rehype-slug": "^6.0.0",
211
212
  "rehype-toc": "^3.0.2",
212
213
  "remark-code-titles": "^0.1.2",
213
- "rollup": "^4.21.1",
214
+ "rollup": "^4.21.2",
214
215
  "sass": "^1.77.8",
215
216
  "undici": "^6.19.8",
216
217
  "unified": "^11.0.5",