Files
websitedev/proto/scripts/migrate-content-to-payload.ts
T
Do SikiandClaude Sonnet 5 6589289878
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Waiting to run
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Blocked by required conditions
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Blocked by required conditions
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Waiting to run
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Blocked by required conditions
feat(cms): enable Payload localization — hu default + en (MITHOME-110)
payload.config.ts: localization: { locales: ['hu','en'], defaultLocale:
'hu', fallback: true }. URL/routing side is separate (MITHOME-114).

Proved the mechanism on a real field rather than a throwaway one:
Common.buttons.* (contact/learnMore/webmail/sendMessage) marked
localized: true — these are genuinely translatable UI labels, so this
doubles as a first, correct slice of the full MITHOME-111 retrofit
instead of being disposable test scaffolding.

Gotcha discovered and documented in the migration script: marking an
existing field `localized: true` after data was already written non-
localized makes that value unreadable via `locale: defaultLocale` (the
storage shape changed) — the migration script must be re-run so it
gets rewritten under the localized shape. This will matter again for
the full MITHOME-111/112 retrofit.

Verified: Local API round-trip (set en, defaultLocale/hu re-seeded via
re-running the migration script) — hu reads "Kapcsolatfelvétel", en
reads "Contact". Real browser: admin UI locale switcher (hu/en) in the
top bar, fields show "— hu"/"— en" per-locale labels, switching
locale swaps the visible value correctly on the Common global editor.
build/lint/tsc/test (58 passed) all clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 13:07:36 +02:00

210 lines
6.6 KiB
TypeScript

