astro 2.6.2 → 2.6.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.
@@ -399,7 +399,7 @@ export interface AstroUserConfig {
399
399
  /**
400
400
  * @docs
401
401
  * @name redirects (Experimental)
402
- * @type {RedirectConfig}
402
+ * @type {Record<string, RedirectConfig>}
403
403
  * @default `{}`
404
404
  * @version 2.6.0
405
405
  * @description Specify a mapping of redirects where the key is the route to match
@@ -439,7 +439,7 @@ export interface AstroUserConfig {
439
439
  * }
440
440
  * ```
441
441
  */
442
- redirects?: RedirectConfig;
442
+ redirects?: Record<string, RedirectConfig>;
443
443
  /**
444
444
  * @docs
445
445
  * @name site
@@ -60,7 +60,7 @@ function astroContentImportPlugin({
60
60
  const code = escapeViteEnvReferences(`
61
61
  export const id = ${JSON.stringify(id)};
62
62
  export const collection = ${JSON.stringify(collection)};
63
- export const data = ${devalue.uneval(data)};
63
+ export const data = ${stringifyEntryData(data)};
64
64
  export const _internal = {
65
65
  type: 'data',
66
66
  filePath: ${JSON.stringify(_internal.filePath)},
@@ -83,7 +83,7 @@ export const _internal = {
83
83
  export const collection = ${JSON.stringify(collection)};
84
84
  export const slug = ${JSON.stringify(slug)};
85
85
  export const body = ${JSON.stringify(body)};
86
- export const data = ${devalue.uneval(data)};
86
+ export const data = ${stringifyEntryData(data)};
87
87
  export const _internal = {
88
88
  type: 'content',
89
89
  filePath: ${JSON.stringify(_internal.filePath)},
@@ -261,6 +261,28 @@ async function getContentConfigFromGlobal() {
261
261
  }
262
262
  return contentConfig;
263
263
  }
264
+ function stringifyEntryData(data) {
265
+ try {
266
+ return devalue.uneval(data, (value) => {
267
+ if (value instanceof URL) {
268
+ return `new URL(${JSON.stringify(value.href)})`;
269
+ }
270
+ });
271
+ } catch (e) {
272
+ if (e instanceof Error) {
273
+ throw new AstroError({
274
+ ...AstroErrorData.UnsupportedConfigTransformError,
275
+ message: AstroErrorData.UnsupportedConfigTransformError.message(e.message),
276
+ stack: e.stack
277
+ });
278
+ } else {
279
+ throw new AstroError({
280
+ code: 99999,
281
+ message: "Unexpected error processing content collection data."
282
+ });
283
+ }
284
+ }
285
+ }
264
286
  export {
265
287
  astroContentImportPlugin
266
288
  };
@@ -98,7 +98,7 @@ async function getStringifiedLookupMap({
98
98
  for (const filePath of contentGlob) {
99
99
  promises.push(
100
100
  limit(async () => {
101
- var _a, _b, _c;
101
+ var _a, _b, _c, _d, _e;
102
102
  const entryType = getEntryType(filePath, contentPaths, contentEntryExts, dataEntryExts);
103
103
  if (entryType !== "content" && entryType !== "data")
104
104
  return;
@@ -128,10 +128,17 @@ async function getStringifiedLookupMap({
128
128
  fileUrl: pathToFileURL(filePath),
129
129
  contentEntryType
130
130
  });
131
+ if ((_c = (_b = lookupMap[collection]) == null ? void 0 : _b.entries) == null ? void 0 : _c[slug]) {
132
+ throw new AstroError({
133
+ ...AstroErrorData.DuplicateContentEntrySlugError,
134
+ message: AstroErrorData.DuplicateContentEntrySlugError.message(collection, slug),
135
+ hint: slug !== generatedSlug ? `Check the \`slug\` frontmatter property in **${id}**.` : void 0
136
+ });
137
+ }
131
138
  lookupMap[collection] = {
132
139
  type: "content",
133
140
  entries: {
134
- ...(_b = lookupMap[collection]) == null ? void 0 : _b.entries,
141
+ ...(_d = lookupMap[collection]) == null ? void 0 : _d.entries,
135
142
  [slug]: rootRelativePath(root, filePath)
136
143
  }
137
144
  };
@@ -140,7 +147,7 @@ async function getStringifiedLookupMap({
140
147
  lookupMap[collection] = {
141
148
  type: "data",
142
149
  entries: {
143
- ...(_c = lookupMap[collection]) == null ? void 0 : _c.entries,
150
+ ...(_e = lookupMap[collection]) == null ? void 0 : _e.entries,
144
151
  [id]: rootRelativePath(root, filePath)
145
152
  }
146
153
  };
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "2.6.2";
1
+ const ASTRO_VERSION = "2.6.4";
2
2
  const SUPPORTED_MARKDOWN_FILE_EXTENSIONS = [
3
3
  ".markdown",
4
4
  ".mdown",
@@ -53,7 +53,7 @@ async function dev(settings, options) {
53
53
  isRestart: options.isRestart
54
54
  })
55
55
  );
56
- const currentVersion = "2.6.2";
56
+ const currentVersion = "2.6.4";
57
57
  if (currentVersion.includes("-")) {
58
58
  warn(options.logging, null, msg.prerelease({ currentVersion }));
59
59
  }
@@ -11,10 +11,14 @@ import { codeFrame } from "../printer.js";
11
11
  import { normalizeLF } from "../utils.js";
12
12
  function collectErrorMetadata(e, rootFolder) {
13
13
  const err = AggregateError.is(e) || Array.isArray(e.errors) ? e.errors : [e];
14
- err.forEach((error) => {
14
+ err.forEach((error, idx) => {
15
15
  var _a, _b;
16
- if (error.stack) {
17
- error = collectInfoFromStacktrace(e);
16
+ if (e.stack) {
17
+ const stackInfo = collectInfoFromStacktrace(e);
18
+ error.stack = stackInfo.stack;
19
+ error.loc = stackInfo.loc;
20
+ error.plugin = stackInfo.plugin;
21
+ error.pluginCode = stackInfo.pluginCode;
18
22
  }
19
23
  const normalizedFile = normalizePath(((_a = error.loc) == null ? void 0 : _a.file) || "");
20
24
  const normalizedRootFolder = removeLeadingForwardSlashWindows((rootFolder == null ? void 0 : rootFolder.pathname) || "");
@@ -91,11 +95,15 @@ See https://docs.astro.build/en/guides/troubleshooting/#document-or-window-is-no
91
95
  }
92
96
  function collectInfoFromStacktrace(error) {
93
97
  var _a, _b, _c;
94
- if (!error.stack)
95
- return error;
96
- error.stack = normalizeLF(error.stack);
98
+ let stackInfo = {
99
+ stack: error.stack,
100
+ plugin: error.plugin,
101
+ pluginCode: error.pluginCode,
102
+ loc: error.loc
103
+ };
104
+ stackInfo.stack = normalizeLF(error.stack);
97
105
  const stackText = stripAnsi(error.stack);
98
- if (!error.loc || !error.loc.column && !error.loc.line) {
106
+ if (!stackInfo.loc || !stackInfo.loc.column && !stackInfo.loc.line) {
99
107
  const possibleFilePath = ((_a = error.loc) == null ? void 0 : _a.file) || error.pluginCode || error.id || // TODO: this could be better, `src` might be something else
100
108
  stackText.split("\n").find((ln) => ln.includes("src") || ln.includes("node_modules"));
101
109
  const source = possibleFilePath == null ? void 0 : possibleFilePath.replace(/^[^(]+\(([^)]+).*$/, "$1").replace(/^\s+at\s+/, "");
@@ -108,18 +116,18 @@ function collectInfoFromStacktrace(error) {
108
116
  file = fileURLToPath(file);
109
117
  } catch {
110
118
  }
111
- error.loc = {
119
+ stackInfo.loc = {
112
120
  file,
113
121
  line: Number.parseInt(line),
114
122
  column: Number.parseInt(column)
115
123
  };
116
124
  }
117
125
  }
118
- if (!error.plugin) {
119
- error.plugin = ((_b = /withastro\/astro\/packages\/integrations\/([\w-]+)/gim.exec(stackText)) == null ? void 0 : _b.at(1)) || ((_c = /(@astrojs\/[\w-]+)\/(server|client|index)/gim.exec(stackText)) == null ? void 0 : _c.at(1)) || void 0;
126
+ if (!stackInfo.plugin) {
127
+ stackInfo.plugin = ((_b = /withastro\/astro\/packages\/integrations\/([\w-]+)/gim.exec(stackText)) == null ? void 0 : _b.at(1)) || ((_c = /(@astrojs\/[\w-]+)\/(server|client|index)/gim.exec(stackText)) == null ? void 0 : _c.at(1)) || void 0;
120
128
  }
121
- error.stack = cleanErrorStack(error.stack);
122
- return error;
129
+ stackInfo.stack = cleanErrorStack(error.stack);
130
+ return stackInfo;
123
131
  }
124
132
  function cleanErrorStack(stack) {
125
133
  return stack.split(/\n/g).map((l) => l.replace(/\/@fs\//g, "/")).join("\n");
@@ -974,6 +974,30 @@ export declare const AstroErrorData: {
974
974
  readonly message: (entryId: string, errorMessage: string) => string;
975
975
  readonly hint: "Ensure your data entry is an object with valid JSON (for `.json` entries) or YAML (for `.yaml` entries).";
976
976
  };
977
+ /**
978
+ * @docs
979
+ * @message `COLLECTION_NAME` contains multiple entries with the same slug: `SLUG`. Slugs must be unique.
980
+ * @description
981
+ * Content collection entries must have unique slugs. Duplicates are often caused by the `slug` frontmatter property.
982
+ */
983
+ readonly DuplicateContentEntrySlugError: {
984
+ readonly title: "Duplicate content entry slug.";
985
+ readonly code: 9008;
986
+ readonly message: (collection: string, slug: string) => string;
987
+ };
988
+ /**
989
+ * @docs
990
+ * @see
991
+ * - [devalue library](https://github.com/rich-harris/devalue)
992
+ * @description
993
+ * `transform()` functions in your content config must return valid JSON, or data types compatible with the devalue library (including Dates, Maps, and Sets).
994
+ */
995
+ readonly UnsupportedConfigTransformError: {
996
+ readonly title: "Unsupported transform in content config.";
997
+ readonly code: 9008;
998
+ readonly message: (parseError: string) => string;
999
+ readonly hint: "See the devalue library for all supported types: https://github.com/rich-harris/devalue";
1000
+ };
977
1001
  readonly UnknownError: {
978
1002
  readonly title: "Unknown Error.";
979
1003
  readonly code: 99999;
@@ -1032,6 +1032,33 @@ Expected \`${defaultExpectedValue}\` value but got \`${suffix}\`.`;
1032
1032
  },
1033
1033
  hint: "Ensure your data entry is an object with valid JSON (for `.json` entries) or YAML (for `.yaml` entries)."
1034
1034
  },
