fix(plugin-seo): allow number ids & resolved relations for image auto-generation (#13906)

### What?

- The SEO plugin's `generateImage` type now also allows returning
`number` in addition to `string` and objects with an `id` property of
the same.

### Why?

`generateImage` can't be used as specified in [the
docs](https://payloadcms.com/docs/plugins/seo#generateimage) if it's
fully typed using Payload-generated collection types. Typechecking only
works because of the fallback `any` type.

This function seems to assume that the setup works with string-based
IDs. This is not necessarily the case for SQL-like databases like
Postgres.

If I fully type the `args` and consequently the return type using the
types Payload generates for me in my setup (which has `number` ids),
then the type signature of my `generateImage` doesn't conform to what
the plugin expects and typechecking fails.

Additionally, Payload's generated types for relation fields are an
ID-object union because it can't know how relations are resolved in
every context. I believe this to be the correct choice.

But it means that `generateImage` might possibly return a media object
(based on the types alone) which would break the functionality. It's
therefore safest to allow this and handle it in the UI, like [it is
already being done in the upload field's `onChange`
handler](39143c9d12/packages/plugin-seo/src/fields/MetaImage/MetaImageComponent.tsx (L183)).

### How?

By
- [widening `GenerateImage`'s return type to allow for a more diverse
set of
configurations](a0ea58d81d (diff-bad1e1b58992c48178ea7d0dfa546f66bfa6e10eed2dd3db5c74e092824fa7ffL58))
- [handling objects in the UI
component](a0ea58d81d)

Fixes #13905
This commit is contained in:
aptt
2025-09-24 21:51:00 +02:00
committed by GitHub
parent 9a59562cd5
commit abbe38fbaf
2 changed files with 11 additions and 3 deletions

View File

@@ -49,7 +49,7 @@ export const MetaImageComponent: React.FC<MetaImageProps> = (props) => {
setValue, setValue,
showError, showError,
value, value,
}: FieldType<string> = useField() }: FieldType<number | string> = useField()
const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>() const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()
@@ -92,7 +92,15 @@ export const MetaImageComponent: React.FC<MetaImageProps> = (props) => {
const { result: generatedImage } = await genImageResponse.json() const { result: generatedImage } = await genImageResponse.json()
setValue(generatedImage || '') // string ids, number ids or nullish values
let newValue: null | number | string | undefined = generatedImage
// non-nullish resolved relations
if (typeof generatedImage === 'object' && generatedImage && 'id' in generatedImage) {
newValue = generatedImage.id
}
// coerce to an empty string for falsy (=empty) values
setValue(newValue || '')
}, [ }, [
hasGenerateImageFn, hasGenerateImageFn,
serverURL, serverURL,

View File

@@ -55,7 +55,7 @@ export type GenerateImage<T = any> = (
locale?: string locale?: string
req: PayloadRequest req: PayloadRequest
} & PartialDocumentInfoContext, } & PartialDocumentInfoContext,
) => Promise<string> | string ) => { id: number | string } | number | Promise<{ id: number | string } | number | string> | string
export type GenerateURL<T = any> = ( export type GenerateURL<T = any> = (
args: { args: {