Fix: better collection entry devalue error (#7341)

* feat: add clear error for devalue parse

* refactor: create error data entry

* deps: up devalue

* chore: changeset
This commit is contained in:
Ben Holmes 2023-06-09 18:15:11 -04:00 committed by GitHub
parent f4f9524656
commit 491c2db424
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 11 deletions

View file

@ -0,0 +1,6 @@
---
'astro': patch
'@astrojs/markdoc': patch
---
Improve error message for unsupported Zod transforms from the content config.

View file

@ -134,7 +134,7 @@
"cookie": "^0.5.0", "cookie": "^0.5.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"deepmerge-ts": "^4.2.2", "deepmerge-ts": "^4.2.2",
"devalue": "^4.2.0", "devalue": "^4.3.2",
"diff": "^5.1.0", "diff": "^5.1.0",
"es-module-lexer": "^1.1.0", "es-module-lexer": "^1.1.0",
"esbuild": "^0.17.18", "esbuild": "^0.17.18",

View file

@ -94,7 +94,7 @@ export function astroContentImportPlugin({
const code = escapeViteEnvReferences(` const code = escapeViteEnvReferences(`
export const id = ${JSON.stringify(id)}; export const id = ${JSON.stringify(id)};
export const collection = ${JSON.stringify(collection)}; export const collection = ${JSON.stringify(collection)};
export const data = ${devalue.uneval(data) /* TODO: reuse astro props serializer */}; export const data = ${stringifyEntryData(data)};
export const _internal = { export const _internal = {
type: 'data', type: 'data',
filePath: ${JSON.stringify(_internal.filePath)}, filePath: ${JSON.stringify(_internal.filePath)},
@ -118,7 +118,7 @@ export const _internal = {
export const collection = ${JSON.stringify(collection)}; export const collection = ${JSON.stringify(collection)};
export const slug = ${JSON.stringify(slug)}; export const slug = ${JSON.stringify(slug)};
export const body = ${JSON.stringify(body)}; export const body = ${JSON.stringify(body)};
export const data = ${devalue.uneval(data) /* TODO: reuse astro props serializer */}; export const data = ${stringifyEntryData(data)};
export const _internal = { export const _internal = {
type: 'content', type: 'content',
filePath: ${JSON.stringify(_internal.filePath)}, filePath: ${JSON.stringify(_internal.filePath)},
@ -352,3 +352,28 @@ async function getContentConfigFromGlobal() {
return contentConfig; return contentConfig;
} }
/** Stringify entry `data` at build time to be used as a Vite module */
function stringifyEntryData(data: Record<string, any>): string {
try {
return devalue.uneval(data, (value) => {
// Add support for URL objects
if (value instanceof URL) {
return `new URL(${JSON.stringify(value.href)})`;
}
});
} catch (e) {
if (e instanceof Error) {
throw new AstroError({
...AstroErrorData.UnsupportedConfigTransformError,
message: AstroErrorData.UnsupportedConfigTransformError.message(e.message),
stack: e.stack,
});
} else {
throw new AstroError({
code: 99999,
message: 'Unexpected error processing content collection data.',
});
}
}
}

View file

@ -1113,6 +1113,21 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
hint: 'Ensure your data entry is an object with valid JSON (for `.json` entries) or YAML (for `.yaml` entries).', hint: 'Ensure your data entry is an object with valid JSON (for `.json` entries) or YAML (for `.yaml` entries).',
}, },
/**
* @docs
* @see
* - [devalue library](https://github.com/rich-harris/devalue)
* @description
* `transform()` functions in your content config must return valid JSON, or data types compatible with the devalue library (including Dates, Maps, and Sets).
*/
UnsupportedConfigTransformError: {
title: 'Unsupported transform in content config.',
code: 9008,
message: (parseError: string) =>
`\`transform()\` functions in your content config must return valid JSON, or data types compatible with the devalue library (including Dates, Maps, and Sets).\nFull error: ${parseError}`,
hint: 'See the devalue library for all supported types: https://github.com/rich-harris/devalue',
},
// Generic catch-all - Only use this in extreme cases, like if there was a cosmic ray bit flip // Generic catch-all - Only use this in extreme cases, like if there was a cosmic ray bit flip
UnknownError: { UnknownError: {
title: 'Unknown Error.', title: 'Unknown Error.',

View file

@ -63,13 +63,13 @@
"test:match": "mocha --timeout 20000 -g" "test:match": "mocha --timeout 20000 -g"
}, },
"dependencies": { "dependencies": {
"shiki": "^0.14.1",
"@astrojs/prism": "^2.1.2", "@astrojs/prism": "^2.1.2",
"@markdoc/markdoc": "^0.3.0", "@markdoc/markdoc": "^0.3.0",
"esbuild": "^0.17.12", "esbuild": "^0.17.12",
"github-slugger": "^2.0.0", "github-slugger": "^2.0.0",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"kleur": "^4.1.5", "kleur": "^4.1.5",
"shiki": "^0.14.1",
"zod": "^3.17.3" "zod": "^3.17.3"
}, },
"peerDependencies": { "peerDependencies": {
@ -83,7 +83,7 @@
"astro": "workspace:*", "astro": "workspace:*",
"astro-scripts": "workspace:*", "astro-scripts": "workspace:*",
"chai": "^4.3.6", "chai": "^4.3.6",
"devalue": "^4.2.0", "devalue": "^4.3.2",
"linkedom": "^0.14.12", "linkedom": "^0.14.12",
"mocha": "^9.2.2", "mocha": "^9.2.2",
"rollup": "^3.20.1", "rollup": "^3.20.1",

View file

@ -559,8 +559,8 @@ importers:
specifier: ^4.2.2 specifier: ^4.2.2
version: 4.2.2 version: 4.2.2
devalue: devalue:
specifier: ^4.2.0 specifier: ^4.3.2
version: 4.2.0 version: 4.3.2
diff: diff:
specifier: ^5.1.0 specifier: ^5.1.0
version: 5.1.0 version: 5.1.0
@ -3990,8 +3990,8 @@ importers:
specifier: ^4.3.6 specifier: ^4.3.6
version: 4.3.6 version: 4.3.6
devalue: devalue:
specifier: ^4.2.0 specifier: ^4.3.2
version: 4.2.0 version: 4.3.2
linkedom: linkedom:
specifier: ^0.14.12 specifier: ^0.14.12
version: 0.14.17 version: 0.14.17
@ -10870,8 +10870,8 @@ packages:
resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==} resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==}
engines: {node: '>=8'} engines: {node: '>=8'}
/devalue@4.2.0: /devalue@4.3.2:
resolution: {integrity: sha512-mbjoAaCL2qogBKgeFxFPOXAUsZchircF+B/79LD4sHH0+NHfYm8gZpQrskKDn5gENGt35+5OI1GUF7hLVnkPDw==} resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==}
/didyoumean@1.2.2: /didyoumean@1.2.2:
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}