1035
+ /**
1036
+ * @docs
1037
+ * @message `COLLECTION_NAME` contains multiple entries with the same slug: `SLUG`. Slugs must be unique.
1038
+ * @description
1039
+ * Content collection entries must have unique slugs. Duplicates are often caused by the `slug` frontmatter property.
1040
+ */
1041
+ DuplicateContentEntrySlugError: {
1042
+ title: "Duplicate content entry slug.",
1043
+ code: 9008,
1044
+ message: (collection, slug) => {
1045
+ return `**${collection}** contains multiple entries with the same slug: \`${slug}\`. Slugs must be unique.`;
1046
+ }
1047
+ },
1048
+ /**
1049
+ * @docs
1050
+ * @see
1051
+ * - [devalue library](https://github.com/rich-harris/devalue)
1052
+ * @description
1053
+ * `transform()` functions in your content config must return valid JSON, or data types compatible with the devalue library (including Dates, Maps, and Sets).
1054
+ */
1055
+ UnsupportedConfigTransformError: {
1056
+ title: "Unsupported transform in content config.",
1057
+ code: 9008,
1058
+ message: (parseError) => `\`transform()\` functions in your content config must return valid JSON, or data types compatible with the devalue library (including Dates, Maps, and Sets).
1059
+ Full error: ${parseError}`,
1060
+ hint: "See the devalue library for all supported types: https://github.com/rich-harris/devalue"
1061
+ },
1035
1062
  // Generic catch-all - Only use this in extreme cases, like if there was a cosmic ray bit flip