/**
* MITHOME-87/88: egyszeri migrációs script — a proto/src/content/pages/*.json
* + common.json tartalmát átemeli a Payload Globals-ekbe (Home, About,
* Services, Contact, Common) és a LegalPages collection-be a Local API-n
* keresztül.
*
* Futtatás (proto/ mappából, futó MongoDB-vel és beállított env-ekkel):
* node --env-file=.env.local --import tsx scripts/migrate-content-to-payload.ts
*
* Idempotens: updateGlobal-t / slug-alapú upsert-et hív, tetszőlegesen
* többször futtatható — mindig a JSON az aktuális "forrás igazság", felül-
* írja a Payload-ban lévő korábbi állapotot. NEM törli/nem érinti a JSON
* fájlokat.
*
* MITHOME-110 tapasztalat: ha egy mezőt utólag `localized: true`-ra
* állítasz (MITHOME-111/112 retrofit), a korábban beírt érték a régi,
* nem-lokalizált tárolási alakban marad, és `locale: defaultLocale`-lal
* nem olvasható vissza (üresnek látszik) — ilyenkor ezt a scriptet újra
* kell futtatni, hogy a defaultLocale (hu) alá újra beírja az értéket a
* lokalizált alakban. Explicit `locale` paramétert egyik updateGlobal/
* update hívás sem ad meg itt, ezért mindig a `defaultLocale` (hu) alá ír.
*/
import path from 'path'
import { fileURLToPath } from 'url'
import { getPayload, type Payload } from 'payload'
import config from '../src/payload.config'
import homeJson from '../src/content/pages/home.json'
import aboutJson from '../src/content/pages/about.json'
import servicesJson from '../src/content/pages/services.json'
import contactJson from '../src/content/pages/contact.json'
import commonJson from '../src/content/common.json'
import adatvedelemJson from '../src/content/pages/adatvedelem.json'
import hasznalatiFeltetelekJson from '../src/content/pages/hasznalati-feltetelek.json'
const scriptDir = path.dirname(fileURLToPath(import.meta.url))
const publicDir = path.resolve(scriptDir, '../public')
/** string[] -> [{ value: string }] — lásd src/globals/fields/stringArray.ts */
function toStringArray(items: readonly string[]): { value: string }[] {
return items.map((value) => ({ value }))
}
function buildHomeData(json: typeof homeJson) {
const { hero, about, services, cta, serviceFeatures } = json
return {
hero: {
...hero,
trustBullets: toStringArray(hero.trustBullets),
},
about,
services: {
...services,
items: services.items.map((item) => ({
...item,
features: toStringArray(item.features),
})),
},
cta,
serviceFeatures,
}
}
function buildAboutData(json: typeof aboutJson) {
const { meta, hero, story, mission, team, cta } = json
return {
meta,
hero,
story: { ...story, paragraphs: toStringArray(story.paragraphs) },
mission,
team: { ...team, paragraphs: toStringArray(team.paragraphs) },
cta,
}
}
function buildServicesData(json: typeof servicesJson) {
const { meta, hero, details, support, cta } = json
return {
meta,
hero,
details: {
...details,
services: details.services.map((service) => ({
...service,
specs: {
...service.specs,
items: toStringArray(service.specs.items),
},
})),
},
support,
cta,
}
}
type LegalPageJson = {
title: string
lastUpdated: string
sections: { id: string; title: string; content: string }[]
}
/** Collections have no per-document "known slug" API like Globals do —
* find-by-slug, then update or create. Idempotent across re-runs. */
async function upsertLegalPage(payload: Payload, slug: string, json: LegalPageJson) {
const existing = await payload.find({
collection: 'legal-pages',
where: { slug: { equals: slug } },
limit: 1,
})
if (existing.docs.length > 0) {
await payload.update({
collection: 'legal-pages',
id: existing.docs[0].id,
data: { slug, ...json },
})
} else {
await payload.create({
collection: 'legal-pages',
data: { slug, ...json },
})
}
}
type PartnerJson = { name: string; url: string; logo: string }
/**
* MITHOME-89 (MVP): a home.json partners.items publikus /partners/*.png
* útvonalait tölti fel Media collection dokumentumként, majd Partner
* rekordot hoz létre/frissít rá hivatkozva. Idempotens: a Media dokumentumot
* `alt` (== partner név) alapján, a Partnert `name` alapján keresi.
*/
async function upsertPartner(payload: Payload, partner: PartnerJson) {
const existingMedia = await payload.find({
collection: 'media',
where: { alt: { equals: partner.name } },
limit: 1,
})
let mediaId: string | number
if (existingMedia.docs.length > 0) {
mediaId = existingMedia.docs[0].id
} else {
const filePath = path.resolve(publicDir, partner.logo.replace(/^\//, ''))
const created = await payload.create({
collection: 'media',
data: { alt: partner.name },
filePath,
})
mediaId = created.id
}
const existingPartner = await payload.find({
collection: 'partners',
where: { name: { equals: partner.name } },
limit: 1,
})
if (existingPartner.docs.length > 0) {
await payload.update({
collection: 'partners',
id: existingPartner.docs[0].id,
data: { name: partner.name, url: partner.url, logo: mediaId },
})
} else {
await payload.create({
collection: 'partners',
data: { name: partner.name, url: partner.url, logo: mediaId },
})
}
}
async function run() {
const payload = await getPayload({ config })
await payload.updateGlobal({ slug: 'home', data: buildHomeData(homeJson) })
payload.logger.info('Home global migrálva')
await payload.updateGlobal({ slug: 'about', data: buildAboutData(aboutJson) })
payload.logger.info('About global migrálva')
await payload.updateGlobal({ slug: 'services', data: buildServicesData(servicesJson) })
payload.logger.info('Services global migrálva')
await payload.updateGlobal({ slug: 'contact', data: contactJson })
payload.logger.info('Contact global migrálva')
await payload.updateGlobal({ slug: 'common', data: commonJson })
payload.logger.info('Common global migrálva')
await upsertLegalPage(payload, 'adatvedelem', adatvedelemJson)
payload.logger.info('LegalPages/adatvedelem migrálva')
await upsertLegalPage(payload, 'hasznalati-feltetelek', hasznalatiFeltetelekJson)
payload.logger.info('LegalPages/hasznalati-feltetelek migrálva')
for (const partner of homeJson.partners.items) {
await upsertPartner(payload, partner)
payload.logger.info(`Partners/${partner.name} migrálva`)
}
payload.logger.info('MITHOME-87/88/89 migráció kész.')
process.exit(0)
}
run().catch((error) => {
console.error('Migráció sikertelen:', error)
process.exit(1)
})