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 <nate@astro.build>
Co-authored-by: Yan Thomas <61414485+Yan-Thomas@users.noreply.github.com>
This commit is contained in:
Nate Moore 2023-01-30 14:11:54 -06:00 committed by GitHub
parent a36e8fd912
commit 41e97158ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 4 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Improve error handling when an Astro component is rendered manually

View file

@ -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:**<br/>
* InvalidComponentArgs: Invalid arguments passed to <MyAstroComponent> component.
* @description
* Astro components cannot be rendered manually via a function call, such as `Component()` or `{items.map(Component)}`. Prefer the component syntax `<Component />` or `{items.map(item => <Component {...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.',

View file

@ -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<AstroComponentFactory> {
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<AstroComponentFactory>) => {
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 {