Files
portfolio/scripts/migrate-content-pages-to-directus.js
denshooter e431ff50fc feat: Add Directus setup scripts for collections, fields, and relations
- Created setup-directus-collections.js to automate the creation of tech stack collections, fields, and relations in Directus.
- Created setup-directus-hobbies.js for setting up hobbies collection with translations.
- Created setup-directus-projects.js for establishing projects collection with comprehensive fields and translations.
- Added setup-tech-stack-directus.js to populate tech_stack_items with predefined data.
2026-01-23 02:53:31 +01:00

124 lines
3.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Migrate Content Pages from PostgreSQL (Prisma) to Directus
*
* - Copies `content_pages` + translations from Postgres into Directus
* - Creates or updates items per (slug, locale)
*
* Usage:
* DATABASE_URL=postgresql://... DIRECTUS_STATIC_TOKEN=... DIRECTUS_URL=... \
* node scripts/migrate-content-pages-to-directus.js
*/
const fetch = require('node-fetch');
const { PrismaClient } = require('@prisma/client');
require('dotenv').config();
const DIRECTUS_URL = process.env.DIRECTUS_URL || 'https://cms.dk0.dev';
const DIRECTUS_TOKEN = process.env.DIRECTUS_STATIC_TOKEN;
if (!DIRECTUS_TOKEN) {
console.error('❌ Error: DIRECTUS_STATIC_TOKEN not found in env');
process.exit(1);
}
const prisma = new PrismaClient();
const localeMap = {
en: 'en-US',
de: 'de-DE',
};
function toDirectusLocale(locale) {
return localeMap[locale] || locale;
}
async function directusRequest(endpoint, method = 'GET', body = null) {
const url = `${DIRECTUS_URL}/${endpoint}`;
const options = {
method,
headers: {
Authorization: `Bearer ${DIRECTUS_TOKEN}`,
'Content-Type': 'application/json',
},
};
if (body) {
options.body = JSON.stringify(body);
}
const res = await fetch(url, options);
if (!res.ok) {
const text = await res.text();
throw new Error(`HTTP ${res.status} on ${endpoint}: ${text}`);
}
return res.json();
}
async function upsertContentIntoDirectus({ slug, locale, status, title, content }) {
const directusLocale = toDirectusLocale(locale);
// allow locale-specific slug variants: base for en, base-locale for others
const slugVariant = directusLocale === 'en-US' ? slug : `${slug}-${directusLocale.toLowerCase()}`;
const payload = {
slug: slugVariant,
locale: directusLocale,
status: status?.toLowerCase?.() === 'published' ? 'published' : status || 'draft',
title: title || slug,
content: content || null,
};
try {
const { data } = await directusRequest('items/content_pages', 'POST', payload);
console.log(` Created ${slugVariant} (${directusLocale}) [id=${data?.id}]`);
return data?.id;
} catch (error) {
const msg = error?.message || '';
if (msg.includes('already exists') || msg.includes('duplicate key') || msg.includes('UNIQUE')) {
console.log(` ⚠️ Skipping ${slugVariant} (${directusLocale}) already exists`);
return null;
}
throw error;
}
}
async function migrateContentPages() {
console.log('\n📦 Migrating Content Pages from PostgreSQL to Directus...');
const pages = await prisma.contentPage.findMany({
include: { translations: true },
});
console.log(`Found ${pages.length} pages in PostgreSQL`);
for (const page of pages) {
const status = page.status || 'PUBLISHED';
for (const tr of page.translations) {
await upsertContentIntoDirectus({
slug: page.key,
locale: tr.locale,
status,
title: tr.title,
content: tr.content,
});
}
}
console.log('✅ Content page migration finished.');
}
async function main() {
try {
await prisma.$connect();
await migrateContentPages();
} catch (error) {
console.error('❌ Migration failed:', error.message);
process.exit(1);
} finally {
await prisma.$disconnect();
}
}
main();