@payloadcms/plugin-seo 4.0.0-internal.d1cc1d3 → 4.0.0-internal.d21c039
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fields/MetaDescription/MetaDescriptionComponent.js +1 -1
- package/dist/fields/MetaDescription/MetaDescriptionComponent.js.map +1 -1
- package/dist/fields/MetaImage/MetaImageComponent.js +1 -1
- package/dist/fields/MetaImage/MetaImageComponent.js.map +1 -1
- package/dist/fields/MetaTitle/MetaTitleComponent.js +1 -1
- package/dist/fields/MetaTitle/MetaTitleComponent.js.map +1 -1
- package/dist/fields/Preview/PreviewComponent.js +1 -1
- package/dist/fields/Preview/PreviewComponent.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +132 -9
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
|
@@ -37,7 +37,7 @@ export const MetaDescriptionComponent = (props)=>{
|
|
|
37
37
|
hasSavePermission: docInfo.hasSavePermission,
|
|
38
38
|
initialData: docInfo.initialData,
|
|
39
39
|
initialState: reduceToSerializableFields(docInfo.initialState ?? {}),
|
|
40
|
-
locale:
|
|
40
|
+
locale: locale?.code,
|
|
41
41
|
title
|
|
42
42
|
}),
|
|
43
43
|
credentials: 'include',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/fields/MetaDescription/MetaDescriptionComponent.tsx"],"sourcesContent":["'use client'\n\nimport type { FieldType } from '@payloadcms/ui'\nimport type { TextareaFieldClientProps } from 'payload'\n\nimport {\n FieldLabel,\n TextareaInput,\n useConfig,\n useDocumentInfo,\n useDocumentTitle,\n useField,\n useForm,\n useLocale,\n useTranslation,\n} from '@payloadcms/ui'\nimport { reduceToSerializableFields } from '@payloadcms/ui/shared'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { useCallback } from 'react'\n\nimport type { PluginSEOTranslationKeys, PluginSEOTranslations } from '../../translations/index.js'\nimport type { GenerateDescription } from '../../types.js'\n\nimport { defaults } from '../../defaults.js'\nimport { LengthIndicator } from '../../ui/LengthIndicator.js'\n\nconst { maxLength: maxLengthDefault, minLength: minLengthDefault } = defaults.description\n\ntype MetaDescriptionProps = {\n readonly hasGenerateDescriptionFn: boolean\n} & TextareaFieldClientProps\n\nexport const MetaDescriptionComponent: React.FC<MetaDescriptionProps> = (props) => {\n const {\n field: {\n label,\n localized,\n maxLength: maxLengthFromProps,\n minLength: minLengthFromProps,\n required,\n },\n hasGenerateDescriptionFn,\n readOnly,\n } = props\n\n const {\n config: {\n routes: { api },\n },\n } = useConfig()\n\n const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()\n\n const locale = useLocale()\n const { getData } = useForm()\n const docInfo = useDocumentInfo()\n const { title } = useDocumentTitle()\n\n const maxLength = maxLengthFromProps || maxLengthDefault\n const minLength = minLengthFromProps || minLengthDefault\n\n const {\n customComponents: { AfterInput, BeforeInput, Label } = {},\n errorMessage,\n path,\n setValue,\n showError,\n value,\n }: FieldType<string> = useField()\n\n const regenerateDescription = useCallback(async () => {\n if (!hasGenerateDescriptionFn) {\n return\n }\n\n const endpoint = formatAdminURL({\n apiRoute: api,\n path: '/plugin-seo/generate-description',\n })\n\n const genDescriptionResponse = await fetch(endpoint, {\n body: JSON.stringify({\n id: docInfo.id,\n collectionSlug: docInfo.collectionSlug,\n doc: getData(),\n docPermissions: docInfo.docPermissions,\n globalSlug: docInfo.globalSlug,\n hasPublishPermission: docInfo.hasPublishPermission,\n hasSavePermission: docInfo.hasSavePermission,\n initialData: docInfo.initialData,\n initialState: reduceToSerializableFields(docInfo.initialState ?? {}),\n locale:
|
|
1
|
+
{"version":3,"sources":["../../../src/fields/MetaDescription/MetaDescriptionComponent.tsx"],"sourcesContent":["'use client'\n\nimport type { FieldType } from '@payloadcms/ui'\nimport type { TextareaFieldClientProps } from 'payload'\n\nimport {\n FieldLabel,\n TextareaInput,\n useConfig,\n useDocumentInfo,\n useDocumentTitle,\n useField,\n useForm,\n useLocale,\n useTranslation,\n} from '@payloadcms/ui'\nimport { reduceToSerializableFields } from '@payloadcms/ui/shared'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { useCallback } from 'react'\n\nimport type { PluginSEOTranslationKeys, PluginSEOTranslations } from '../../translations/index.js'\nimport type { GenerateDescription } from '../../types.js'\n\nimport { defaults } from '../../defaults.js'\nimport { LengthIndicator } from '../../ui/LengthIndicator.js'\n\nconst { maxLength: maxLengthDefault, minLength: minLengthDefault } = defaults.description\n\ntype MetaDescriptionProps = {\n readonly hasGenerateDescriptionFn: boolean\n} & TextareaFieldClientProps\n\nexport const MetaDescriptionComponent: React.FC<MetaDescriptionProps> = (props) => {\n const {\n field: {\n label,\n localized,\n maxLength: maxLengthFromProps,\n minLength: minLengthFromProps,\n required,\n },\n hasGenerateDescriptionFn,\n readOnly,\n } = props\n\n const {\n config: {\n routes: { api },\n },\n } = useConfig()\n\n const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()\n\n const locale = useLocale()\n const { getData } = useForm()\n const docInfo = useDocumentInfo()\n const { title } = useDocumentTitle()\n\n const maxLength = maxLengthFromProps || maxLengthDefault\n const minLength = minLengthFromProps || minLengthDefault\n\n const {\n customComponents: { AfterInput, BeforeInput, Label } = {},\n errorMessage,\n path,\n setValue,\n showError,\n value,\n }: FieldType<string> = useField()\n\n const regenerateDescription = useCallback(async () => {\n if (!hasGenerateDescriptionFn) {\n return\n }\n\n const endpoint = formatAdminURL({\n apiRoute: api,\n path: '/plugin-seo/generate-description',\n })\n\n const genDescriptionResponse = await fetch(endpoint, {\n body: JSON.stringify({\n id: docInfo.id,\n collectionSlug: docInfo.collectionSlug,\n doc: getData(),\n docPermissions: docInfo.docPermissions,\n globalSlug: docInfo.globalSlug,\n hasPublishPermission: docInfo.hasPublishPermission,\n hasSavePermission: docInfo.hasSavePermission,\n initialData: docInfo.initialData,\n initialState: reduceToSerializableFields(docInfo.initialState ?? {}),\n locale: locale?.code,\n title,\n } satisfies Omit<\n Parameters<GenerateDescription>[0],\n 'collectionConfig' | 'globalConfig' | 'hasPublishedDoc' | 'req' | 'versionCount'\n >),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n\n const { result: generatedDescription } = await genDescriptionResponse.json()\n\n setValue(generatedDescription || '')\n }, [\n hasGenerateDescriptionFn,\n\n api,\n docInfo.id,\n docInfo.collectionSlug,\n docInfo.docPermissions,\n docInfo.globalSlug,\n docInfo.hasPublishPermission,\n docInfo.hasSavePermission,\n docInfo.initialData,\n docInfo.initialState,\n getData,\n locale,\n setValue,\n title,\n ])\n\n return (\n <div\n style={{\n marginBottom: '20px',\n }}\n >\n <div\n style={{\n marginBottom: '5px',\n position: 'relative',\n }}\n >\n <div className=\"plugin-seo__field\">\n {Label ?? (\n <FieldLabel label={label} localized={localized} path={path} required={required} />\n )}\n {hasGenerateDescriptionFn && (\n <React.Fragment>\n — \n <button\n disabled={readOnly}\n onClick={() => {\n void regenerateDescription()\n }}\n style={{\n background: 'none',\n backgroundColor: 'transparent',\n border: 'none',\n color: 'currentcolor',\n cursor: 'pointer',\n padding: 0,\n textDecoration: 'underline',\n }}\n type=\"button\"\n >\n {t('plugin-seo:autoGenerate')}\n </button>\n </React.Fragment>\n )}\n </div>\n <div\n style={{\n color: '#9A9A9A',\n }}\n >\n {t('plugin-seo:lengthTipDescription', { maxLength, minLength })}\n <a\n href=\"https://developers.google.com/search/docs/advanced/appearance/snippet#meta-descriptions\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n >\n {t('plugin-seo:bestPractices')}\n </a>\n </div>\n </div>\n <div\n style={{\n marginBottom: '10px',\n position: 'relative',\n }}\n >\n <TextareaInput\n AfterInput={AfterInput}\n BeforeInput={BeforeInput}\n Error={errorMessage}\n onChange={setValue}\n path={path}\n readOnly={readOnly}\n required={required}\n showError={showError}\n style={{\n marginBottom: 0,\n }}\n value={value}\n />\n </div>\n <div\n style={{\n alignItems: 'center',\n display: 'flex',\n width: '100%',\n }}\n >\n <LengthIndicator maxLength={maxLength} minLength={minLength} text={value} />\n </div>\n </div>\n )\n}\n"],"names":["FieldLabel","TextareaInput","useConfig","useDocumentInfo","useDocumentTitle","useField","useForm","useLocale","useTranslation","reduceToSerializableFields","formatAdminURL","React","useCallback","defaults","LengthIndicator","maxLength","maxLengthDefault","minLength","minLengthDefault","description","MetaDescriptionComponent","props","field","label","localized","maxLengthFromProps","minLengthFromProps","required","hasGenerateDescriptionFn","readOnly","config","routes","api","t","locale","getData","docInfo","title","customComponents","AfterInput","BeforeInput","Label","errorMessage","path","setValue","showError","value","regenerateDescription","endpoint","apiRoute","genDescriptionResponse","fetch","body","JSON","stringify","id","collectionSlug","doc","docPermissions","globalSlug","hasPublishPermission","hasSavePermission","initialData","initialState","code","credentials","headers","method","result","generatedDescription","json","div","style","marginBottom","position","className","Fragment","button","disabled","onClick","background","backgroundColor","border","color","cursor","padding","textDecoration","type","a","href","rel","target","Error","onChange","alignItems","display","width","text"],"mappings":"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"}
|
|
@@ -33,7 +33,7 @@ export const MetaImageComponent = (props)=>{
|
|
|
33
33
|
hasSavePermission: docInfo.hasSavePermission,
|
|
34
34
|
initialData: docInfo.initialData,
|
|
35
35
|
initialState: reduceToSerializableFields(docInfo.initialState ?? {}),
|
|
36
|
-
locale:
|
|
36
|
+
locale: locale?.code,
|
|
37
37
|
title
|
|
38
38
|
}),
|
|
39
39
|
credentials: 'include',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/fields/MetaImage/MetaImageComponent.tsx"],"sourcesContent":["'use client'\n\nimport type { FieldType } from '@payloadcms/ui'\nimport type { UploadFieldClientProps } from 'payload'\n\nimport {\n FieldLabel,\n RenderCustomComponent,\n UploadInput,\n useConfig,\n useDocumentInfo,\n useDocumentTitle,\n useField,\n useForm,\n useLocale,\n useTranslation,\n} from '@payloadcms/ui'\nimport { reduceToSerializableFields } from '@payloadcms/ui/shared'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { useCallback } from 'react'\n\nimport type { PluginSEOTranslationKeys, PluginSEOTranslations } from '../../translations/index.js'\nimport type { GenerateImage } from '../../types.js'\n\nimport { Pill } from '../../ui/Pill.js'\n\ntype MetaImageProps = {\n readonly hasGenerateImageFn: boolean\n} & UploadFieldClientProps\n\nexport const MetaImageComponent: React.FC<MetaImageProps> = (props) => {\n const {\n field: { admin: { allowCreate } = {}, label, localized, relationTo, required },\n hasGenerateImageFn,\n readOnly,\n } = props\n\n const {\n config: {\n routes: { api },\n serverURL,\n },\n getEntityConfig,\n } = useConfig()\n\n const {\n customComponents: { Error, Label } = {},\n filterOptions,\n path,\n setValue,\n showError,\n value,\n }: FieldType<number | string> = useField()\n\n const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()\n\n const locale = useLocale()\n const { getData } = useForm()\n const docInfo = useDocumentInfo()\n\n const { title } = useDocumentTitle()\n\n const regenerateImage = useCallback(async () => {\n if (!hasGenerateImageFn) {\n return\n }\n\n const endpoint = formatAdminURL({\n apiRoute: api,\n path: '/plugin-seo/generate-image',\n })\n\n const genImageResponse = await fetch(endpoint, {\n body: JSON.stringify({\n id: docInfo.id,\n collectionSlug: docInfo.collectionSlug,\n doc: getData(),\n docPermissions: docInfo.docPermissions,\n globalSlug: docInfo.globalSlug,\n hasPublishPermission: docInfo.hasPublishPermission,\n hasSavePermission: docInfo.hasSavePermission,\n initialData: docInfo.initialData,\n initialState: reduceToSerializableFields(docInfo.initialState ?? {}),\n locale: typeof locale === 'object' ? locale?.code : locale,\n title,\n } satisfies Omit<\n Parameters<GenerateImage>[0],\n 'collectionConfig' | 'globalConfig' | 'hasPublishedDoc' | 'req' | 'versionCount'\n >),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n\n const { result: generatedImage } = await genImageResponse.json()\n\n // string ids, number ids or nullish values\n let newValue: null | number | string | undefined = generatedImage\n // non-nullish resolved relations\n if (typeof generatedImage === 'object' && generatedImage && 'id' in generatedImage) {\n newValue = generatedImage.id\n }\n\n // coerce to an empty string for falsy (=empty) values\n setValue(newValue || '')\n }, [\n hasGenerateImageFn,\n api,\n docInfo.id,\n docInfo.collectionSlug,\n docInfo.docPermissions,\n docInfo.globalSlug,\n docInfo.hasPublishPermission,\n docInfo.hasSavePermission,\n docInfo.initialData,\n docInfo.initialState,\n getData,\n locale,\n setValue,\n title,\n ])\n\n const hasImage = Boolean(value)\n\n const collection = getEntityConfig({ collectionSlug: relationTo })\n\n return (\n <div\n style={{\n marginBottom: '20px',\n }}\n >\n <div\n style={{\n marginBottom: '5px',\n position: 'relative',\n }}\n >\n <div className=\"plugin-seo__field\">\n <RenderCustomComponent\n CustomComponent={Label}\n Fallback={\n <FieldLabel label={label} localized={localized} path={path} required={required} />\n }\n />\n {hasGenerateImageFn && (\n <React.Fragment>\n — \n <button\n disabled={readOnly}\n onClick={() => {\n void regenerateImage()\n }}\n style={{\n background: 'none',\n backgroundColor: 'transparent',\n border: 'none',\n color: 'currentcolor',\n cursor: 'pointer',\n padding: 0,\n textDecoration: 'underline',\n }}\n type=\"button\"\n >\n {t('plugin-seo:autoGenerate')}\n </button>\n </React.Fragment>\n )}\n </div>\n {hasGenerateImageFn && (\n <div\n style={{\n color: '#9A9A9A',\n }}\n >\n {t('plugin-seo:imageAutoGenerationTip')}\n </div>\n )}\n </div>\n <div\n style={{\n marginBottom: '10px',\n position: 'relative',\n }}\n >\n <UploadInput\n allowCreate={allowCreate !== false}\n api={api}\n collection={collection}\n Error={Error}\n filterOptions={filterOptions}\n onChange={(incomingImage) => {\n if (incomingImage !== null) {\n if (typeof incomingImage === 'object') {\n const { id: incomingID } = incomingImage\n setValue(incomingID)\n } else {\n setValue(incomingImage)\n }\n } else {\n setValue(null)\n }\n }}\n path={path}\n readOnly={readOnly}\n relationTo={relationTo}\n required={required}\n serverURL={serverURL}\n showError={showError}\n style={{\n marginBottom: 0,\n }}\n value={value}\n />\n </div>\n <div\n style={{\n alignItems: 'center',\n display: 'flex',\n width: '100%',\n }}\n >\n <Pill\n backgroundColor={hasImage ? 'green' : 'red'}\n color=\"white\"\n label={hasImage ? t('plugin-seo:good') : t('plugin-seo:noImage')}\n />\n </div>\n </div>\n )\n}\n"],"names":["FieldLabel","RenderCustomComponent","UploadInput","useConfig","useDocumentInfo","useDocumentTitle","useField","useForm","useLocale","useTranslation","reduceToSerializableFields","formatAdminURL","React","useCallback","Pill","MetaImageComponent","props","field","admin","allowCreate","label","localized","relationTo","required","hasGenerateImageFn","readOnly","config","routes","api","serverURL","getEntityConfig","customComponents","Error","Label","filterOptions","path","setValue","showError","value","t","locale","getData","docInfo","title","regenerateImage","endpoint","apiRoute","genImageResponse","fetch","body","JSON","stringify","id","collectionSlug","doc","docPermissions","globalSlug","hasPublishPermission","hasSavePermission","initialData","initialState","code","credentials","headers","method","result","generatedImage","json","newValue","hasImage","Boolean","collection","div","style","marginBottom","position","className","CustomComponent","Fallback","Fragment","button","disabled","onClick","background","backgroundColor","border","color","cursor","padding","textDecoration","type","onChange","incomingImage","incomingID","alignItems","display","width"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/fields/MetaImage/MetaImageComponent.tsx"],"sourcesContent":["'use client'\n\nimport type { FieldType } from '@payloadcms/ui'\nimport type { UploadFieldClientProps } from 'payload'\n\nimport {\n FieldLabel,\n RenderCustomComponent,\n UploadInput,\n useConfig,\n useDocumentInfo,\n useDocumentTitle,\n useField,\n useForm,\n useLocale,\n useTranslation,\n} from '@payloadcms/ui'\nimport { reduceToSerializableFields } from '@payloadcms/ui/shared'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { useCallback } from 'react'\n\nimport type { PluginSEOTranslationKeys, PluginSEOTranslations } from '../../translations/index.js'\nimport type { GenerateImage } from '../../types.js'\n\nimport { Pill } from '../../ui/Pill.js'\n\ntype MetaImageProps = {\n readonly hasGenerateImageFn: boolean\n} & UploadFieldClientProps\n\nexport const MetaImageComponent: React.FC<MetaImageProps> = (props) => {\n const {\n field: { admin: { allowCreate } = {}, label, localized, relationTo, required },\n hasGenerateImageFn,\n readOnly,\n } = props\n\n const {\n config: {\n routes: { api },\n serverURL,\n },\n getEntityConfig,\n } = useConfig()\n\n const {\n customComponents: { Error, Label } = {},\n filterOptions,\n path,\n setValue,\n showError,\n value,\n }: FieldType<number | string> = useField()\n\n const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()\n\n const locale = useLocale()\n const { getData } = useForm()\n const docInfo = useDocumentInfo()\n\n const { title } = useDocumentTitle()\n\n const regenerateImage = useCallback(async () => {\n if (!hasGenerateImageFn) {\n return\n }\n\n const endpoint = formatAdminURL({\n apiRoute: api,\n path: '/plugin-seo/generate-image',\n })\n\n const genImageResponse = await fetch(endpoint, {\n body: JSON.stringify({\n id: docInfo.id,\n collectionSlug: docInfo.collectionSlug,\n doc: getData(),\n docPermissions: docInfo.docPermissions,\n globalSlug: docInfo.globalSlug,\n hasPublishPermission: docInfo.hasPublishPermission,\n hasSavePermission: docInfo.hasSavePermission,\n initialData: docInfo.initialData,\n initialState: reduceToSerializableFields(docInfo.initialState ?? {}),\n locale: locale?.code,\n title,\n } satisfies Omit<\n Parameters<GenerateImage>[0],\n 'collectionConfig' | 'globalConfig' | 'hasPublishedDoc' | 'req' | 'versionCount'\n >),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n\n const { result: generatedImage } = await genImageResponse.json()\n\n // string ids, number ids or nullish values\n let newValue: null | number | string | undefined = generatedImage\n // non-nullish resolved relations\n if (typeof generatedImage === 'object' && generatedImage && 'id' in generatedImage) {\n newValue = generatedImage.id\n }\n\n // coerce to an empty string for falsy (=empty) values\n setValue(newValue || '')\n }, [\n hasGenerateImageFn,\n api,\n docInfo.id,\n docInfo.collectionSlug,\n docInfo.docPermissions,\n docInfo.globalSlug,\n docInfo.hasPublishPermission,\n docInfo.hasSavePermission,\n docInfo.initialData,\n docInfo.initialState,\n getData,\n locale,\n setValue,\n title,\n ])\n\n const hasImage = Boolean(value)\n\n const collection = getEntityConfig({ collectionSlug: relationTo })\n\n return (\n <div\n style={{\n marginBottom: '20px',\n }}\n >\n <div\n style={{\n marginBottom: '5px',\n position: 'relative',\n }}\n >\n <div className=\"plugin-seo__field\">\n <RenderCustomComponent\n CustomComponent={Label}\n Fallback={\n <FieldLabel label={label} localized={localized} path={path} required={required} />\n }\n />\n {hasGenerateImageFn && (\n <React.Fragment>\n — \n <button\n disabled={readOnly}\n onClick={() => {\n void regenerateImage()\n }}\n style={{\n background: 'none',\n backgroundColor: 'transparent',\n border: 'none',\n color: 'currentcolor',\n cursor: 'pointer',\n padding: 0,\n textDecoration: 'underline',\n }}\n type=\"button\"\n >\n {t('plugin-seo:autoGenerate')}\n </button>\n </React.Fragment>\n )}\n </div>\n {hasGenerateImageFn && (\n <div\n style={{\n color: '#9A9A9A',\n }}\n >\n {t('plugin-seo:imageAutoGenerationTip')}\n </div>\n )}\n </div>\n <div\n style={{\n marginBottom: '10px',\n position: 'relative',\n }}\n >\n <UploadInput\n allowCreate={allowCreate !== false}\n api={api}\n collection={collection}\n Error={Error}\n filterOptions={filterOptions}\n onChange={(incomingImage) => {\n if (incomingImage !== null) {\n if (typeof incomingImage === 'object') {\n const { id: incomingID } = incomingImage\n setValue(incomingID)\n } else {\n setValue(incomingImage)\n }\n } else {\n setValue(null)\n }\n }}\n path={path}\n readOnly={readOnly}\n relationTo={relationTo}\n required={required}\n serverURL={serverURL}\n showError={showError}\n style={{\n marginBottom: 0,\n }}\n value={value}\n />\n </div>\n <div\n style={{\n alignItems: 'center',\n display: 'flex',\n width: '100%',\n }}\n >\n <Pill\n backgroundColor={hasImage ? 'green' : 'red'}\n color=\"white\"\n label={hasImage ? t('plugin-seo:good') : t('plugin-seo:noImage')}\n />\n </div>\n </div>\n )\n}\n"],"names":["FieldLabel","RenderCustomComponent","UploadInput","useConfig","useDocumentInfo","useDocumentTitle","useField","useForm","useLocale","useTranslation","reduceToSerializableFields","formatAdminURL","React","useCallback","Pill","MetaImageComponent","props","field","admin","allowCreate","label","localized","relationTo","required","hasGenerateImageFn","readOnly","config","routes","api","serverURL","getEntityConfig","customComponents","Error","Label","filterOptions","path","setValue","showError","value","t","locale","getData","docInfo","title","regenerateImage","endpoint","apiRoute","genImageResponse","fetch","body","JSON","stringify","id","collectionSlug","doc","docPermissions","globalSlug","hasPublishPermission","hasSavePermission","initialData","initialState","code","credentials","headers","method","result","generatedImage","json","newValue","hasImage","Boolean","collection","div","style","marginBottom","position","className","CustomComponent","Fallback","Fragment","button","disabled","onClick","background","backgroundColor","border","color","cursor","padding","textDecoration","type","onChange","incomingImage","incomingID","alignItems","display","width"],"mappings":"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"}
|
|
@@ -38,7 +38,7 @@ export const MetaTitleComponent = (props)=>{
|
|
|
38
38
|
hasSavePermission: docInfo.hasSavePermission,
|
|
39
39
|
initialData: docInfo.initialData,
|
|
40
40
|
initialState: reduceToSerializableFields(docInfo.initialState ?? {}),
|
|
41
|
-
locale:
|
|
41
|
+
locale: locale?.code,
|
|
42
42
|
title
|
|
43
43
|
}),
|
|
44
44
|
credentials: 'include',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/fields/MetaTitle/MetaTitleComponent.tsx"],"sourcesContent":["'use client'\n\nimport type { FieldType } from '@payloadcms/ui'\nimport type { TextFieldClientProps } from 'payload'\n\nimport {\n FieldLabel,\n TextInput,\n useConfig,\n useDocumentInfo,\n useDocumentTitle,\n useField,\n useForm,\n useLocale,\n useTranslation,\n} from '@payloadcms/ui'\nimport { reduceToSerializableFields } from '@payloadcms/ui/shared'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { useCallback } from 'react'\n\nimport type { PluginSEOTranslationKeys, PluginSEOTranslations } from '../../translations/index.js'\nimport type { GenerateTitle } from '../../types.js'\n\nimport { defaults } from '../../defaults.js'\nimport { LengthIndicator } from '../../ui/LengthIndicator.js'\nimport '../index.css'\n\nconst { maxLength: maxLengthDefault, minLength: minLengthDefault } = defaults.title\n\ntype MetaTitleProps = {\n readonly hasGenerateTitleFn: boolean\n} & TextFieldClientProps\n\nexport const MetaTitleComponent: React.FC<MetaTitleProps> = (props) => {\n const {\n field: {\n label,\n localized,\n maxLength: maxLengthFromProps,\n minLength: minLengthFromProps,\n required,\n },\n hasGenerateTitleFn,\n readOnly,\n } = props\n\n const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()\n\n const {\n config: {\n routes: { api },\n },\n } = useConfig()\n\n const {\n customComponents: { AfterInput, BeforeInput, Label } = {},\n errorMessage,\n path,\n setValue,\n showError,\n value,\n }: FieldType<string> = useField()\n\n const locale = useLocale()\n const { getData } = useForm()\n const docInfo = useDocumentInfo()\n const { title } = useDocumentTitle()\n\n const minLength = minLengthFromProps || minLengthDefault\n const maxLength = maxLengthFromProps || maxLengthDefault\n\n const regenerateTitle = useCallback(async () => {\n if (!hasGenerateTitleFn) {\n return\n }\n\n const endpoint = formatAdminURL({\n apiRoute: api,\n path: '/plugin-seo/generate-title',\n })\n\n const genTitleResponse = await fetch(endpoint, {\n body: JSON.stringify({\n id: docInfo.id,\n collectionSlug: docInfo.collectionSlug,\n doc: getData(),\n docPermissions: docInfo.docPermissions,\n globalSlug: docInfo.globalSlug,\n hasPublishPermission: docInfo.hasPublishPermission,\n hasSavePermission: docInfo.hasSavePermission,\n initialData: docInfo.initialData,\n initialState: reduceToSerializableFields(docInfo.initialState ?? {}),\n locale:
|
|
1
|
+
{"version":3,"sources":["../../../src/fields/MetaTitle/MetaTitleComponent.tsx"],"sourcesContent":["'use client'\n\nimport type { FieldType } from '@payloadcms/ui'\nimport type { TextFieldClientProps } from 'payload'\n\nimport {\n FieldLabel,\n TextInput,\n useConfig,\n useDocumentInfo,\n useDocumentTitle,\n useField,\n useForm,\n useLocale,\n useTranslation,\n} from '@payloadcms/ui'\nimport { reduceToSerializableFields } from '@payloadcms/ui/shared'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { useCallback } from 'react'\n\nimport type { PluginSEOTranslationKeys, PluginSEOTranslations } from '../../translations/index.js'\nimport type { GenerateTitle } from '../../types.js'\n\nimport { defaults } from '../../defaults.js'\nimport { LengthIndicator } from '../../ui/LengthIndicator.js'\nimport '../index.css'\n\nconst { maxLength: maxLengthDefault, minLength: minLengthDefault } = defaults.title\n\ntype MetaTitleProps = {\n readonly hasGenerateTitleFn: boolean\n} & TextFieldClientProps\n\nexport const MetaTitleComponent: React.FC<MetaTitleProps> = (props) => {\n const {\n field: {\n label,\n localized,\n maxLength: maxLengthFromProps,\n minLength: minLengthFromProps,\n required,\n },\n hasGenerateTitleFn,\n readOnly,\n } = props\n\n const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()\n\n const {\n config: {\n routes: { api },\n },\n } = useConfig()\n\n const {\n customComponents: { AfterInput, BeforeInput, Label } = {},\n errorMessage,\n path,\n setValue,\n showError,\n value,\n }: FieldType<string> = useField()\n\n const locale = useLocale()\n const { getData } = useForm()\n const docInfo = useDocumentInfo()\n const { title } = useDocumentTitle()\n\n const minLength = minLengthFromProps || minLengthDefault\n const maxLength = maxLengthFromProps || maxLengthDefault\n\n const regenerateTitle = useCallback(async () => {\n if (!hasGenerateTitleFn) {\n return\n }\n\n const endpoint = formatAdminURL({\n apiRoute: api,\n path: '/plugin-seo/generate-title',\n })\n\n const genTitleResponse = await fetch(endpoint, {\n body: JSON.stringify({\n id: docInfo.id,\n collectionSlug: docInfo.collectionSlug,\n doc: getData(),\n docPermissions: docInfo.docPermissions,\n globalSlug: docInfo.globalSlug,\n hasPublishPermission: docInfo.hasPublishPermission,\n hasSavePermission: docInfo.hasSavePermission,\n initialData: docInfo.initialData,\n initialState: reduceToSerializableFields(docInfo.initialState ?? {}),\n locale: locale?.code,\n title,\n } satisfies Omit<\n Parameters<GenerateTitle>[0],\n 'collectionConfig' | 'globalConfig' | 'hasPublishedDoc' | 'req' | 'versionCount'\n >),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n\n const { result: generatedTitle } = await genTitleResponse.json()\n\n setValue(generatedTitle || '')\n }, [\n hasGenerateTitleFn,\n api,\n docInfo.id,\n docInfo.collectionSlug,\n docInfo.docPermissions,\n docInfo.globalSlug,\n docInfo.hasPublishPermission,\n docInfo.hasSavePermission,\n docInfo.initialData,\n docInfo.initialState,\n getData,\n locale,\n setValue,\n title,\n ])\n\n return (\n <div\n style={{\n marginBottom: '20px',\n }}\n >\n <div\n style={{\n marginBottom: '5px',\n position: 'relative',\n }}\n >\n <div className=\"plugin-seo__field\">\n {Label ?? (\n <FieldLabel label={label} localized={localized} path={path} required={required} />\n )}\n {hasGenerateTitleFn && (\n <React.Fragment>\n — \n <button\n disabled={readOnly}\n onClick={() => {\n void regenerateTitle()\n }}\n style={{\n background: 'none',\n backgroundColor: 'transparent',\n border: 'none',\n color: 'currentcolor',\n cursor: 'pointer',\n padding: 0,\n textDecoration: 'underline',\n }}\n type=\"button\"\n >\n {t('plugin-seo:autoGenerate')}\n </button>\n </React.Fragment>\n )}\n </div>\n <div\n style={{\n color: '#9A9A9A',\n }}\n >\n {t('plugin-seo:lengthTipTitle', { maxLength, minLength })}\n <a\n href=\"https://developers.google.com/search/docs/advanced/appearance/title-link#page-titles\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n >\n {t('plugin-seo:bestPractices')}\n </a>\n .\n </div>\n </div>\n <div\n style={{\n marginBottom: '10px',\n position: 'relative',\n }}\n >\n <TextInput\n AfterInput={AfterInput}\n BeforeInput={BeforeInput}\n Error={errorMessage}\n onChange={setValue}\n path={path}\n readOnly={readOnly}\n required={required}\n showError={showError}\n style={{\n marginBottom: 0,\n }}\n value={value}\n />\n </div>\n <div\n style={{\n alignItems: 'center',\n display: 'flex',\n width: '100%',\n }}\n >\n <LengthIndicator maxLength={maxLength} minLength={minLength} text={value} />\n </div>\n </div>\n )\n}\n"],"names":["FieldLabel","TextInput","useConfig","useDocumentInfo","useDocumentTitle","useField","useForm","useLocale","useTranslation","reduceToSerializableFields","formatAdminURL","React","useCallback","defaults","LengthIndicator","maxLength","maxLengthDefault","minLength","minLengthDefault","title","MetaTitleComponent","props","field","label","localized","maxLengthFromProps","minLengthFromProps","required","hasGenerateTitleFn","readOnly","t","config","routes","api","customComponents","AfterInput","BeforeInput","Label","errorMessage","path","setValue","showError","value","locale","getData","docInfo","regenerateTitle","endpoint","apiRoute","genTitleResponse","fetch","body","JSON","stringify","id","collectionSlug","doc","docPermissions","globalSlug","hasPublishPermission","hasSavePermission","initialData","initialState","code","credentials","headers","method","result","generatedTitle","json","div","style","marginBottom","position","className","Fragment","button","disabled","onClick","background","backgroundColor","border","color","cursor","padding","textDecoration","type","a","href","rel","target","Error","onChange","alignItems","display","width","text"],"mappings":"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"}
|
|
@@ -34,7 +34,7 @@ export const PreviewComponent = (props)=>{
|
|
|
34
34
|
hasSavePermission: docInfo.hasSavePermission,
|
|
35
35
|
initialData: docInfo.initialData,
|
|
36
36
|
initialState: reduceToSerializableFields(docInfo.initialState ?? {}),
|
|
37
|
-
locale:
|
|
37
|
+
locale: locale?.code,
|
|
38
38
|
title
|
|
39
39
|
}),
|
|
40
40
|
credentials: 'include',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/fields/Preview/PreviewComponent.tsx"],"sourcesContent":["'use client'\n\nimport type { FormField, UIField } from 'payload'\n\nimport {\n useAllFormFields,\n useConfig,\n useDocumentInfo,\n useDocumentTitle,\n useForm,\n useLocale,\n useTranslation,\n} from '@payloadcms/ui'\nimport { reduceToSerializableFields } from '@payloadcms/ui/shared'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { useEffect, useState } from 'react'\n\nimport type { PluginSEOTranslationKeys, PluginSEOTranslations } from '../../translations/index.js'\nimport type { GenerateURL } from '../../types.js'\n\ntype PreviewProps = {\n readonly descriptionPath?: string\n readonly hasGenerateURLFn: boolean\n readonly titlePath?: string\n} & UIField\n\nexport const PreviewComponent: React.FC<PreviewProps> = (props) => {\n const {\n descriptionPath: descriptionPathFromContext,\n hasGenerateURLFn,\n titlePath: titlePathFromContext,\n } = props\n\n const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()\n\n const {\n config: {\n routes: { api },\n },\n } = useConfig()\n\n const locale = useLocale()\n const [fields] = useAllFormFields()\n const { getData } = useForm()\n const docInfo = useDocumentInfo()\n const { title } = useDocumentTitle()\n\n const descriptionPath = descriptionPathFromContext || 'meta.description'\n const titlePath = titlePathFromContext || 'meta.title'\n\n const {\n [descriptionPath]: { value: metaDescription } = {} as FormField,\n [titlePath]: { value: metaTitle } = {} as FormField,\n } = fields\n\n const [href, setHref] = useState<string>()\n\n useEffect(() => {\n const endpoint = formatAdminURL({\n apiRoute: api,\n path: '/plugin-seo/generate-url',\n })\n\n const getHref = async () => {\n const genURLResponse = await fetch(endpoint, {\n body: JSON.stringify({\n id: docInfo.id,\n collectionSlug: docInfo.collectionSlug,\n doc: getData(),\n docPermissions: docInfo.docPermissions,\n globalSlug: docInfo.globalSlug,\n hasPublishPermission: docInfo.hasPublishPermission,\n hasSavePermission: docInfo.hasSavePermission,\n initialData: docInfo.initialData,\n initialState: reduceToSerializableFields(docInfo.initialState ?? {}),\n locale:
|
|
1
|
+
{"version":3,"sources":["../../../src/fields/Preview/PreviewComponent.tsx"],"sourcesContent":["'use client'\n\nimport type { FormField, UIField } from 'payload'\n\nimport {\n useAllFormFields,\n useConfig,\n useDocumentInfo,\n useDocumentTitle,\n useForm,\n useLocale,\n useTranslation,\n} from '@payloadcms/ui'\nimport { reduceToSerializableFields } from '@payloadcms/ui/shared'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { useEffect, useState } from 'react'\n\nimport type { PluginSEOTranslationKeys, PluginSEOTranslations } from '../../translations/index.js'\nimport type { GenerateURL } from '../../types.js'\n\ntype PreviewProps = {\n readonly descriptionPath?: string\n readonly hasGenerateURLFn: boolean\n readonly titlePath?: string\n} & UIField\n\nexport const PreviewComponent: React.FC<PreviewProps> = (props) => {\n const {\n descriptionPath: descriptionPathFromContext,\n hasGenerateURLFn,\n titlePath: titlePathFromContext,\n } = props\n\n const { t } = useTranslation<PluginSEOTranslations, PluginSEOTranslationKeys>()\n\n const {\n config: {\n routes: { api },\n },\n } = useConfig()\n\n const locale = useLocale()\n const [fields] = useAllFormFields()\n const { getData } = useForm()\n const docInfo = useDocumentInfo()\n const { title } = useDocumentTitle()\n\n const descriptionPath = descriptionPathFromContext || 'meta.description'\n const titlePath = titlePathFromContext || 'meta.title'\n\n const {\n [descriptionPath]: { value: metaDescription } = {} as FormField,\n [titlePath]: { value: metaTitle } = {} as FormField,\n } = fields\n\n const [href, setHref] = useState<string>()\n\n useEffect(() => {\n const endpoint = formatAdminURL({\n apiRoute: api,\n path: '/plugin-seo/generate-url',\n })\n\n const getHref = async () => {\n const genURLResponse = await fetch(endpoint, {\n body: JSON.stringify({\n id: docInfo.id,\n collectionSlug: docInfo.collectionSlug,\n doc: getData(),\n docPermissions: docInfo.docPermissions,\n globalSlug: docInfo.globalSlug,\n hasPublishPermission: docInfo.hasPublishPermission,\n hasSavePermission: docInfo.hasSavePermission,\n initialData: docInfo.initialData,\n initialState: reduceToSerializableFields(docInfo.initialState ?? {}),\n locale: locale?.code,\n title,\n } satisfies Omit<\n Parameters<GenerateURL>[0],\n 'collectionConfig' | 'globalConfig' | 'hasPublishedDoc' | 'req' | 'versionCount'\n >),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n\n const { result: newHref } = await genURLResponse.json()\n\n setHref(newHref)\n }\n\n if (hasGenerateURLFn && !href) {\n void getHref()\n }\n }, [fields, href, locale, docInfo, hasGenerateURLFn, getData, api, title])\n\n return (\n <div\n style={{\n marginBottom: '20px',\n }}\n >\n <div>{t('plugin-seo:preview')}</div>\n <div\n style={{\n color: '#9A9A9A',\n marginBottom: '5px',\n }}\n >\n {t('plugin-seo:previewDescription')}\n </div>\n <div\n style={{\n background: 'var(--color-bg-secondary)',\n borderRadius: '5px',\n boxShadow: '0px 0px 10px rgba(0, 0, 0, 0.1)',\n maxWidth: '600px',\n padding: '20px',\n pointerEvents: 'none',\n width: '100%',\n }}\n >\n <div>\n <a\n href={href}\n style={{\n textDecoration: 'none',\n }}\n >\n {href || 'https://...'}\n </a>\n </div>\n <h4\n style={{\n margin: 0,\n }}\n >\n <a\n href=\"/\"\n style={{\n textDecoration: 'none',\n }}\n >\n {metaTitle as string}\n </a>\n </h4>\n <p\n style={{\n margin: 0,\n }}\n >\n {metaDescription as string}\n </p>\n </div>\n </div>\n )\n}\n"],"names":["useAllFormFields","useConfig","useDocumentInfo","useDocumentTitle","useForm","useLocale","useTranslation","reduceToSerializableFields","formatAdminURL","React","useEffect","useState","PreviewComponent","props","descriptionPath","descriptionPathFromContext","hasGenerateURLFn","titlePath","titlePathFromContext","t","config","routes","api","locale","fields","getData","docInfo","title","value","metaDescription","metaTitle","href","setHref","endpoint","apiRoute","path","getHref","genURLResponse","fetch","body","JSON","stringify","id","collectionSlug","doc","docPermissions","globalSlug","hasPublishPermission","hasSavePermission","initialData","initialState","code","credentials","headers","method","result","newHref","json","div","style","marginBottom","color","background","borderRadius","boxShadow","maxWidth","padding","pointerEvents","width","a","textDecoration","h4","margin","p"],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAKV,eAAe,EAChB,MAAM,YAAY,CAAA;AASnB,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAKV,eAAe,EAChB,MAAM,YAAY,CAAA;AASnB,eAAO,MAAM,SAAS,wDA8YpB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { definePlugin } from 'payload';
|
|
1
|
+
import { canAccessAdmin, definePlugin, executeAccess, Forbidden, UnauthorizedError } from 'payload';
|
|
2
2
|
import { deepMergeSimple } from 'payload/shared';
|
|
3
3
|
import { MetaDescriptionField } from './fields/MetaDescription/index.js';
|
|
4
4
|
import { MetaImageField } from './fields/MetaImage/index.js';
|
|
@@ -48,6 +48,93 @@ export const seoPlugin = definePlugin({
|
|
|
48
48
|
for (const g of config.globals ?? []){
|
|
49
49
|
globalConfigBySlug.set(g.slug, g);
|
|
50
50
|
}
|
|
51
|
+
const authorizeGenerateTarget = async ({ data, req })=>{
|
|
52
|
+
if (!data || typeof data !== 'object') {
|
|
53
|
+
throw new Forbidden(req.t);
|
|
54
|
+
}
|
|
55
|
+
const collectionConfig = data.collectionSlug && pluginConfig.collections?.includes(data.collectionSlug) ? collectionConfigBySlug.get(data.collectionSlug) : undefined;
|
|
56
|
+
const globalConfig = data.globalSlug && pluginConfig.globals?.includes(data.globalSlug) ? globalConfigBySlug.get(data.globalSlug) : undefined;
|
|
57
|
+
if (collectionConfig && !data.globalSlug) {
|
|
58
|
+
const dataDocumentID = data.doc && typeof data.doc === 'object' && 'id' in data.doc ? data.doc.id : undefined;
|
|
59
|
+
const documentIDs = [
|
|
60
|
+
data.id,
|
|
61
|
+
dataDocumentID
|
|
62
|
+
].filter((id)=>id !== null && id !== undefined);
|
|
63
|
+
if (documentIDs.some((id)=>typeof id !== 'string' && typeof id !== 'number')) {
|
|
64
|
+
throw new Forbidden(req.t);
|
|
65
|
+
}
|
|
66
|
+
if (documentIDs.length === 2 && String(documentIDs[0]) !== String(documentIDs[1])) {
|
|
67
|
+
throw new Forbidden(req.t);
|
|
68
|
+
}
|
|
69
|
+
const documentID = documentIDs[0];
|
|
70
|
+
if (documentID !== undefined) {
|
|
71
|
+
const accessibleDoc = await req.payload.findByID({
|
|
72
|
+
id: documentID,
|
|
73
|
+
collection: collectionConfig.slug,
|
|
74
|
+
depth: 0,
|
|
75
|
+
disableErrors: true,
|
|
76
|
+
draft: true,
|
|
77
|
+
overrideAccess: false,
|
|
78
|
+
req,
|
|
79
|
+
trash: true,
|
|
80
|
+
user: req.user
|
|
81
|
+
});
|
|
82
|
+
if (!accessibleDoc) {
|
|
83
|
+
const { totalDocs } = await req.payload.count({
|
|
84
|
+
collection: collectionConfig.slug,
|
|
85
|
+
disableErrors: true,
|
|
86
|
+
overrideAccess: true,
|
|
87
|
+
req,
|
|
88
|
+
trash: true,
|
|
89
|
+
where: {
|
|
90
|
+
id: {
|
|
91
|
+
equals: documentID
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
if (totalDocs > 0) {
|
|
96
|
+
throw new Forbidden(req.t);
|
|
97
|
+
}
|
|
98
|
+
if (collectionConfig.access?.create) {
|
|
99
|
+
await executeAccess({
|
|
100
|
+
slug: collectionConfig.slug,
|
|
101
|
+
data: data.doc,
|
|
102
|
+
req
|
|
103
|
+
}, collectionConfig.access.create);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
} else if (collectionConfig.access?.create) {
|
|
107
|
+
await executeAccess({
|
|
108
|
+
slug: collectionConfig.slug,
|
|
109
|
+
data: data.doc,
|
|
110
|
+
req
|
|
111
|
+
}, collectionConfig.access.create);
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
collectionConfig,
|
|
115
|
+
globalConfig: undefined
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (globalConfig && !data.collectionSlug) {
|
|
119
|
+
const doc = await req.payload.findGlobal({
|
|
120
|
+
slug: globalConfig.slug,
|
|
121
|
+
depth: 0,
|
|
122
|
+
disableErrors: true,
|
|
123
|
+
draft: true,
|
|
124
|
+
overrideAccess: false,
|
|
125
|
+
req,
|
|
126
|
+
user: req.user
|
|
127
|
+
});
|
|
128
|
+
if (!doc) {
|
|
129
|
+
throw new Forbidden(req.t);
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
collectionConfig: undefined,
|
|
133
|
+
globalConfig
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
throw new Forbidden(req.t);
|
|
137
|
+
};
|
|
51
138
|
return {
|
|
52
139
|
...config,
|
|
53
140
|
collections: config.collections?.map((collection)=>{
|
|
@@ -114,12 +201,19 @@ export const seoPlugin = definePlugin({
|
|
|
114
201
|
...config.endpoints ?? [],
|
|
115
202
|
{
|
|
116
203
|
handler: async (req)=>{
|
|
204
|
+
await authorizeGenerate({
|
|
205
|
+
req
|
|
206
|
+
});
|
|
117
207
|
const data = await req.json?.();
|
|
118
208
|
const reqData = data ?? req.data;
|
|
209
|
+
const { collectionConfig, globalConfig } = await authorizeGenerateTarget({
|
|
210
|
+
data: reqData,
|
|
211
|
+
req
|
|
212
|
+
});
|
|
119
213
|
const result = pluginConfig.generateTitle ? await pluginConfig.generateTitle({
|
|
120
214
|
...data,
|
|
121
|
-
collectionConfig
|
|
122
|
-
globalConfig
|
|
215
|
+
collectionConfig,
|
|
216
|
+
globalConfig,
|
|
123
217
|
req
|
|
124
218
|
}) : '';
|
|
125
219
|
return new Response(JSON.stringify({
|
|
@@ -133,12 +227,19 @@ export const seoPlugin = definePlugin({
|
|
|
133
227
|
},
|
|
134
228
|
{
|
|
135
229
|
handler: async (req)=>{
|
|
230
|
+
await authorizeGenerate({
|
|
231
|
+
req
|
|
232
|
+
});
|
|
136
233
|
const data = await req.json?.();
|
|
137
234
|
const reqData = data ?? req.data;
|
|
235
|
+
const { collectionConfig, globalConfig } = await authorizeGenerateTarget({
|
|
236
|
+
data: reqData,
|
|
237
|
+
req
|
|
238
|
+
});
|
|
138
239
|
const result = pluginConfig.generateDescription ? await pluginConfig.generateDescription({
|
|
139
240
|
...data,
|
|
140
|
-
collectionConfig
|
|
141
|
-
globalConfig
|
|
241
|
+
collectionConfig,
|
|
242
|
+
globalConfig,
|
|
142
243
|
req
|
|
143
244
|
}) : '';
|
|
144
245
|
return new Response(JSON.stringify({
|
|
@@ -152,12 +253,19 @@ export const seoPlugin = definePlugin({
|
|
|
152
253
|
},
|
|
153
254
|
{
|
|
154
255
|
handler: async (req)=>{
|
|
256
|
+
await authorizeGenerate({
|
|
257
|
+
req
|
|
258
|
+
});
|
|
155
259
|
const data = await req.json?.();
|
|
156
260
|
const reqData = data ?? req.data;
|
|
261
|
+
const { collectionConfig, globalConfig } = await authorizeGenerateTarget({
|
|
262
|
+
data: reqData,
|
|
263
|
+
req
|
|
264
|
+
});
|
|
157
265
|
const result = pluginConfig.generateURL ? await pluginConfig.generateURL({
|
|
158
266
|
...data,
|
|
159
|
-
collectionConfig
|
|
160
|
-
globalConfig
|
|
267
|
+
collectionConfig,
|
|
268
|
+
globalConfig,
|
|
161
269
|
req
|
|
162
270
|
}) : '';
|
|
163
271
|
return new Response(JSON.stringify({
|
|
@@ -171,12 +279,19 @@ export const seoPlugin = definePlugin({
|
|
|
171
279
|
},
|
|
172
280
|
{
|
|
173
281
|
handler: async (req)=>{
|
|
282
|
+
await authorizeGenerate({
|
|
283
|
+
req
|
|
284
|
+
});
|
|
174
285
|
const data = await req.json?.();
|
|
175
286
|
const reqData = data ?? req.data;
|
|
287
|
+
const { collectionConfig, globalConfig } = await authorizeGenerateTarget({
|
|
288
|
+
data: reqData,
|
|
289
|
+
req
|
|
290
|
+
});
|
|
176
291
|
const result = pluginConfig.generateImage ? await pluginConfig.generateImage({
|
|
177
292
|
...data,
|
|
178
|
-
collectionConfig
|
|
179
|
-
globalConfig
|
|
293
|
+
collectionConfig,
|
|
294
|
+
globalConfig,
|
|
180
295
|
req
|
|
181
296
|
}) : '';
|
|
182
297
|
return new Response(JSON.stringify({
|
|
@@ -240,5 +355,13 @@ export const seoPlugin = definePlugin({
|
|
|
240
355
|
};
|
|
241
356
|
}
|
|
242
357
|
});
|
|
358
|
+
const authorizeGenerate = async ({ req })=>{
|
|
359
|
+
if (!req.user) {
|
|
360
|
+
throw new UnauthorizedError(req.t);
|
|
361
|
+
}
|
|
362
|
+
await canAccessAdmin({
|
|
363
|
+
req
|
|
364
|
+
});
|
|
365
|
+
};
|
|
243
366
|
|
|
244
367
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Config, Field, GroupField, TabsField } from 'payload'\n\nimport { definePlugin } from 'payload'\nimport { deepMergeSimple } from 'payload/shared'\n\nimport type {\n GenerateDescription,\n GenerateImage,\n GenerateTitle,\n GenerateURL,\n SEOPluginConfig,\n} from './types.js'\n\nimport { MetaDescriptionField } from './fields/MetaDescription/index.js'\nimport { MetaImageField } from './fields/MetaImage/index.js'\nimport { MetaTitleField } from './fields/MetaTitle/index.js'\nimport { OverviewField } from './fields/Overview/index.js'\nimport { PreviewField } from './fields/Preview/index.js'\nimport { translations } from './translations/index.js'\n\nexport const seoPlugin = definePlugin<SEOPluginConfig>({\n slug: '@payloadcms/plugin-seo',\n plugin: ({ config, options: pluginConfig }) => {\n const defaultFields: Field[] = [\n OverviewField({}),\n MetaTitleField({\n hasGenerateFn: typeof pluginConfig?.generateTitle === 'function',\n }),\n MetaDescriptionField({\n hasGenerateFn: typeof pluginConfig?.generateDescription === 'function',\n }),\n ...(pluginConfig?.uploadsCollection\n ? [\n MetaImageField({\n hasGenerateFn: typeof pluginConfig?.generateImage === 'function',\n relationTo: pluginConfig.uploadsCollection as string,\n }),\n ]\n : []),\n PreviewField({\n hasGenerateFn: typeof pluginConfig?.generateURL === 'function',\n }),\n ]\n\n const seoFields: GroupField[] = [\n {\n name: 'meta',\n type: 'group',\n fields: [\n ...(pluginConfig?.fields && typeof pluginConfig.fields === 'function'\n ? pluginConfig.fields({ defaultFields })\n : defaultFields),\n ],\n interfaceName: pluginConfig.interfaceName,\n label: 'SEO',\n },\n ]\n\n const collectionConfigBySlug = new Map<string, NonNullable<Config['collections']>[number]>()\n for (const c of config.collections ?? []) {\n collectionConfigBySlug.set(c.slug, c)\n }\n const globalConfigBySlug = new Map<string, NonNullable<Config['globals']>[number]>()\n for (const g of config.globals ?? []) {\n globalConfigBySlug.set(g.slug, g)\n }\n\n return {\n ...config,\n collections:\n config.collections?.map((collection) => {\n const { slug } = collection\n const isEnabled = pluginConfig?.collections?.includes(slug)\n\n if (isEnabled) {\n if (pluginConfig?.tabbedUI) {\n // prevent issues with auth enabled collections having an email field that shouldn't be moved to the SEO tab\n const emailField =\n collection.auth &&\n !(typeof collection.auth === 'object' && collection.auth.disableLocalStrategy) &&\n collection.fields?.find((field) => 'name' in field && field.name === 'email')\n const hasOnlyEmailField = collection.fields?.length === 1 && emailField\n\n const seoTabs: TabsField[] = hasOnlyEmailField\n ? [\n {\n type: 'tabs',\n tabs: [\n {\n fields: seoFields,\n label: 'SEO',\n },\n ],\n },\n ]\n : [\n {\n type: 'tabs',\n tabs: [\n // append a new tab onto the end of the tabs array, if there is one at the first index\n // if needed, create a new `Content` tab in the first index for this collection's base fields\n ...(collection?.fields?.[0]?.type === 'tabs' &&\n collection?.fields?.[0]?.tabs\n ? collection.fields[0].tabs\n : [\n {\n fields: [\n ...(emailField\n ? collection.fields.filter(\n (field) => 'name' in field && field.name !== 'email',\n )\n : collection.fields),\n ],\n label: collection?.labels?.singular || 'Content',\n },\n ]),\n {\n fields: seoFields,\n label: 'SEO',\n },\n ],\n },\n ]\n\n return {\n ...collection,\n fields: [\n ...(emailField ? [emailField] : []),\n ...seoTabs,\n ...(collection?.fields?.[0]?.type === 'tabs' ? collection.fields.slice(1) : []),\n ],\n }\n }\n\n return {\n ...collection,\n fields: [...(collection?.fields || []), ...seoFields],\n }\n }\n\n return collection\n }) || [],\n endpoints: [\n ...(config.endpoints ?? []),\n {\n handler: async (req) => {\n const data: Omit<\n Parameters<GenerateTitle>[0],\n 'collectionConfig' | 'globalConfig' | 'req'\n > = await req.json?.()\n\n const reqData = data ?? req.data\n\n const result = pluginConfig.generateTitle\n ? await pluginConfig.generateTitle({\n ...data,\n collectionConfig: reqData.collectionSlug\n ? collectionConfigBySlug.get(reqData.collectionSlug)\n : undefined,\n globalConfig: reqData.globalSlug\n ? globalConfigBySlug.get(reqData.globalSlug)\n : undefined,\n req,\n } satisfies Parameters<GenerateTitle>[0])\n : ''\n return new Response(JSON.stringify({ result }), { status: 200 })\n },\n method: 'post',\n path: '/plugin-seo/generate-title',\n },\n {\n handler: async (req) => {\n const data: Omit<\n Parameters<GenerateTitle>[0],\n 'collectionConfig' | 'globalConfig' | 'req'\n > = await req.json?.()\n\n const reqData = data ?? req.data\n\n const result = pluginConfig.generateDescription\n ? await pluginConfig.generateDescription({\n ...data,\n collectionConfig: reqData.collectionSlug\n ? collectionConfigBySlug.get(reqData.collectionSlug)\n : undefined,\n globalConfig: reqData.globalSlug\n ? globalConfigBySlug.get(reqData.globalSlug)\n : undefined,\n req,\n } satisfies Parameters<GenerateDescription>[0])\n : ''\n return new Response(JSON.stringify({ result }), { status: 200 })\n },\n method: 'post',\n path: '/plugin-seo/generate-description',\n },\n {\n handler: async (req) => {\n const data: Omit<\n Parameters<GenerateTitle>[0],\n 'collectionConfig' | 'globalConfig' | 'req'\n > = await req.json?.()\n\n const reqData = data ?? req.data\n\n const result = pluginConfig.generateURL\n ? await pluginConfig.generateURL({\n ...data,\n collectionConfig: reqData.collectionSlug\n ? collectionConfigBySlug.get(reqData.collectionSlug)\n : undefined,\n globalConfig: reqData.globalSlug\n ? globalConfigBySlug.get(reqData.globalSlug)\n : undefined,\n req,\n } satisfies Parameters<GenerateURL>[0])\n : ''\n return new Response(JSON.stringify({ result }), { status: 200 })\n },\n method: 'post',\n path: '/plugin-seo/generate-url',\n },\n {\n handler: async (req) => {\n const data: Omit<\n Parameters<GenerateTitle>[0],\n 'collectionConfig' | 'globalConfig' | 'req'\n > = await req.json?.()\n\n const reqData = data ?? req.data\n\n const result = pluginConfig.generateImage\n ? await pluginConfig.generateImage({\n ...data,\n collectionConfig: reqData.collectionSlug\n ? collectionConfigBySlug.get(reqData.collectionSlug)\n : undefined,\n globalConfig: reqData.globalSlug\n ? globalConfigBySlug.get(reqData.globalSlug)\n : undefined,\n req,\n } satisfies Parameters<GenerateImage>[0])\n : ''\n return new Response(JSON.stringify({ result }), { status: 200 })\n },\n method: 'post',\n path: '/plugin-seo/generate-image',\n },\n ],\n globals:\n config.globals?.map((global) => {\n const { slug } = global\n const isEnabled = pluginConfig?.globals?.includes(slug)\n\n if (isEnabled) {\n if (pluginConfig?.tabbedUI) {\n const seoTabs: TabsField[] = [\n {\n type: 'tabs',\n tabs: [\n // append a new tab onto the end of the tabs array, if there is one at the first index\n // if needed, create a new `Content` tab in the first index for this global's base fields\n ...(global?.fields?.[0]?.type === 'tabs' && global?.fields?.[0].tabs\n ? global.fields[0].tabs\n : [\n {\n fields: [...(global?.fields || [])],\n label: global?.label || 'Content',\n },\n ]),\n {\n fields: seoFields,\n label: 'SEO',\n },\n ],\n },\n ]\n\n return {\n ...global,\n fields: [\n ...seoTabs,\n ...(global?.fields?.[0]?.type === 'tabs' ? global.fields.slice(1) : []),\n ],\n }\n }\n\n return {\n ...global,\n fields: [...(global?.fields || []), ...seoFields],\n }\n }\n\n return global\n }) || [],\n i18n: {\n ...config.i18n,\n translations: deepMergeSimple(translations, config.i18n?.translations ?? {}),\n },\n }\n },\n})\n"],"names":["definePlugin","deepMergeSimple","MetaDescriptionField","MetaImageField","MetaTitleField","OverviewField","PreviewField","translations","seoPlugin","slug","plugin","config","options","pluginConfig","defaultFields","hasGenerateFn","generateTitle","generateDescription","uploadsCollection","generateImage","relationTo","generateURL","seoFields","name","type","fields","interfaceName","label","collectionConfigBySlug","Map","c","collections","set","globalConfigBySlug","g","globals","map","collection","isEnabled","includes","tabbedUI","emailField","auth","disableLocalStrategy","find","field","hasOnlyEmailField","length","seoTabs","tabs","filter","labels","singular","slice","endpoints","handler","req","data","json","reqData","result","collectionConfig","collectionSlug","get","undefined","globalConfig","globalSlug","Response","JSON","stringify","status","method","path","global","i18n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Config, Field, GroupField, PayloadRequest, TabsField } from 'payload'\n\nimport { canAccessAdmin, definePlugin, executeAccess, Forbidden, UnauthorizedError } from 'payload'\nimport { deepMergeSimple } from 'payload/shared'\n\nimport type {\n GenerateDescription,\n GenerateImage,\n GenerateTitle,\n GenerateURL,\n SEOPluginConfig,\n} from './types.js'\n\nimport { MetaDescriptionField } from './fields/MetaDescription/index.js'\nimport { MetaImageField } from './fields/MetaImage/index.js'\nimport { MetaTitleField } from './fields/MetaTitle/index.js'\nimport { OverviewField } from './fields/Overview/index.js'\nimport { PreviewField } from './fields/Preview/index.js'\nimport { translations } from './translations/index.js'\n\nexport const seoPlugin = definePlugin<SEOPluginConfig>({\n slug: '@payloadcms/plugin-seo',\n plugin: ({ config, options: pluginConfig }) => {\n const defaultFields: Field[] = [\n OverviewField({}),\n MetaTitleField({\n hasGenerateFn: typeof pluginConfig?.generateTitle === 'function',\n }),\n MetaDescriptionField({\n hasGenerateFn: typeof pluginConfig?.generateDescription === 'function',\n }),\n ...(pluginConfig?.uploadsCollection\n ? [\n MetaImageField({\n hasGenerateFn: typeof pluginConfig?.generateImage === 'function',\n relationTo: pluginConfig.uploadsCollection as string,\n }),\n ]\n : []),\n PreviewField({\n hasGenerateFn: typeof pluginConfig?.generateURL === 'function',\n }),\n ]\n\n const seoFields: GroupField[] = [\n {\n name: 'meta',\n type: 'group',\n fields: [\n ...(pluginConfig?.fields && typeof pluginConfig.fields === 'function'\n ? pluginConfig.fields({ defaultFields })\n : defaultFields),\n ],\n interfaceName: pluginConfig.interfaceName,\n label: 'SEO',\n },\n ]\n\n const collectionConfigBySlug = new Map<string, NonNullable<Config['collections']>[number]>()\n for (const c of config.collections ?? []) {\n collectionConfigBySlug.set(c.slug, c)\n }\n const globalConfigBySlug = new Map<string, NonNullable<Config['globals']>[number]>()\n for (const g of config.globals ?? []) {\n globalConfigBySlug.set(g.slug, g)\n }\n\n const authorizeGenerateTarget = async ({\n data,\n req,\n }: {\n data:\n | null\n | Omit<Parameters<GenerateTitle>[0], 'collectionConfig' | 'globalConfig' | 'req'>\n | undefined\n req: PayloadRequest\n }) => {\n if (!data || typeof data !== 'object') {\n throw new Forbidden(req.t)\n }\n\n const collectionConfig =\n data.collectionSlug && pluginConfig.collections?.includes(data.collectionSlug)\n ? collectionConfigBySlug.get(data.collectionSlug)\n : undefined\n const globalConfig =\n data.globalSlug && pluginConfig.globals?.includes(data.globalSlug)\n ? globalConfigBySlug.get(data.globalSlug)\n : undefined\n\n if (collectionConfig && !data.globalSlug) {\n const dataDocumentID =\n data.doc && typeof data.doc === 'object' && 'id' in data.doc ? data.doc.id : undefined\n const documentIDs = [data.id, dataDocumentID].filter(\n (id) => id !== null && id !== undefined,\n )\n\n if (documentIDs.some((id) => typeof id !== 'string' && typeof id !== 'number')) {\n throw new Forbidden(req.t)\n }\n\n if (documentIDs.length === 2 && String(documentIDs[0]) !== String(documentIDs[1])) {\n throw new Forbidden(req.t)\n }\n\n const documentID = documentIDs[0] as number | string | undefined\n\n if (documentID !== undefined) {\n const accessibleDoc = await req.payload.findByID({\n id: documentID,\n collection: collectionConfig.slug,\n depth: 0,\n disableErrors: true,\n draft: true,\n overrideAccess: false,\n req,\n trash: true,\n user: req.user,\n })\n\n if (!accessibleDoc) {\n const { totalDocs } = await req.payload.count({\n collection: collectionConfig.slug,\n disableErrors: true,\n overrideAccess: true,\n req,\n trash: true,\n where: {\n id: {\n equals: documentID,\n },\n },\n })\n\n if (totalDocs > 0) {\n throw new Forbidden(req.t)\n }\n\n if (collectionConfig.access?.create) {\n await executeAccess(\n { slug: collectionConfig.slug, data: data.doc, req },\n collectionConfig.access.create,\n )\n }\n }\n } else if (collectionConfig.access?.create) {\n await executeAccess(\n { slug: collectionConfig.slug, data: data.doc, req },\n collectionConfig.access.create,\n )\n }\n\n return { collectionConfig, globalConfig: undefined }\n }\n\n if (globalConfig && !data.collectionSlug) {\n const doc = await req.payload.findGlobal({\n slug: globalConfig.slug,\n depth: 0,\n disableErrors: true,\n draft: true,\n overrideAccess: false,\n req,\n user: req.user,\n })\n\n if (!doc) {\n throw new Forbidden(req.t)\n }\n\n return { collectionConfig: undefined, globalConfig }\n }\n\n throw new Forbidden(req.t)\n }\n\n return {\n ...config,\n collections:\n config.collections?.map((collection) => {\n const { slug } = collection\n const isEnabled = pluginConfig?.collections?.includes(slug)\n\n if (isEnabled) {\n if (pluginConfig?.tabbedUI) {\n // prevent issues with auth enabled collections having an email field that shouldn't be moved to the SEO tab\n const emailField =\n collection.auth &&\n !(typeof collection.auth === 'object' && collection.auth.disableLocalStrategy) &&\n collection.fields?.find((field) => 'name' in field && field.name === 'email')\n const hasOnlyEmailField = collection.fields?.length === 1 && emailField\n\n const seoTabs: TabsField[] = hasOnlyEmailField\n ? [\n {\n type: 'tabs',\n tabs: [\n {\n fields: seoFields,\n label: 'SEO',\n },\n ],\n },\n ]\n : [\n {\n type: 'tabs',\n tabs: [\n // append a new tab onto the end of the tabs array, if there is one at the first index\n // if needed, create a new `Content` tab in the first index for this collection's base fields\n ...(collection?.fields?.[0]?.type === 'tabs' &&\n collection?.fields?.[0]?.tabs\n ? collection.fields[0].tabs\n : [\n {\n fields: [\n ...(emailField\n ? collection.fields.filter(\n (field) => 'name' in field && field.name !== 'email',\n )\n : collection.fields),\n ],\n label: collection?.labels?.singular || 'Content',\n },\n ]),\n {\n fields: seoFields,\n label: 'SEO',\n },\n ],\n },\n ]\n\n return {\n ...collection,\n fields: [\n ...(emailField ? [emailField] : []),\n ...seoTabs,\n ...(collection?.fields?.[0]?.type === 'tabs' ? collection.fields.slice(1) : []),\n ],\n }\n }\n\n return {\n ...collection,\n fields: [...(collection?.fields || []), ...seoFields],\n }\n }\n\n return collection\n }) || [],\n endpoints: [\n ...(config.endpoints ?? []),\n {\n handler: async (req) => {\n await authorizeGenerate({ req })\n\n const data: Omit<\n Parameters<GenerateTitle>[0],\n 'collectionConfig' | 'globalConfig' | 'req'\n > = await req.json?.()\n\n const reqData = data ?? req.data\n const { collectionConfig, globalConfig } = await authorizeGenerateTarget({\n data: reqData,\n req,\n })\n\n const result = pluginConfig.generateTitle\n ? await pluginConfig.generateTitle({\n ...data,\n collectionConfig,\n globalConfig,\n req,\n } satisfies Parameters<GenerateTitle>[0])\n : ''\n return new Response(JSON.stringify({ result }), { status: 200 })\n },\n method: 'post',\n path: '/plugin-seo/generate-title',\n },\n {\n handler: async (req) => {\n await authorizeGenerate({ req })\n\n const data: Omit<\n Parameters<GenerateTitle>[0],\n 'collectionConfig' | 'globalConfig' | 'req'\n > = await req.json?.()\n\n const reqData = data ?? req.data\n const { collectionConfig, globalConfig } = await authorizeGenerateTarget({\n data: reqData,\n req,\n })\n\n const result = pluginConfig.generateDescription\n ? await pluginConfig.generateDescription({\n ...data,\n collectionConfig,\n globalConfig,\n req,\n } satisfies Parameters<GenerateDescription>[0])\n : ''\n return new Response(JSON.stringify({ result }), { status: 200 })\n },\n method: 'post',\n path: '/plugin-seo/generate-description',\n },\n {\n handler: async (req) => {\n await authorizeGenerate({ req })\n\n const data: Omit<\n Parameters<GenerateTitle>[0],\n 'collectionConfig' | 'globalConfig' | 'req'\n > = await req.json?.()\n\n const reqData = data ?? req.data\n const { collectionConfig, globalConfig } = await authorizeGenerateTarget({\n data: reqData,\n req,\n })\n\n const result = pluginConfig.generateURL\n ? await pluginConfig.generateURL({\n ...data,\n collectionConfig,\n globalConfig,\n req,\n } satisfies Parameters<GenerateURL>[0])\n : ''\n return new Response(JSON.stringify({ result }), { status: 200 })\n },\n method: 'post',\n path: '/plugin-seo/generate-url',\n },\n {\n handler: async (req) => {\n await authorizeGenerate({ req })\n\n const data: Omit<\n Parameters<GenerateTitle>[0],\n 'collectionConfig' | 'globalConfig' | 'req'\n > = await req.json?.()\n\n const reqData = data ?? req.data\n const { collectionConfig, globalConfig } = await authorizeGenerateTarget({\n data: reqData,\n req,\n })\n\n const result = pluginConfig.generateImage\n ? await pluginConfig.generateImage({\n ...data,\n collectionConfig,\n globalConfig,\n req,\n } satisfies Parameters<GenerateImage>[0])\n : ''\n return new Response(JSON.stringify({ result }), { status: 200 })\n },\n method: 'post',\n path: '/plugin-seo/generate-image',\n },\n ],\n globals:\n config.globals?.map((global) => {\n const { slug } = global\n const isEnabled = pluginConfig?.globals?.includes(slug)\n\n if (isEnabled) {\n if (pluginConfig?.tabbedUI) {\n const seoTabs: TabsField[] = [\n {\n type: 'tabs',\n tabs: [\n // append a new tab onto the end of the tabs array, if there is one at the first index\n // if needed, create a new `Content` tab in the first index for this global's base fields\n ...(global?.fields?.[0]?.type === 'tabs' && global?.fields?.[0].tabs\n ? global.fields[0].tabs\n : [\n {\n fields: [...(global?.fields || [])],\n label: global?.label || 'Content',\n },\n ]),\n {\n fields: seoFields,\n label: 'SEO',\n },\n ],\n },\n ]\n\n return {\n ...global,\n fields: [\n ...seoTabs,\n ...(global?.fields?.[0]?.type === 'tabs' ? global.fields.slice(1) : []),\n ],\n }\n }\n\n return {\n ...global,\n fields: [...(global?.fields || []), ...seoFields],\n }\n }\n\n return global\n }) || [],\n i18n: {\n ...config.i18n,\n translations: deepMergeSimple(translations, config.i18n?.translations ?? {}),\n },\n }\n },\n})\n\nconst authorizeGenerate = async ({ req }: { req: PayloadRequest }): Promise<void> => {\n if (!req.user) {\n throw new UnauthorizedError(req.t)\n }\n\n await canAccessAdmin({ req })\n}\n"],"names":["canAccessAdmin","definePlugin","executeAccess","Forbidden","UnauthorizedError","deepMergeSimple","MetaDescriptionField","MetaImageField","MetaTitleField","OverviewField","PreviewField","translations","seoPlugin","slug","plugin","config","options","pluginConfig","defaultFields","hasGenerateFn","generateTitle","generateDescription","uploadsCollection","generateImage","relationTo","generateURL","seoFields","name","type","fields","interfaceName","label","collectionConfigBySlug","Map","c","collections","set","globalConfigBySlug","g","globals","authorizeGenerateTarget","data","req","t","collectionConfig","collectionSlug","includes","get","undefined","globalConfig","globalSlug","dataDocumentID","doc","id","documentIDs","filter","some","length","String","documentID","accessibleDoc","payload","findByID","collection","depth","disableErrors","draft","overrideAccess","trash","user","totalDocs","count","where","equals","access","create","findGlobal","map","isEnabled","tabbedUI","emailField","auth","disableLocalStrategy","find","field","hasOnlyEmailField","seoTabs","tabs","labels","singular","slice","endpoints","handler","authorizeGenerate","json","reqData","result","Response","JSON","stringify","status","method","path","global","i18n"],"mappings":"AAEA,SAASA,cAAc,EAAEC,YAAY,EAAEC,aAAa,EAAEC,SAAS,EAAEC,iBAAiB,QAAQ,UAAS;AACnG,SAASC,eAAe,QAAQ,iBAAgB;AAUhD,SAASC,oBAAoB,QAAQ,oCAAmC;AACxE,SAASC,cAAc,QAAQ,8BAA6B;AAC5D,SAASC,cAAc,QAAQ,8BAA6B;AAC5D,SAASC,aAAa,QAAQ,6BAA4B;AAC1D,SAASC,YAAY,QAAQ,4BAA2B;AACxD,SAASC,YAAY,QAAQ,0BAAyB;AAEtD,OAAO,MAAMC,YAAYX,aAA8B;IACrDY,MAAM;IACNC,QAAQ,CAAC,EAAEC,MAAM,EAAEC,SAASC,YAAY,EAAE;QACxC,MAAMC,gBAAyB;YAC7BT,cAAc,CAAC;YACfD,eAAe;gBACbW,eAAe,OAAOF,cAAcG,kBAAkB;YACxD;YACAd,qBAAqB;gBACnBa,eAAe,OAAOF,cAAcI,wBAAwB;YAC9D;eACIJ,cAAcK,oBACd;gBACEf,eAAe;oBACbY,eAAe,OAAOF,cAAcM,kBAAkB;oBACtDC,YAAYP,aAAaK,iBAAiB;gBAC5C;aACD,GACD,EAAE;YACNZ,aAAa;gBACXS,eAAe,OAAOF,cAAcQ,gBAAgB;YACtD;SACD;QAED,MAAMC,YAA0B;YAC9B;gBACEC,MAAM;gBACNC,MAAM;gBACNC,QAAQ;uBACFZ,cAAcY,UAAU,OAAOZ,aAAaY,MAAM,KAAK,aACvDZ,aAAaY,MAAM,CAAC;wBAAEX;oBAAc,KACpCA;iBACL;gBACDY,eAAeb,aAAaa,aAAa;gBACzCC,OAAO;YACT;SACD;QAED,MAAMC,yBAAyB,IAAIC;QACnC,KAAK,MAAMC,KAAKnB,OAAOoB,WAAW,IAAI,EAAE,CAAE;YACxCH,uBAAuBI,GAAG,CAACF,EAAErB,IAAI,EAAEqB;QACrC;QACA,MAAMG,qBAAqB,IAAIJ;QAC/B,KAAK,MAAMK,KAAKvB,OAAOwB,OAAO,IAAI,EAAE,CAAE;YACpCF,mBAAmBD,GAAG,CAACE,EAAEzB,IAAI,EAAEyB;QACjC;QAEA,MAAME,0BAA0B,OAAO,EACrCC,IAAI,EACJC,GAAG,EAOJ;YACC,IAAI,CAACD,QAAQ,OAAOA,SAAS,UAAU;gBACrC,MAAM,IAAItC,UAAUuC,IAAIC,CAAC;YAC3B;YAEA,MAAMC,mBACJH,KAAKI,cAAc,IAAI5B,aAAakB,WAAW,EAAEW,SAASL,KAAKI,cAAc,IACzEb,uBAAuBe,GAAG,CAACN,KAAKI,cAAc,IAC9CG;YACN,MAAMC,eACJR,KAAKS,UAAU,IAAIjC,aAAasB,OAAO,EAAEO,SAASL,KAAKS,UAAU,IAC7Db,mBAAmBU,GAAG,CAACN,KAAKS,UAAU,IACtCF;YAEN,IAAIJ,oBAAoB,CAACH,KAAKS,UAAU,EAAE;gBACxC,MAAMC,iBACJV,KAAKW,GAAG,IAAI,OAAOX,KAAKW,GAAG,KAAK,YAAY,QAAQX,KAAKW,GAAG,GAAGX,KAAKW,GAAG,CAACC,EAAE,GAAGL;gBAC/E,MAAMM,cAAc;oBAACb,KAAKY,EAAE;oBAAEF;iBAAe,CAACI,MAAM,CAClD,CAACF,KAAOA,OAAO,QAAQA,OAAOL;gBAGhC,IAAIM,YAAYE,IAAI,CAAC,CAACH,KAAO,OAAOA,OAAO,YAAY,OAAOA,OAAO,WAAW;oBAC9E,MAAM,IAAIlD,UAAUuC,IAAIC,CAAC;gBAC3B;gBAEA,IAAIW,YAAYG,MAAM,KAAK,KAAKC,OAAOJ,WAAW,CAAC,EAAE,MAAMI,OAAOJ,WAAW,CAAC,EAAE,GAAG;oBACjF,MAAM,IAAInD,UAAUuC,IAAIC,CAAC;gBAC3B;gBAEA,MAAMgB,aAAaL,WAAW,CAAC,EAAE;gBAEjC,IAAIK,eAAeX,WAAW;oBAC5B,MAAMY,gBAAgB,MAAMlB,IAAImB,OAAO,CAACC,QAAQ,CAAC;wBAC/CT,IAAIM;wBACJI,YAAYnB,iBAAiB/B,IAAI;wBACjCmD,OAAO;wBACPC,eAAe;wBACfC,OAAO;wBACPC,gBAAgB;wBAChBzB;wBACA0B,OAAO;wBACPC,MAAM3B,IAAI2B,IAAI;oBAChB;oBAEA,IAAI,CAACT,eAAe;wBAClB,MAAM,EAAEU,SAAS,EAAE,GAAG,MAAM5B,IAAImB,OAAO,CAACU,KAAK,CAAC;4BAC5CR,YAAYnB,iBAAiB/B,IAAI;4BACjCoD,eAAe;4BACfE,gBAAgB;4BAChBzB;4BACA0B,OAAO;4BACPI,OAAO;gCACLnB,IAAI;oCACFoB,QAAQd;gCACV;4BACF;wBACF;wBAEA,IAAIW,YAAY,GAAG;4BACjB,MAAM,IAAInE,UAAUuC,IAAIC,CAAC;wBAC3B;wBAEA,IAAIC,iBAAiB8B,MAAM,EAAEC,QAAQ;4BACnC,MAAMzE,cACJ;gCAAEW,MAAM+B,iBAAiB/B,IAAI;gCAAE4B,MAAMA,KAAKW,GAAG;gCAAEV;4BAAI,GACnDE,iBAAiB8B,MAAM,CAACC,MAAM;wBAElC;oBACF;gBACF,OAAO,IAAI/B,iBAAiB8B,MAAM,EAAEC,QAAQ;oBAC1C,MAAMzE,cACJ;wBAAEW,MAAM+B,iBAAiB/B,IAAI;wBAAE4B,MAAMA,KAAKW,GAAG;wBAAEV;oBAAI,GACnDE,iBAAiB8B,MAAM,CAACC,MAAM;gBAElC;gBAEA,OAAO;oBAAE/B;oBAAkBK,cAAcD;gBAAU;YACrD;YAEA,IAAIC,gBAAgB,CAACR,KAAKI,cAAc,EAAE;gBACxC,MAAMO,MAAM,MAAMV,IAAImB,OAAO,CAACe,UAAU,CAAC;oBACvC/D,MAAMoC,aAAapC,IAAI;oBACvBmD,OAAO;oBACPC,eAAe;oBACfC,OAAO;oBACPC,gBAAgB;oBAChBzB;oBACA2B,MAAM3B,IAAI2B,IAAI;gBAChB;gBAEA,IAAI,CAACjB,KAAK;oBACR,MAAM,IAAIjD,UAAUuC,IAAIC,CAAC;gBAC3B;gBAEA,OAAO;oBAAEC,kBAAkBI;oBAAWC;gBAAa;YACrD;YAEA,MAAM,IAAI9C,UAAUuC,IAAIC,CAAC;QAC3B;QAEA,OAAO;YACL,GAAG5B,MAAM;YACToB,aACEpB,OAAOoB,WAAW,EAAE0C,IAAI,CAACd;gBACvB,MAAM,EAAElD,IAAI,EAAE,GAAGkD;gBACjB,MAAMe,YAAY7D,cAAckB,aAAaW,SAASjC;gBAEtD,IAAIiE,WAAW;oBACb,IAAI7D,cAAc8D,UAAU;wBAC1B,4GAA4G;wBAC5G,MAAMC,aACJjB,WAAWkB,IAAI,IACf,CAAE,CAAA,OAAOlB,WAAWkB,IAAI,KAAK,YAAYlB,WAAWkB,IAAI,CAACC,oBAAoB,AAAD,KAC5EnB,WAAWlC,MAAM,EAAEsD,KAAK,CAACC,QAAU,UAAUA,SAASA,MAAMzD,IAAI,KAAK;wBACvE,MAAM0D,oBAAoBtB,WAAWlC,MAAM,EAAE4B,WAAW,KAAKuB;wBAE7D,MAAMM,UAAuBD,oBACzB;4BACE;gCACEzD,MAAM;gCACN2D,MAAM;oCACJ;wCACE1D,QAAQH;wCACRK,OAAO;oCACT;iCACD;4BACH;yBACD,GACD;4BACE;gCACEH,MAAM;gCACN2D,MAAM;oCACJ,sFAAsF;oCACtF,6FAA6F;uCACzFxB,YAAYlC,QAAQ,CAAC,EAAE,EAAED,SAAS,UACtCmC,YAAYlC,QAAQ,CAAC,EAAE,EAAE0D,OACrBxB,WAAWlC,MAAM,CAAC,EAAE,CAAC0D,IAAI,GACzB;wCACE;4CACE1D,QAAQ;mDACFmD,aACAjB,WAAWlC,MAAM,CAAC0B,MAAM,CACtB,CAAC6B,QAAU,UAAUA,SAASA,MAAMzD,IAAI,KAAK,WAE/CoC,WAAWlC,MAAM;6CACtB;4CACDE,OAAOgC,YAAYyB,QAAQC,YAAY;wCACzC;qCACD;oCACL;wCACE5D,QAAQH;wCACRK,OAAO;oCACT;iCACD;4BACH;yBACD;wBAEL,OAAO;4BACL,GAAGgC,UAAU;4BACblC,QAAQ;mCACFmD,aAAa;oCAACA;iCAAW,GAAG,EAAE;mCAC/BM;mCACCvB,YAAYlC,QAAQ,CAAC,EAAE,EAAED,SAAS,SAASmC,WAAWlC,MAAM,CAAC6D,KAAK,CAAC,KAAK,EAAE;6BAC/E;wBACH;oBACF;oBAEA,OAAO;wBACL,GAAG3B,UAAU;wBACblC,QAAQ;+BAAKkC,YAAYlC,UAAU,EAAE;+BAAMH;yBAAU;oBACvD;gBACF;gBAEA,OAAOqC;YACT,MAAM,EAAE;YACV4B,WAAW;mBACL5E,OAAO4E,SAAS,IAAI,EAAE;gBAC1B;oBACEC,SAAS,OAAOlD;wBACd,MAAMmD,kBAAkB;4BAAEnD;wBAAI;wBAE9B,MAAMD,OAGF,MAAMC,IAAIoD,IAAI;wBAElB,MAAMC,UAAUtD,QAAQC,IAAID,IAAI;wBAChC,MAAM,EAAEG,gBAAgB,EAAEK,YAAY,EAAE,GAAG,MAAMT,wBAAwB;4BACvEC,MAAMsD;4BACNrD;wBACF;wBAEA,MAAMsD,SAAS/E,aAAaG,aAAa,GACrC,MAAMH,aAAaG,aAAa,CAAC;4BAC/B,GAAGqB,IAAI;4BACPG;4BACAK;4BACAP;wBACF,KACA;wBACJ,OAAO,IAAIuD,SAASC,KAAKC,SAAS,CAAC;4BAAEH;wBAAO,IAAI;4BAAEI,QAAQ;wBAAI;oBAChE;oBACAC,QAAQ;oBACRC,MAAM;gBACR;gBACA;oBACEV,SAAS,OAAOlD;wBACd,MAAMmD,kBAAkB;4BAAEnD;wBAAI;wBAE9B,MAAMD,OAGF,MAAMC,IAAIoD,IAAI;wBAElB,MAAMC,UAAUtD,QAAQC,IAAID,IAAI;wBAChC,MAAM,EAAEG,gBAAgB,EAAEK,YAAY,EAAE,GAAG,MAAMT,wBAAwB;4BACvEC,MAAMsD;4BACNrD;wBACF;wBAEA,MAAMsD,SAAS/E,aAAaI,mBAAmB,GAC3C,MAAMJ,aAAaI,mBAAmB,CAAC;4BACrC,GAAGoB,IAAI;4BACPG;4BACAK;4BACAP;wBACF,KACA;wBACJ,OAAO,IAAIuD,SAASC,KAAKC,SAAS,CAAC;4BAAEH;wBAAO,IAAI;4BAAEI,QAAQ;wBAAI;oBAChE;oBACAC,QAAQ;oBACRC,MAAM;gBACR;gBACA;oBACEV,SAAS,OAAOlD;wBACd,MAAMmD,kBAAkB;4BAAEnD;wBAAI;wBAE9B,MAAMD,OAGF,MAAMC,IAAIoD,IAAI;wBAElB,MAAMC,UAAUtD,QAAQC,IAAID,IAAI;wBAChC,MAAM,EAAEG,gBAAgB,EAAEK,YAAY,EAAE,GAAG,MAAMT,wBAAwB;4BACvEC,MAAMsD;4BACNrD;wBACF;wBAEA,MAAMsD,SAAS/E,aAAaQ,WAAW,GACnC,MAAMR,aAAaQ,WAAW,CAAC;4BAC7B,GAAGgB,IAAI;4BACPG;4BACAK;4BACAP;wBACF,KACA;wBACJ,OAAO,IAAIuD,SAASC,KAAKC,SAAS,CAAC;4BAAEH;wBAAO,IAAI;4BAAEI,QAAQ;wBAAI;oBAChE;oBACAC,QAAQ;oBACRC,MAAM;gBACR;gBACA;oBACEV,SAAS,OAAOlD;wBACd,MAAMmD,kBAAkB;4BAAEnD;wBAAI;wBAE9B,MAAMD,OAGF,MAAMC,IAAIoD,IAAI;wBAElB,MAAMC,UAAUtD,QAAQC,IAAID,IAAI;wBAChC,MAAM,EAAEG,gBAAgB,EAAEK,YAAY,EAAE,GAAG,MAAMT,wBAAwB;4BACvEC,MAAMsD;4BACNrD;wBACF;wBAEA,MAAMsD,SAAS/E,aAAaM,aAAa,GACrC,MAAMN,aAAaM,aAAa,CAAC;4BAC/B,GAAGkB,IAAI;4BACPG;4BACAK;4BACAP;wBACF,KACA;wBACJ,OAAO,IAAIuD,SAASC,KAAKC,SAAS,CAAC;4BAAEH;wBAAO,IAAI;4BAAEI,QAAQ;wBAAI;oBAChE;oBACAC,QAAQ;oBACRC,MAAM;gBACR;aACD;YACD/D,SACExB,OAAOwB,OAAO,EAAEsC,IAAI,CAAC0B;gBACnB,MAAM,EAAE1F,IAAI,EAAE,GAAG0F;gBACjB,MAAMzB,YAAY7D,cAAcsB,SAASO,SAASjC;gBAElD,IAAIiE,WAAW;oBACb,IAAI7D,cAAc8D,UAAU;wBAC1B,MAAMO,UAAuB;4BAC3B;gCACE1D,MAAM;gCACN2D,MAAM;oCACJ,sFAAsF;oCACtF,yFAAyF;uCACrFgB,QAAQ1E,QAAQ,CAAC,EAAE,EAAED,SAAS,UAAU2E,QAAQ1E,QAAQ,CAAC,EAAE,CAAC0D,OAC5DgB,OAAO1E,MAAM,CAAC,EAAE,CAAC0D,IAAI,GACrB;wCACE;4CACE1D,QAAQ;mDAAK0E,QAAQ1E,UAAU,EAAE;6CAAE;4CACnCE,OAAOwE,QAAQxE,SAAS;wCAC1B;qCACD;oCACL;wCACEF,QAAQH;wCACRK,OAAO;oCACT;iCACD;4BACH;yBACD;wBAED,OAAO;4BACL,GAAGwE,MAAM;4BACT1E,QAAQ;mCACHyD;mCACCiB,QAAQ1E,QAAQ,CAAC,EAAE,EAAED,SAAS,SAAS2E,OAAO1E,MAAM,CAAC6D,KAAK,CAAC,KAAK,EAAE;6BACvE;wBACH;oBACF;oBAEA,OAAO;wBACL,GAAGa,MAAM;wBACT1E,QAAQ;+BAAK0E,QAAQ1E,UAAU,EAAE;+BAAMH;yBAAU;oBACnD;gBACF;gBAEA,OAAO6E;YACT,MAAM,EAAE;YACVC,MAAM;gBACJ,GAAGzF,OAAOyF,IAAI;gBACd7F,cAAcN,gBAAgBM,cAAcI,OAAOyF,IAAI,EAAE7F,gBAAgB,CAAC;YAC5E;QACF;IACF;AACF,GAAE;AAEF,MAAMkF,oBAAoB,OAAO,EAAEnD,GAAG,EAA2B;IAC/D,IAAI,CAACA,IAAI2B,IAAI,EAAE;QACb,MAAM,IAAIjE,kBAAkBsC,IAAIC,CAAC;IACnC;IAEA,MAAM3C,eAAe;QAAE0C;IAAI;AAC7B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloadcms/plugin-seo",
|
|
3
|
-
"version": "4.0.0-internal.
|
|
3
|
+
"version": "4.0.0-internal.d21c039",
|
|
4
4
|
"description": "SEO plugin for Payload",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"payload",
|
|
@@ -57,20 +57,20 @@
|
|
|
57
57
|
"dist"
|
|
58
58
|
],
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@payloadcms/
|
|
61
|
-
"@payloadcms/
|
|
60
|
+
"@payloadcms/ui": "4.0.0-internal.d21c039",
|
|
61
|
+
"@payloadcms/translations": "4.0.0-internal.d21c039"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/react": "19.2.14",
|
|
65
65
|
"@types/react-dom": "19.2.3",
|
|
66
66
|
"@payloadcms/eslint-config": "3.28.0",
|
|
67
|
-
"
|
|
68
|
-
"
|
|
67
|
+
"@payloadcms/next": "4.0.0-internal.d21c039",
|
|
68
|
+
"payload": "4.0.0-internal.d21c039"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
71
|
"react": "^19.0.1 || ^19.1.2 || ^19.2.1",
|
|
72
72
|
"react-dom": "^19.0.1 || ^19.1.2 || ^19.2.1",
|
|
73
|
-
"payload": "4.0.0-internal.
|
|
73
|
+
"payload": "4.0.0-internal.d21c039"
|
|
74
74
|
},
|
|
75
75
|
"publishConfig": {
|
|
76
76
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
|
83
83
|
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
|
84
84
|
"clean": "rimraf -g {dist,*.tsbuildinfo}",
|
|
85
|
-
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
|
|
85
|
+
"copyfiles": "copyfiles -u 1 -e \"**/*.spec.*\" \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
|
|
86
86
|
"lint": "eslint .",
|
|
87
87
|
"lint:fix": "eslint . --fix"
|
|
88
88
|
}
|