From 41e97158ba90d23d346b6e3ff6c7c14b5ecbe903 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Mon, 30 Jan 2023 14:11:54 -0600 Subject: [PATCH] Handle invalid argument errors (#6045) * fix: add error handling for invalid arguments * chore: add changeset * Update packages/astro/src/core/errors/errors-data.ts Co-authored-by: Yan Thomas <61414485+Yan-Thomas@users.noreply.github.com> --------- Co-authored-by: Nate Moore Co-authored-by: Yan Thomas <61414485+Yan-Thomas@users.noreply.github.com> --- .changeset/happy-fireants-occur.md | 5 ++++ packages/astro/src/core/errors/errors-data.ts | 14 +++++++++++ .../src/runtime/server/astro-component.ts | 25 ++++++++++++++++--- 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 .changeset/happy-fireants-occur.md diff --git a/.changeset/happy-fireants-occur.md b/.changeset/happy-fireants-occur.md new file mode 100644 index 000000000000..40ffcf4c6cf7 --- /dev/null +++ b/.changeset/happy-fireants-occur.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Improve error handling when an Astro component is rendered manually diff --git a/packages/astro/src/core/errors/errors-data.ts b/packages/astro/src/core/errors/errors-data.ts index 0b74ca6752a5..5a2b75cabd2f 100644 --- a/packages/astro/src/core/errors/errors-data.ts +++ b/packages/astro/src/core/errors/errors-data.ts @@ -415,6 +415,20 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati }, hint: 'Mutable values declared at runtime are not supported. Please make sure to use exactly `export const prerender = true`.', }, + /** + * @docs + * @message + * **Example error messages:**
+ * InvalidComponentArgs: Invalid arguments passed to component. + * @description + * Astro components cannot be rendered manually via a function call, such as `Component()` or `{items.map(Component)}`. Prefer the component syntax `` or `{items.map(item => )}`. + */ + InvalidComponentArgs: { + title: 'Invalid component arguments.', + code: 3020, + message: (name: string) => `Invalid arguments passed to${name ? ` <${name}>` : ''} component.`, + hint: 'Astro components cannot be rendered directly via function call, such as `Component()` or `{items.map(Component)}`.', + }, // Vite Errors - 4xxx UnknownViteError: { title: 'Unknown Vite Error.', diff --git a/packages/astro/src/runtime/server/astro-component.ts b/packages/astro/src/runtime/server/astro-component.ts index 933a69a9a67a..975be7054acb 100644 --- a/packages/astro/src/runtime/server/astro-component.ts +++ b/packages/astro/src/runtime/server/astro-component.ts @@ -1,11 +1,28 @@ import type { PropagationHint } from '../../@types/astro'; import type { AstroComponentFactory } from './render/index.js'; +import { AstroError, AstroErrorData } from '../../core/errors/index.js'; -function baseCreateComponent(cb: AstroComponentFactory, moduleId?: string) { +function validateArgs(args: unknown[]): args is Parameters { + if (args.length !== 3) return false; + if (!args[0] ||typeof args[0] !== 'object') return false; + return true; +} +function baseCreateComponent(cb: AstroComponentFactory, moduleId?: string): AstroComponentFactory { + const name = moduleId?.split('/').pop()?.replace('.astro', '') ?? '' + const fn = (...args: Parameters) => { + if (!validateArgs(args)) { + throw new AstroError({ + ...AstroErrorData.InvalidComponentArgs, + message: AstroErrorData.InvalidComponentArgs.message(name), + }); + } + return cb(...args); + } + Object.defineProperty(fn, 'name', { value: name, writable: false }); // Add a flag to this callback to mark it as an Astro component - cb.isAstroComponentFactory = true; - cb.moduleId = moduleId; - return cb; + fn.isAstroComponentFactory = true; + fn.moduleId = moduleId; + return fn; } interface CreateComponentOptions {