1036
1063
  UnknownError: {
1037
1064
  title: "Unknown Error.",
@@ -47,7 +47,7 @@ function serverStart({
47
47
  base,
48
48
  isRestart = false
49
49
  }) {
50
- const version = "2.6.2";
50
+ const version = "2.6.4";
51
51
  const localPrefix = `${dim("\u2503")} Local `;
52
52
  const networkPrefix = `${dim("\u2503")} Network `;
53
53
  const emptyPrefix = " ".repeat(11);
@@ -233,7 +233,7 @@ function printHelp({
233
233
  message.push(
234
234
  linebreak(),
235
235
  ` ${bgGreen(black(` ${commandName} `))} ${green(
236
- `v${"2.6.2"}`
236
+ `v${"2.6.4"}`
237
237
  )} ${headline}`
238
238
  );
239
239
  }
@@ -13,6 +13,16 @@ async function check(Component, props, { default: children = null, ...slotted }
13
13
  const result = await Component({ ...props, ...slots, children });
14
14
  return result[AstroJSX];
15
15
  } catch (e) {
16
+ const error = e;
17
+ if (Component[Symbol.for("mdx-component")]) {
18
+ throw createFormattedError({
19
+ message: error.message,
20
+ title: error.name,
21
+ hint: `This issue often occurs when your MDX component encounters runtime errors.`,
22
+ name: error.name,
23
+ stack: error.stack
24
+ });
25
+ }
16
26
  }
17
27
  return false;
18
28
  }
@@ -26,6 +36,13 @@ async function renderToStaticMarkup(Component, props = {}, { default: children =
26
36
  const html = await renderJSX(result, jsx(Component, { ...props, ...slots, children }));
27
37
  return { html };
28
38
  }
39
+ function createFormattedError({ message, name, stack, hint }) {
40
+ const error = new Error(message);
41
+ error.name = name;
42
+ error.stack = stack;
43
+ error.hint = hint;
44
+ return error;
45
+ }
29
46
  var server_default = {
30
47
  check,
31
48
  renderToStaticMarkup
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "2.6.2",
3
+ "version": "2.6.4",
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",
@@ -121,7 +121,7 @@
121
121
  "cookie": "^0.5.0",
122
122
  "debug": "^4.3.4",
123
123
  "deepmerge-ts": "^4.2.2",
124
- "devalue": "^4.2.0",
124
+ "devalue": "^4.3.2",
125
125
  "diff": "^5.1.0",
126
126
  "es-module-lexer": "^1.1.0",
127
127
  "esbuild": "^0.17.18",