- 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.
226 lines
7.4 KiB
JavaScript
226 lines
7.4 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Migrate Projects from PostgreSQL to Directus
|
|
*
|
|
* Migriert ALLE bestehenden Projects aus deiner PostgreSQL Datenbank nach Directus
|
|
* inklusive aller Felder und Translations.
|
|
*
|
|
* Usage:
|
|
* node scripts/migrate-projects-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();
|
|
|
|
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);
|
|
}
|
|
|
|
try {
|
|
const response = await fetch(url, options);
|
|
if (!response.ok) {
|
|
const text = await response.text();
|
|
throw new Error(`HTTP ${response.status}: ${text}`);
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error(`Error calling ${method} ${endpoint}:`, error.message);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async function migrateProjects() {
|
|
console.log('\n📦 Migrating Projects from PostgreSQL to Directus...\n');
|
|
|
|
// Load all published projects from PostgreSQL
|
|
const projects = await prisma.project.findMany({
|
|
where: { published: true },
|
|
include: {
|
|
translations: true
|
|
},
|
|
orderBy: { createdAt: 'desc' }
|
|
});
|
|
|
|
console.log(`Found ${projects.length} published projects in PostgreSQL\n`);
|
|
|
|
let successCount = 0;
|
|
let errorCount = 0;
|
|
|
|
for (const project of projects) {
|
|
console.log(`\n📁 Migrating: ${project.title}`);
|
|
|
|
try {
|
|
// 1. Create project in Directus
|
|
console.log(' Creating project...');
|
|
const projectData = {
|
|
slug: project.slug,
|
|
status: 'published',
|
|
featured: project.featured,
|
|
category: project.category,
|
|
difficulty: project.difficulty,
|
|
date: project.date,
|
|
time_to_complete: project.timeToComplete,
|
|
github: project.github,
|
|
live: project.live,
|
|
image_url: project.imageUrl,
|
|
demo_video: project.demoVideo,
|
|
color_scheme: project.colorScheme,
|
|
accessibility: project.accessibility,
|
|
tags: project.tags,
|
|
technologies: project.technologies,
|
|
challenges: project.challenges,
|
|
lessons_learned: project.lessonsLearned,
|
|
future_improvements: project.futureImprovements,
|
|
screenshots: project.screenshots,
|
|
performance: project.performance
|
|
};
|
|
|
|
const { data: createdProject } = await directusRequest(
|
|
'items/projects',
|
|
'POST',
|
|
projectData
|
|
);
|
|
|
|
console.log(` ✅ Project created with ID: ${createdProject.id}`);
|
|
|
|
// 2. Create Translations
|
|
console.log(' Creating translations...');
|
|
|
|
// Default locale translation (from main project fields)
|
|
await directusRequest(
|
|
'items/projects_translations',
|
|
'POST',
|
|
{
|
|
projects_id: createdProject.id,
|
|
languages_code: project.defaultLocale === 'en' ? 'en-US' : 'de-DE',
|
|
title: project.title,
|
|
description: project.description,
|
|
content: project.content,
|
|
meta_description: project.metaDescription,
|
|
keywords: project.keywords
|
|
}
|
|
);
|
|
|
|
// Additional translations from ProjectTranslation table
|
|
for (const translation of project.translations) {
|
|
// Skip if it's the same as default locale (already created above)
|
|
if (translation.locale === project.defaultLocale) {
|
|
continue;
|
|
}
|
|
|
|
await directusRequest(
|
|
'items/projects_translations',
|
|
'POST',
|
|
{
|
|
projects_id: createdProject.id,
|
|
languages_code: translation.locale === 'en' ? 'en-US' : 'de-DE',
|
|
title: translation.title,
|
|
description: translation.description,
|
|
content: translation.content ? JSON.stringify(translation.content) : null,
|
|
meta_description: translation.metaDescription,
|
|
keywords: translation.keywords
|
|
}
|
|
);
|
|
}
|
|
|
|
console.log(` ✅ Translations created (${project.translations.length + 1} locales)`);
|
|
successCount++;
|
|
|
|
} catch (error) {
|
|
console.error(` ❌ Error migrating ${project.title}:`, error.message);
|
|
errorCount++;
|
|
}
|
|
}
|
|
|
|
console.log('\n╔════════════════════════════════════════╗');
|
|
console.log(`║ Migration Complete! ║`);
|
|
console.log('╚════════════════════════════════════════╝\n');
|
|
console.log(`✅ Successfully migrated: ${successCount} projects`);
|
|
console.log(`❌ Failed: ${errorCount} projects\n`);
|
|
|
|
if (successCount > 0) {
|
|
console.log('🎉 Projects are now in Directus!\n');
|
|
console.log('Next steps:');
|
|
console.log(' 1. Visit: https://cms.dk0.dev/admin/content/projects');
|
|
console.log(' 2. Verify all projects are visible');
|
|
console.log(' 3. Update lib/directus.ts with getProjects() function');
|
|
console.log(' 4. Update components to use Directus API\n');
|
|
}
|
|
}
|
|
|
|
async function verifyMigration() {
|
|
console.log('\n🔍 Verifying Migration...\n');
|
|
|
|
try {
|
|
const { data: projects } = await directusRequest(
|
|
'items/projects?fields=slug,status,translations.title,translations.languages_code'
|
|
);
|
|
|
|
console.log(`✅ Found ${projects.length} projects in Directus:`);
|
|
projects.slice(0, 5).forEach(p => {
|
|
const enTitle = p.translations?.find(t => t.languages_code === 'en-US')?.title;
|
|
console.log(` - ${p.slug}: "${enTitle || 'No title'}"`);
|
|
});
|
|
|
|
if (projects.length > 5) {
|
|
console.log(` ... and ${projects.length - 5} more`);
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ Verification failed:', error.message);
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
console.log('\n╔════════════════════════════════════════╗');
|
|
console.log('║ Project Migration: PostgreSQL → Directus ║');
|
|
console.log('╚════════════════════════════════════════╝\n');
|
|
|
|
try {
|
|
// Test database connection first
|
|
console.log('🔍 Testing database connection...');
|
|
await prisma.$connect();
|
|
console.log('✅ Database connected\n');
|
|
|
|
await migrateProjects();
|
|
await verifyMigration();
|
|
} catch (error) {
|
|
if (error.message?.includes("Can't reach database")) {
|
|
console.error('\n❌ PostgreSQL ist nicht erreichbar!');
|
|
console.error('\n💡 Lösungen:');
|
|
console.error(' 1. Starte PostgreSQL: npm run dev');
|
|
console.error(' 2. Oder nutze Docker: docker-compose up -d postgres');
|
|
console.error(' 3. Oder skip diesen Schritt - Projects Collection existiert bereits in Directus\n');
|
|
console.error('Du kannst Projects später manuell in Directus erstellen oder die Migration erneut ausführen.\n');
|
|
process.exit(0); // Graceful exit
|
|
}
|
|
console.error('\n❌ Migration failed:', error);
|
|
process.exit(1);
|
|
} finally {
|
|
await prisma.$disconnect();
|
|
}
|
|
}
|
|
|
|
main();
|