astro 2.5.5 → 2.5.6

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 (46) hide show
  1. package/dist/@types/astro.d.ts +3 -2
  2. package/dist/assets/services/service.js +6 -0
  3. package/dist/assets/utils/emitAsset.d.ts +1 -3
  4. package/dist/assets/utils/emitAsset.js +4 -15
  5. package/dist/assets/vite-plugin-assets.js +5 -5
  6. package/dist/content/runtime-assets.d.ts +1 -2
  7. package/dist/content/runtime-assets.js +2 -3
  8. package/dist/content/runtime.js +1 -1
  9. package/dist/content/types-generator.js +9 -5
  10. package/dist/content/utils.d.ts +2 -2
  11. package/dist/content/utils.js +4 -4
  12. package/dist/content/vite-plugin-content-imports.js +113 -150
  13. package/dist/content/vite-plugin-content-virtual-mod.d.ts +3 -3
  14. package/dist/content/vite-plugin-content-virtual-mod.js +7 -3
  15. package/dist/core/app/index.d.ts +0 -2
  16. package/dist/core/app/index.js +5 -7
  17. package/dist/core/app/types.d.ts +3 -2
  18. package/dist/core/build/generate.js +16 -11
  19. package/dist/core/build/graph.js +3 -2
  20. package/dist/core/build/internal.d.ts +8 -4
  21. package/dist/core/build/internal.js +19 -1
  22. package/dist/core/build/plugins/plugin-css.js +9 -14
  23. package/dist/core/build/plugins/plugin-middleware.d.ts +0 -1
  24. package/dist/core/build/plugins/plugin-middleware.js +3 -16
  25. package/dist/core/build/plugins/plugin-pages.d.ts +10 -0
  26. package/dist/core/build/plugins/plugin-pages.js +40 -24
  27. package/dist/core/build/plugins/plugin-ssr.d.ts +2 -2
  28. package/dist/core/build/plugins/plugin-ssr.js +46 -20
  29. package/dist/core/build/static-build.js +18 -5
  30. package/dist/core/build/types.d.ts +2 -2
  31. package/dist/core/config/schema.d.ts +170 -170
  32. package/dist/core/constants.js +1 -1
  33. package/dist/core/dev/dev.js +1 -1
  34. package/dist/core/errors/errors-data.d.ts +57 -8
  35. package/dist/core/errors/errors-data.js +57 -12
  36. package/dist/core/messages.js +2 -2
  37. package/dist/core/render/dev/index.js +1 -2
  38. package/dist/prerender/routing.d.ts +13 -0
  39. package/dist/prerender/routing.js +49 -0
  40. package/dist/runtime/server/astro-global.js +11 -1
  41. package/dist/runtime/server/index.d.ts +1 -1
  42. package/dist/runtime/server/index.js +9 -1
  43. package/dist/runtime/server/render/astro/instance.js +3 -0
  44. package/dist/runtime/server/scripts.js +1 -1
  45. package/dist/vite-plugin-astro-server/route.js +3 -11
  46. package/package.json +4 -4
@@ -1166,8 +1166,9 @@ export interface ContentEntryType {
1166
1166
  contents: string;
1167
1167
  }): GetContentEntryInfoReturnType | Promise<GetContentEntryInfoReturnType>;
1168
1168
  getRenderModule?(this: rollup.PluginContext, params: {
1169
+ contents: string;
1170
+ fileUrl: URL;
1169
1171
  viteId: string;
1170
- entry: ContentEntryModule;
1171
1172
  }): rollup.LoadResult | Promise<rollup.LoadResult>;
1172
1173
  contentModuleTypes?: string;
1173
1174
  }
@@ -1528,7 +1529,7 @@ export interface APIContext<Props extends Record<string, any> = Record<string, a
1528
1529
  *
1529
1530
  * export const onRequest = defineMiddleware((context, next) => {
1530
1531
  * context.locals.greeting = "Hello!";
1531
- * next();
1532
+ * return next();
1532
1533
  * });
