From abbe38fbaf6b516a3e5dc4b8e82c547c12272b54 Mon Sep 17 00:00:00 2001 From: aptt <62893352+apttx@users.noreply.github.com> Date: Wed, 24 Sep 2025 21:51:00 +0200 Subject: [PATCH] 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](https://github.com/payloadcms/payload/blob/39143c9d12ac81de25e677517b58406ae81d317f/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](https://github.com/payloadcms/payload/commit/a0ea58d81d9cf8953e92621eebf82e895e9d5431#diff-bad1e1b58992c48178ea7d0dfa546f66bfa6e10eed2dd3db5c74e092824fa7ffL58) - [handling objects in the UI component](https://github.com/payloadcms/payload/commit/a0ea58d81d9cf8953e92621eebf82e895e9d5431) Fixes #13905 --- .../src/fields/MetaImage/MetaImageComponent.tsx | 12 ++++++++++-- packages/plugin-seo/src/types.ts | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/plugin-seo/src/fields/MetaImage/MetaImageComponent.tsx b/packages/plugin-seo/src/fields/MetaImage/MetaImageComponent.tsx index 4001a1942..86cdcaccc 100644 --- a/packages/plugin-seo/src/fields/MetaImage/MetaImageComponent.tsx +++ b/packages/plugin-seo/src/fields/MetaImage/MetaImageComponent.tsx @@ -49,7 +49,7 @@ export const MetaImageComponent: React.FC = (props) => { setValue, showError, value, - }: FieldType = useField() + }: FieldType = useField() const { t } = useTranslation() @@ -92,7 +92,15 @@ export const MetaImageComponent: React.FC = (props) => { 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, serverURL, diff --git a/packages/plugin-seo/src/types.ts b/packages/plugin-seo/src/types.ts index 1b3c1ef8c..02dc4e0e3 100644 --- a/packages/plugin-seo/src/types.ts +++ b/packages/plugin-seo/src/types.ts @@ -55,7 +55,7 @@ export type GenerateImage = ( locale?: string req: PayloadRequest } & PartialDocumentInfoContext, -) => Promise | string +) => { id: number | string } | number | Promise<{ id: number | string } | number | string> | string export type GenerateURL = ( args: {