188 lines
5.4 KiB
TypeScript
188 lines
5.4 KiB
TypeScript
import 'dotenv/config'
|
|
|
|
import config from '@payload-config'
|
|
import crypto from 'crypto'
|
|
import { getPayload, type Payload } from 'payload'
|
|
import { mediaByFilename } from './mediaByFilename'
|
|
|
|
import { netzwerkContent } from '@/spa/netzwerkContent'
|
|
|
|
const safeRemoteName = (url: string) => {
|
|
const parsed = new URL(url)
|
|
const ext = parsed.pathname.split('/').pop()?.includes('.') ? `.${parsed.pathname.split('.').pop()}` : '.jpg'
|
|
const hash = crypto.createHash('sha1').update(url).digest('hex').slice(0, 10)
|
|
return `${parsed.hostname.replace(/[^a-z0-9]+/gi, '-')}-${hash}${ext}`.toLowerCase()
|
|
}
|
|
|
|
const filenameForSource = (source: string) => {
|
|
if (source.startsWith('http')) return safeRemoteName(source)
|
|
return source.split('?')[0]?.split('/').filter(Boolean).pop()
|
|
}
|
|
|
|
const itemsWithImageUploads = async <T extends { image?: string }>(payload: Payload, items: T[]) =>
|
|
Promise.all(
|
|
items.map(async (item) => {
|
|
const filename = item.image ? filenameForSource(item.image) : undefined
|
|
return {
|
|
...item,
|
|
imageUpload: filename ? await mediaByFilename(payload, filename) : undefined,
|
|
}
|
|
}),
|
|
)
|
|
|
|
const partnersForPayload = netzwerkContent.partners.items.map(({ id, ...partner }, index) => ({
|
|
...partner,
|
|
stableId: id,
|
|
active: true,
|
|
showOnHomepage: true,
|
|
sortOrder: index,
|
|
_status: 'published' as const,
|
|
}))
|
|
|
|
async function upsertPartners(payload: Payload) {
|
|
await Promise.all(
|
|
partnersForPayload.map(async (partner) => {
|
|
const existing = await payload.find({
|
|
collection: 'partners',
|
|
limit: 1,
|
|
pagination: false,
|
|
draft: true,
|
|
overrideAccess: true,
|
|
where: {
|
|
stableId: { equals: partner.stableId },
|
|
},
|
|
})
|
|
|
|
const doc = existing.docs[0]
|
|
|
|
if (doc) {
|
|
await payload.update({
|
|
collection: 'partners',
|
|
id: doc.id,
|
|
overrideAccess: true,
|
|
context: { disableRevalidate: true },
|
|
data: partner as never,
|
|
})
|
|
return
|
|
}
|
|
|
|
await payload.create({
|
|
collection: 'partners',
|
|
overrideAccess: true,
|
|
context: { disableRevalidate: true },
|
|
data: partner as never,
|
|
})
|
|
}),
|
|
)
|
|
}
|
|
|
|
async function juryMembersForPage(payload: Payload) {
|
|
const existing = await payload.find({
|
|
collection: 'jury-mitglieder',
|
|
limit: 300,
|
|
pagination: false,
|
|
draft: true,
|
|
overrideAccess: true,
|
|
sort: 'sortOrder',
|
|
})
|
|
|
|
if (existing.docs.length) {
|
|
return existing.docs.filter((member) => member.active !== false).map((member) => member.id)
|
|
}
|
|
|
|
const membersWithUploads = await itemsWithImageUploads(payload, netzwerkContent.jury.members)
|
|
const created = await Promise.all(
|
|
membersWithUploads.map((member, index) =>
|
|
payload.create({
|
|
collection: 'jury-mitglieder',
|
|
overrideAccess: true,
|
|
context: { disableRevalidate: true },
|
|
data: {
|
|
name: member.name,
|
|
image: member.imageUpload,
|
|
imageAlt: member.name,
|
|
role: member.role,
|
|
bio: member.bio,
|
|
sortOrder: index,
|
|
active: true,
|
|
_status: 'published',
|
|
},
|
|
}),
|
|
),
|
|
)
|
|
|
|
return created.map((member) => member.id)
|
|
}
|
|
|
|
async function main() {
|
|
const payload = await getPayload({ config })
|
|
|
|
const pageResult = await payload.find({
|
|
collection: 'pages',
|
|
limit: 1,
|
|
pagination: false,
|
|
draft: true,
|
|
overrideAccess: true,
|
|
where: {
|
|
or: [{ spaPath: { equals: '/netzwerk' } }, { slug: { equals: 'netzwerk' } }, { slug: { equals: 'network' } }],
|
|
},
|
|
})
|
|
|
|
const page = pageResult.docs[0]
|
|
if (!page) throw new Error('Netzwerk page not found. Expected spaPath=/netzwerk or slug=netzwerk/network.')
|
|
|
|
const heroImage = await mediaByFilename(payload, netzwerkContent.hero.imageFilename)
|
|
const sponsoringImage = await mediaByFilename(payload, netzwerkContent.sponsoring.imageFilename)
|
|
const { imageFilename: _heroFilename, ...heroContent } = netzwerkContent.hero
|
|
const { imageFilename: _sponsoringFilename, ...sponsoringContent } = netzwerkContent.sponsoring
|
|
const { items: _partnerItems, tiers: partnerTiers, ...partnerSectionContent } = netzwerkContent.partners
|
|
const existingGreetingVideo = page.netzwerk?.patronage?.greetingVideo || null
|
|
const [patronPeople, juryMembers] = await Promise.all([
|
|
itemsWithImageUploads(payload, netzwerkContent.patronage.people),
|
|
juryMembersForPage(payload),
|
|
])
|
|
|
|
await payload.update({
|
|
collection: 'pages',
|
|
id: page.id,
|
|
overrideAccess: true,
|
|
context: { disableRevalidate: true },
|
|
data: {
|
|
netzwerk: {
|
|
...netzwerkContent,
|
|
hero: {
|
|
...heroContent,
|
|
image: heroImage,
|
|
},
|
|
patronage: {
|
|
...netzwerkContent.patronage,
|
|
greetingVideo: existingGreetingVideo,
|
|
people: patronPeople,
|
|
},
|
|
jury: {
|
|
...netzwerkContent.jury,
|
|
members: juryMembers,
|
|
},
|
|
sponsoring: {
|
|
...sponsoringContent,
|
|
image: sponsoringImage,
|
|
},
|
|
partners: {
|
|
...partnerSectionContent,
|
|
tiers: partnerTiers.map(({ tier, label, note }) => ({ tier, label, note })),
|
|
},
|
|
},
|
|
} as never,
|
|
})
|
|
|
|
await upsertPartners(payload)
|
|
|
|
payload.logger.info(`Preloaded Netzwerk CMS fields for page ${page.id}`)
|
|
process.exit(0)
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error(error)
|
|
process.exit(1)
|
|
})
|