1533
1534
  * ```
1534
1535
  * Inside a `.astro` file:
@@ -24,6 +24,12 @@ const baseService = {
24
24
  });
25
25
  }
26
26
  if (!isESMImportedImage(options.src)) {
27
+ if (options.src.startsWith("/@fs/")) {
28
+ throw new AstroError({
29
+ ...AstroErrorData.LocalImageUsedWrongly,
30
+ message: AstroErrorData.LocalImageUsedWrongly.message(options.src)
31
+ });
32
+ }
27
33
  let missingDimension;
28
34
  if (!options.width && !options.height) {
29
35
  missingDimension = "both";
@@ -1,4 +1,2 @@
1
- import type { AstroSettings } from '../../@types/astro';
2
1
  import { type Metadata } from './metadata.js';
3
- export declare function emitESMImage(id: string | undefined, watchMode: boolean, fileEmitter: any, settings: Pick<AstroSettings, 'config'>): Promise<Metadata | undefined>;
4
- export declare function emoji(char: string, fallback: string): string;
2
+ export declare function emitESMImage(id: string | undefined, watchMode: boolean, fileEmitter: any): Promise<Metadata | undefined>;
@@ -2,8 +2,9 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
4
  import slash from "slash";
5
+ import { prependForwardSlash } from "../../core/path.js";
5
6
  import { imageMetadata } from "./metadata.js";
6
- async function emitESMImage(id, watchMode, fileEmitter, settings) {
7
+ async function emitESMImage(id, watchMode, fileEmitter) {
7
8
  if (!id) {
8
9
  return void 0;
9
10
  }
@@ -25,25 +26,13 @@ async function emitESMImage(id, watchMode, fileEmitter, settings) {
25
26
  url.searchParams.append("origWidth", meta.width.toString());
26
27
  url.searchParams.append("origHeight", meta.height.toString());
27
28
  url.searchParams.append("origFormat", meta.format);
28
- meta.src = rootRelativePath(settings.config, url);
29
+ meta.src = `/@fs` + prependForwardSlash(fileURLToNormalizedPath(url));
29
30
  }
30
31
  return meta;
31
32
  }
32
- function rootRelativePath(config, url) {
33
- const basePath = fileURLToNormalizedPath(url);
34
- const rootPath = fileURLToNormalizedPath(config.root);
35
- return prependForwardSlash(basePath.slice(rootPath.length));
36
- }
37
- function prependForwardSlash(filePath) {
38
- return filePath[0] === "/" ? filePath : "/" + filePath;
39
- }
40
33
  function fileURLToNormalizedPath(filePath) {
41
34
  return slash(fileURLToPath(filePath) + filePath.search).replace(/\\/g, "/");
42
35
  }
43
- function emoji(char, fallback) {
44
- return process.platform !== "win32" ? char : fallback;
45
- }
46
36
  export {
47
- emitESMImage,
48
- emoji
37
+ emitESMImage
49
38
  };
@@ -87,17 +87,17 @@ function assets({
87
87
  // Handle serving images during development
88
88
  configureServer(server) {
89
89
  server.middlewares.use(async (req, res, next) => {
90
- var _a2;
90
+ var _a2, _b;
91
91
  if ((_a2 = req.url) == null ? void 0 : _a2.startsWith("/_image")) {
92
92
  if (!isLocalService(globalThis.astroAsset.imageService)) {
93
93
  return next();
94
94
  }
95
95
  const url = new URL(req.url, "file:");
96
- const filePath = url.searchParams.get("href");
97
- if (!filePath) {
96
+ if (!url.searchParams.has("href")) {
98
97
  return next();
99
98
  }
100
- const filePathURL = new URL("." + filePath, settings.config.root);
99
+ const filePath = (_b = url.searchParams.get("href")) == null ? void 0 : _b.slice("/@fs".length);
100
+ const filePathURL = new URL("." + filePath, "file:");
101
101
  const file = await fs.readFile(filePathURL);
102
102
  let meta = getOrigQueryParams(filePathURL.searchParams);
103
103
  if (!meta) {
@@ -196,7 +196,7 @@ function assets({
196
196
  }
197
197
  const cleanedUrl = removeQueryString(id);
198
198
  if (/\.(jpeg|jpg|png|tiff|webp|gif|svg)$/.test(cleanedUrl)) {
199
- const meta = await emitESMImage(id, this.meta.watchMode, this.emitFile, settings);
199
+ const meta = await emitESMImage(id, this.meta.watchMode, this.emitFile);
200
200
  return `export default ${JSON.stringify(meta)}`;
201
201
  }
202
202
  }
@@ -1,4 +1,3 @@
1
1
  import type { PluginContext } from 'rollup';
2
2
  import { z } from 'zod';
3
- import type { AstroSettings } from '../@types/astro.js';
4
- export declare function createImage(settings: Pick<AstroSettings, 'config'>, pluginContext: PluginContext, entryFilePath: string): () => z.ZodEffects<z.ZodString, import("../assets/utils/metadata.js").Metadata | z.ZodNever, string>;
3
+ export declare function createImage(pluginContext: PluginContext, entryFilePath: string): () => z.ZodEffects<z.ZodString, import("../assets/utils/metadata.js").Metadata | z.ZodNever, string>;
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { emitESMImage } from "../assets/index.js";
3
- function createImage(settings, pluginContext, entryFilePath) {
3
+ function createImage(pluginContext, entryFilePath) {
4
4
  return () => {
5
5
  return z.string().transform(async (imagePath, ctx) => {
6
6
  var _a;
@@ -8,8 +8,7 @@ function createImage(settings, pluginContext, entryFilePath) {
8
8
  const metadata = await emitESMImage(
9
9
  resolvedFilePath,
10
10
  pluginContext.meta.watchMode,
11
- pluginContext.emitFile,
12
- settings
11
+ pluginContext.emitFile
13
12
  );
14
13
  if (!metadata) {
15
14
  ctx.addIssue({
@@ -223,7 +223,7 @@ async function render({
223
223
  scripts = collectedScripts.map((script) => renderScriptElement(script)).join("");
224
224
  }
225
225
  let props = baseProps;
226
- if (id.endsWith("mdx")) {
226
+ if (id.endsWith(".mdx")) {
227
227
  props = {
228
228
  components: mod.components ?? {},
229
229
  ...baseProps
@@ -9,12 +9,12 @@ import { info, warn } from "../core/logger/core.js";
9
9
  import { isRelativePath } from "../core/path.js";
10
10
  import { CONTENT_TYPES_FILE, VIRTUAL_MODULE_ID } from "./consts.js";
11
11
  import {
12
- getContentEntryConfigByExtMap,
13
12
  getContentEntryIdAndSlug,
14
13
  getContentPaths,
15
14
  getDataEntryExts,
16
15
  getDataEntryId,
17
16
  getEntryCollectionName,
17
+ getEntryConfigByExtMap,
18
18
  getEntrySlug,
19
19
  getEntryType,
20
20
  reloadContentConfigObserver
@@ -30,7 +30,7 @@ async function createContentTypesGenerator({
30
30
  }) {
31
31
  const collectionEntryMap = {};
32
32
  const contentPaths = getContentPaths(settings.config, fs);
33
- const contentEntryConfigByExt = getContentEntryConfigByExtMap(settings);
33
+ const contentEntryConfigByExt = getEntryConfigByExtMap(settings.contentEntryTypes);
34
34
  const contentEntryExts = [...contentEntryConfigByExt.keys()];
35
35
  const dataEntryExts = getDataEntryExts(settings);
36
36
  let events = [];
@@ -327,7 +327,7 @@ async function writeContentFiles({
327
327
  for (const collectionKey of Object.keys(collectionEntryMap).sort()) {
328
328
  const collectionConfig = contentConfig == null ? void 0 : contentConfig.collections[JSON.parse(collectionKey)];
329
329
  const collection = collectionEntryMap[collectionKey];
330
- if ((collectionConfig == null ? void 0 : collectionConfig.type) && collection.type !== collectionConfig.type) {
330
+ if ((collectionConfig == null ? void 0 : collectionConfig.type) && collection.type !== "unknown" && collection.type !== collectionConfig.type) {
331
331
  viteServer.ws.send({
332
332
  type: "error",
333
333
  err: new AstroError({
@@ -346,7 +346,12 @@ async function writeContentFiles({
346
346
  });
347
347
  return;
348
348
  }
349
- switch (collection.type) {
349
+ const resolvedType = collection.type === "unknown" ? (
350
+ // Add empty / unknown collections to the data type map by default
351
+ // This ensures `getCollection('empty-collection')` doesn't raise a type error
352
+ (collectionConfig == null ? void 0 : collectionConfig.type) ?? "data"
353
+ ) : collection.type;
354
+ switch (resolvedType) {
350
355
  case "content":
351
356
  contentTypesStr += `${collectionKey}: {
352
357
  `;
@@ -370,7 +375,6 @@ async function writeContentFiles({
370
375
  `;
371
376
  break;
372
377
  case "data":
373
- case "unknown":
374
378
  dataTypesStr += `${collectionKey}: {
375
379
  `;
376
380
  for (const entryKey of Object.keys(collection.entries).sort()) {
@@ -4,7 +4,7 @@ import fsMod from 'node:fs';
4
4
  import type { PluginContext } from 'rollup';
5
5
  import { type ViteDevServer } from 'vite';
6
6
  import { z } from 'zod';
7
- import type { AstroConfig, AstroSettings, ContentEntryType } from '../@types/astro.js';
7
+ import type { AstroConfig, AstroSettings, ContentEntryType, DataEntryType } from '../@types/astro.js';
8
8
  import { CONTENT_FLAGS } from './consts.js';
9
9
  /**
10
10
  * Amap from a collection + slug to the local file path.
@@ -102,7 +102,7 @@ export declare function getEntryData(entry: {
102
102
  }, collectionConfig: CollectionConfig, pluginContext: PluginContext, config: AstroConfig): Promise<any>;
103
103
  export declare function getContentEntryExts(settings: Pick<AstroSettings, 'contentEntryTypes'>): string[];
104
104
  export declare function getDataEntryExts(settings: Pick<AstroSettings, 'dataEntryTypes'>): string[];
105
- export declare function getContentEntryConfigByExtMap(settings: Pick<AstroSettings, 'contentEntryTypes'>): Map<string, ContentEntryType>;
105
+ export declare function getEntryConfigByExtMap<TEntryType extends ContentEntryType | DataEntryType>(entryTypes: TEntryType[]): Map<string, TEntryType>;
106
106
  export declare function getEntryCollectionName({ contentDir, entry, }: Pick<ContentPaths, 'contentDir'> & {
107
107
  entry: string | URL;
108
108
  }): string | undefined;
@@ -65,7 +65,7 @@ async function getEntryData(entry, collectionConfig, pluginContext, config) {
65
65
  );
66
66
  }
67
67
  schema = schema({
68
- image: createImage({ config }, pluginContext, entry._internal.filePath)
68
+ image: createImage(pluginContext, entry._internal.filePath)
69
69
  });
70
70
  }
71
71
  if (schema) {
@@ -114,9 +114,9 @@ function getContentEntryExts(settings) {
114
114
  function getDataEntryExts(settings) {
115
115
  return settings.dataEntryTypes.map((t) => t.extensions).flat();
116
116
  }
117
- function getContentEntryConfigByExtMap(settings) {
117
+ function getEntryConfigByExtMap(entryTypes) {
118
118
  const map = /* @__PURE__ */ new Map();
119
- for (const entryType of settings.contentEntryTypes) {
119
+ for (const entryType of entryTypes) {
120
120
  for (const ext of entryType.extensions) {
121
121
  map.set(ext, entryType);
122
122
  }
@@ -340,7 +340,6 @@ export {
340
340
  collectionConfigParser,
341
341
  contentConfigParser,
342
342
  contentObservable,
343
- getContentEntryConfigByExtMap,
344
343
  getContentEntryExts,
345
344
  getContentEntryIdAndSlug,
346
345
  getContentPaths,
@@ -348,6 +347,7 @@ export {
348
347
  getDataEntryId,
349
348
  getDotAstroTypeReference,
350
349
  getEntryCollectionName,
350
+ getEntryConfigByExtMap,
351
351
  getEntryData,
352
352
  getEntrySlug,
353
353
  getEntryType,
@@ -3,16 +3,16 @@ import { extname } from "node:path";
3
3
  import { pathToFileURL } from "url";
4
4
  import { AstroErrorData } from "../core/errors/errors-data.js";
5
5
  import { AstroError } from "../core/errors/errors.js";
6
- import { escapeViteEnvReferences, getFileInfo } from "../vite-plugin-utils/index.js";
6
+ import { escapeViteEnvReferences } from "../vite-plugin-utils/index.js";
7
7
  import { CONTENT_FLAG, DATA_FLAG } from "./consts.js";
8
8
  import {
9
- getContentEntryConfigByExtMap,
10
9
  getContentEntryExts,
11
10
  getContentEntryIdAndSlug,
12
11
  getContentPaths,
13
12
  getDataEntryExts,
14
13
  getDataEntryId,
15
14
  getEntryCollectionName,
15
+ getEntryConfigByExtMap,
16
16
  getEntryData,
17
17
  getEntryType,
18
18
  globalContentConfigObserver,
@@ -40,13 +40,9 @@ function astroContentImportPlugin({
40
40
  const contentPaths = getContentPaths(settings.config, fs);
41
41
  const contentEntryExts = getContentEntryExts(settings);
42
42
  const dataEntryExts = getDataEntryExts(settings);
43
- const contentEntryConfigByExt = getContentEntryConfigByExtMap(settings);
44
- const dataEntryExtToParser = /* @__PURE__ */ new Map();
45
- for (const entryType of settings.dataEntryTypes) {
46
- for (const ext of entryType.extensions) {
47
- dataEntryExtToParser.set(ext, entryType.getEntryInfo);
48
- }
49
- }
43
+ const contentEntryConfigByExt = getEntryConfigByExtMap(settings.contentEntryTypes);
44
+ const dataEntryConfigByExt = getEntryConfigByExtMap(settings.dataEntryTypes);
45
+ const { contentDir } = contentPaths;
50
46
  const plugins = [
51
47
  {
52
48
  name: "astro:content-imports",
@@ -55,9 +51,9 @@ function astroContentImportPlugin({
55
51
  const fileId = viteId.split("?")[0] ?? viteId;
56
52
  const { id, data, collection, _internal } = await getDataEntryModule({
57
53
  fileId,
58
- dataEntryExtToParser,
59
- contentPaths,
60
- settings,
54
+ entryConfigByExt: dataEntryConfigByExt,
55
+ contentDir,
56
+ config: settings.config,
61
57
  fs,
62
58
  pluginContext: this
63
59
  });
@@ -74,8 +70,12 @@ export const _internal = {
74
70
  return code;
75
71
  } else if (hasContentFlag(viteId, CONTENT_FLAG)) {
76
72
  const fileId = viteId.split("?")[0];
77
- const { id, slug, collection, body, data, _internal } = await setContentEntryModuleCache({
73
+ const { id, slug, collection, body, data, _internal } = await getContentEntryModule({
78
74
  fileId,
75
+ entryConfigByExt: contentEntryConfigByExt,
76
+ contentDir,
77
+ config: settings.config,
78
+ fs,
79
79
  pluginContext: this
80
80
  });
81
81
  const code = escapeViteEnvReferences(`
@@ -123,103 +123,115 @@ export const _internal = {
123
123
  if (settings.contentEntryTypes.some((t) => t.getRenderModule)) {
124
124
  plugins.push({
125
125
  name: "astro:content-render-imports",
126
- async transform(_, viteId) {
126
+ async transform(contents, viteId) {
127
127
  const contentRenderer = getContentRendererByViteId(viteId, settings);
128
128
  if (!contentRenderer)
129
129
  return;
130
- const { fileId } = getFileInfo(viteId, settings.config);
131
- const entry = await getContentEntryModuleFromCache(fileId);
132
- if (!entry) {
133
- throw new AstroError({
134
- ...AstroErrorData.UnknownContentCollectionError,
135
- message: `Unable to render ${JSON.stringify(
136
- fileId
137
- )}. Did you import this module directly without using a content collection query?`
138
- });
139
- }
140
- return contentRenderer.bind(this)({ entry, viteId });
130
+ const fileId = viteId.split("?")[0];
131
+ return contentRenderer.bind(this)({ viteId, contents, fileUrl: pathToFileURL(fileId) });
141
132
  }
142
133
  });
143
134
  }
144
- const contentEntryModuleByIdCache = /* @__PURE__ */ new Map();
145
- function isAwaitingQueue(cacheEntry) {
146
- return typeof cacheEntry === "object" && cacheEntry != null && "awaitingQueue" in cacheEntry;
147
- }
148
- function getContentEntryModuleFromCache(id) {
149
- const cacheEntry = contentEntryModuleByIdCache.get(id);
150
- if (isAwaitingQueue(cacheEntry)) {
151
- return new Promise((resolve, reject) => {
152
- cacheEntry.awaitingQueue.push(resolve);
153
- });
154
- } else if (cacheEntry) {
155
- return Promise.resolve(cacheEntry);
156
- }
157
- return Promise.resolve(void 0);
158
- }
159
- async function setContentEntryModuleCache({
160
- fileId,
161
- pluginContext
162
- }) {
163
- contentEntryModuleByIdCache.set(fileId, { awaitingQueue: [] });
164
- const contentConfig = await getContentConfigFromGlobal();
165
- const rawContents = await fs.promises.readFile(fileId, "utf-8");
166
- const fileExt = extname(fileId);
167
- if (!contentEntryConfigByExt.has(fileExt)) {
168
- throw new AstroError({
169
- ...AstroErrorData.UnknownContentCollectionError,
170
- message: `No parser found for content entry ${JSON.stringify(
171
- fileId
172
- )}. Did you apply an integration for this file type?`
173
- });
174
- }
175
- const contentEntryConfig = contentEntryConfigByExt.get(fileExt);
176
- const {
177
- rawData,
178
- body,
179
- slug: frontmatterSlug,
180
- data: unvalidatedData
181
- } = await contentEntryConfig.getEntryInfo({
182
- fileUrl: pathToFileURL(fileId),
183
- contents: rawContents
135
+ return plugins;
136
+ }
137
+ async function getContentEntryModule(params) {
138
+ const { fileId, contentDir, pluginContext, config } = params;
139
+ const { collectionConfig, entryConfig, entry, rawContents, collection } = await getEntryModuleBaseInfo(params);
140
+ const {
141
+ rawData,
142
+ data: unvalidatedData,
143
+ body,
144
+ slug: frontmatterSlug
145
+ } = await entryConfig.getEntryInfo({
146
+ fileUrl: pathToFileURL(fileId),
147
+ contents: rawContents
148
+ });
149
+ const _internal = { filePath: fileId, rawData };
150
+ const { id, slug: generatedSlug } = getContentEntryIdAndSlug({ entry, contentDir, collection });
151
+ const slug = parseEntrySlug({
152
+ id,
153
+ collection,
154
+ generatedSlug,
155
+ frontmatterSlug
156
+ });
157
+ const data = collectionConfig ? await getEntryData(
158
+ { id, collection, _internal, unvalidatedData },
159
+ collectionConfig,
160
+ pluginContext,
161
+ config
162
+ ) : unvalidatedData;
163
+ const contentEntryModule = {
164
+ id,
165
+ slug,
166
+ collection,
167
+ data,
168
+ body,
169
+ _internal
170
+ };
171
+ return contentEntryModule;
172
+ }
173
+ async function getDataEntryModule(params) {
174
+ const { fileId, contentDir, pluginContext, config } = params;
175
+ const { collectionConfig, entryConfig, entry, rawContents, collection } = await getEntryModuleBaseInfo(params);
176
+ const { rawData = "", data: unvalidatedData } = await entryConfig.getEntryInfo({
177
+ fileUrl: pathToFileURL(fileId),
178
+ contents: rawContents
179
+ });
180
+ const _internal = { filePath: fileId, rawData };
181
+ const id = getDataEntryId({ entry, contentDir, collection });
182
+ const data = collectionConfig ? await getEntryData(
183
+ { id, collection, _internal, unvalidatedData },
184
+ collectionConfig,
185
+ pluginContext,
186
+ config
187
+ ) : unvalidatedData;
188
+ const dataEntryModule = {
189
+ id,
190
+ collection,
191
+ data,
192
+ _internal
193
+ };
194
+ return dataEntryModule;
195
+ }
196
+ async function getEntryModuleBaseInfo({
197
+ fileId,
198
+ entryConfigByExt,
199
+ contentDir,
200
+ fs
201
+ }) {
202
+ const contentConfig = await getContentConfigFromGlobal();
203
+ let rawContents;
204
+ try {
205
+ rawContents = await fs.promises.readFile(fileId, "utf-8");
206
+ } catch (e) {
207
+ throw new AstroError({
208
+ ...AstroErrorData.UnknownContentCollectionError,
209
+ message: `Unexpected error reading entry ${JSON.stringify(fileId)}.`,
210
+ stack: e instanceof Error ? e.stack : void 0
184
211
  });
185
- const entry = pathToFileURL(fileId);
186
- const { contentDir } = contentPaths;
187
- const collection = getEntryCollectionName({ entry, contentDir });
188
- if (collection === void 0)
189
- throw new AstroError(AstroErrorData.UnknownContentCollectionError);
190
- const { id, slug: generatedSlug } = getContentEntryIdAndSlug({ entry, contentDir, collection });
191
- const _internal = { filePath: fileId, rawData };
192
- const slug = parseEntrySlug({
193
- id,
194
- collection,
195
- generatedSlug,
196
- frontmatterSlug
212
+ }
213
+ const fileExt = extname(fileId);
214
+ const entryConfig = entryConfigByExt.get(fileExt);
215
+ if (!entryConfig) {
216
+ throw new AstroError({
217
+ ...AstroErrorData.UnknownContentCollectionError,
218
+ message: `No parser found for data entry ${JSON.stringify(
219
+ fileId
220
+ )}. Did you apply an integration for this file type?`
197
221
  });
198
- const collectionConfig = contentConfig == null ? void 0 : contentConfig.collections[collection];
199
- let data = collectionConfig ? await getEntryData(
200
- { id, collection, _internal, unvalidatedData },
201
- collectionConfig,
202
- pluginContext,
203
- settings.config
204
- ) : unvalidatedData;
205
- const contentEntryModule = {
206
- id,
207
- slug,
208
- collection,
209
- data,
210
- body,
211
- _internal
212
- };
213
- const cacheEntry = contentEntryModuleByIdCache.get(fileId);
214
- if (isAwaitingQueue(cacheEntry)) {
215
- for (const resolve of cacheEntry.awaitingQueue) {
216
- resolve(contentEntryModule);
217
- }
218
- }
219
- contentEntryModuleByIdCache.set(fileId, contentEntryModule);
220
- return contentEntryModule;
221
222
  }
222
- return plugins;
223
+ const entry = pathToFileURL(fileId);
224
+ const collection = getEntryCollectionName({ entry, contentDir });
225
+ if (collection === void 0)
226
+ throw new AstroError(AstroErrorData.UnknownContentCollectionError);
227
+ const collectionConfig = contentConfig == null ? void 0 : contentConfig.collections[collection];
228
+ return {
229
+ collectionConfig,
230
+ entry,
231
+ entryConfig,
232
+ collection,
233
+ rawContents
234
+ };
223
235
  }
224
236
  async function getContentConfigFromGlobal() {
225
237
  const observable = globalContentConfigObserver.get();
@@ -249,55 +261,6 @@ async function getContentConfigFromGlobal() {
249
261
  }
250
262
  return contentConfig;
251
263
  }
252
- async function getDataEntryModule({
253
- fileId,
254
- dataEntryExtToParser,
255
- contentPaths,
256
- fs,
257
- pluginContext,
258
- settings
259
- }) {
260
- const contentConfig = await getContentConfigFromGlobal();
261
- let rawContents;
262
- try {
263
- rawContents = await fs.promises.readFile(fileId, "utf-8");
264
- } catch (e) {
265
- throw new AstroError({
266
- ...AstroErrorData.UnknownContentCollectionError,
267
- message: `Unexpected error reading entry ${JSON.stringify(fileId)}.`,
268
- stack: e instanceof Error ? e.stack : void 0
269
- });
270
- }
271
- const fileExt = extname(fileId);
272
- const dataEntryParser = dataEntryExtToParser.get(fileExt);
273
- if (!dataEntryParser) {
274
- throw new AstroError({
275
- ...AstroErrorData.UnknownContentCollectionError,
276
- message: `No parser found for data entry ${JSON.stringify(
277
- fileId
278
- )}. Did you apply an integration for this file type?`
279
- });
280
- }
281
- const { data: unvalidatedData, rawData = "" } = await dataEntryParser({
282
- fileUrl: pathToFileURL(fileId),
283
- contents: rawContents
284
- });
285
- const entry = pathToFileURL(fileId);
286
- const { contentDir } = contentPaths;
287
- const collection = getEntryCollectionName({ entry, contentDir });
288
- if (collection === void 0)
289
- throw new AstroError(AstroErrorData.UnknownContentCollectionError);
290
- const id = getDataEntryId({ entry, contentDir, collection });
291
- const _internal = { filePath: fileId, rawData };
292
- const collectionConfig = contentConfig == null ? void 0 : contentConfig.collections[collection];
293
- const data = collectionConfig ? await getEntryData(
294
- { id, collection, _internal, unvalidatedData },
295
- collectionConfig,
296
- pluginContext,
297
- settings.config
298
- ) : unvalidatedData;
299
- return { id, collection, data, _internal };
300
- }
301
264
  export {
302
265
  astroContentImportPlugin
303
266
  };
@@ -1,8 +1,8 @@
1
1
  /// <reference types="node" />
2
2
  import fsMod from 'node:fs';
3
3
  import type { Plugin } from 'vite';
4
- import type { AstroSettings } from '../@types/astro.js';
5
- import { getContentEntryConfigByExtMap, type ContentPaths } from './utils.js';
4
+ import type { AstroSettings, ContentEntryType } from '../@types/astro.js';
5
+ import { type ContentPaths } from './utils.js';
6
6
  interface AstroContentVirtualModPluginParams {
7
7
  settings: AstroSettings;
8
8
  }
@@ -13,7 +13,7 @@ export declare function astroContentVirtualModPlugin({ settings, }: AstroContent
13
13
  * @see `src/content/virtual-mod.mjs`
14
14
  */
15
15
  export declare function getStringifiedLookupMap({ contentPaths, contentEntryConfigByExt, dataEntryExts, root, fs, }: {
16
- contentEntryConfigByExt: ReturnType<typeof getContentEntryConfigByExtMap>;
16
+ contentEntryConfigByExt: Map<string, ContentEntryType>;
17
17
  dataEntryExts: string[];
18
18
  contentPaths: Pick<ContentPaths, 'contentDir' | 'config'>;
19
19
  root: URL;
@@ -7,12 +7,12 @@ import { AstroError, AstroErrorData } from "../core/errors/index.js";
7
7
  import { rootRelativePath } from "../core/util.js";
8
8
  import { VIRTUAL_MODULE_ID } from "./consts.js";
9
9
  import {
10
- getContentEntryConfigByExtMap,
11
10
  getContentEntryIdAndSlug,
12
11
  getContentPaths,
13
12
  getDataEntryExts,
14
13
  getDataEntryId,
15
14
  getEntryCollectionName,
15
+ getEntryConfigByExtMap,
16
16
  getEntrySlug,
17
17
  getEntryType,
18
18
  getExtGlob
@@ -22,13 +22,17 @@ function astroContentVirtualModPlugin({
22
22
  }) {
23
23
  const contentPaths = getContentPaths(settings.config);
24
24
  const relContentDir = rootRelativePath(settings.config.root, contentPaths.contentDir);
25
- const contentEntryConfigByExt = getContentEntryConfigByExtMap(settings);
25
+ const contentEntryConfigByExt = getEntryConfigByExtMap(settings.contentEntryTypes);
26
26
  const contentEntryExts = [...contentEntryConfigByExt.keys()];
27
27
  const dataEntryExts = getDataEntryExts(settings);
28
28
  const virtualModContents = fsMod.readFileSync(contentPaths.virtualModTemplate, "utf-8").replace(
29
29
  "@@COLLECTION_NAME_BY_REFERENCE_KEY@@",
30
30
  new URL("reference-map.json", contentPaths.cacheDir).pathname
31
- ).replace("@@CONTENT_DIR@@", relContentDir).replace("@@CONTENT_ENTRY_GLOB_PATH@@", `${relContentDir}**/*${getExtGlob(contentEntryExts)}`).replace("@@DATA_ENTRY_GLOB_PATH@@", `${relContentDir}**/*${getExtGlob(dataEntryExts)}`).replace(
31
+ ).replace("@@CONTENT_DIR@@", relContentDir).replace(
32
+ "@@CONTENT_ENTRY_GLOB_PATH@@",
33
+ // [!_] = ignore files starting with "_"
34
+ `${relContentDir}**/[!_]*${getExtGlob(contentEntryExts)}`
35
+ ).replace("@@DATA_ENTRY_GLOB_PATH@@", `${relContentDir}**/[!_]*${getExtGlob(dataEntryExts)}`).replace(
32
36
  "@@RENDER_ENTRY_GLOB_PATH@@",
33
37
  `${relContentDir}**/*${getExtGlob(
34
38
  /** Note: data collections excluded */
@@ -1,8 +1,6 @@
1
1
  import type { RouteData } from '../../@types/astro';
2
2
  import type { SSRManifest as Manifest } from './types';
3
3
  export { deserializeManifest } from './common.js';
4
- export declare const pagesVirtualModuleId = "@astrojs-pages-virtual-entry";
5
- export declare const resolvedPagesVirtualModuleId: string;
6
4
  export interface MatchOptions {
7
5
  matchNotFound?: boolean | undefined;
8
6
  }