Files
portfolio/scripts/setup-directus-hobbies.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

286 lines
7.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Directus Hobbies Collection Setup via REST API
*
* Erstellt die Hobbies Collection mit Translations
*
* Usage:
* node scripts/setup-directus-hobbies.js
*/
const fetch = require('node-fetch');
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);
}
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);
const text = await response.text();
if (!response.ok) {
if (text.includes('already exists') || text.includes('RECORD_NOT_UNIQUE')) {
console.log(` ⚠️ Already exists, skipping...`);
return { data: null, alreadyExists: true };
}
throw new Error(`HTTP ${response.status}: ${text}`);
}
return text ? JSON.parse(text) : {};
} catch (error) {
console.error(`❌ Error calling ${method} ${endpoint}:`, error.message);
throw error;
}
}
async function createHobbiesCollections() {
console.log('\n📦 Creating Hobbies Collections...\n');
console.log('1⃣ Creating hobbies...');
try {
await directusRequest('collections', 'POST', {
collection: 'hobbies',
meta: {
icon: 'sports_esports',
display_template: '{{translations.title}}',
hidden: false,
singleton: false,
sort_field: 'sort'
},
schema: {
name: 'hobbies'
}
});
console.log(' ✅ Collection created');
} catch (error) {
console.log(' ⚠️ Collection might already exist');
}
console.log('\n2⃣ Creating hobbies_translations...');
try {
await directusRequest('collections', 'POST', {
collection: 'hobbies_translations',
meta: {
hidden: true,
icon: 'import_export'
},
schema: {
name: 'hobbies_translations'
}
});
console.log(' ✅ Collection created');
} catch (error) {
console.log(' ⚠️ Collection might already exist');
}
}
async function createHobbyFields() {
console.log('\n🔧 Creating Fields...\n');
const hobbyFields = [
{
field: 'status',
type: 'string',
meta: {
interface: 'select-dropdown',
options: {
choices: [
{ text: 'Published', value: 'published' },
{ text: 'Draft', value: 'draft' }
]
}
},
schema: { default_value: 'draft', is_nullable: false }
},
{
field: 'sort',
type: 'integer',
meta: { interface: 'input', hidden: true },
schema: {}
},
{
field: 'key',
type: 'string',
meta: {
interface: 'input',
note: 'Unique identifier (e.g. self_hosting, gaming)'
},
schema: { is_unique: true, is_nullable: false }
},
{
field: 'icon',
type: 'string',
meta: {
interface: 'select-dropdown',
options: {
choices: [
{ text: 'Code', value: 'Code' },
{ text: 'Gamepad2', value: 'Gamepad2' },
{ text: 'Server', value: 'Server' },
{ text: 'Activity', value: 'Activity' }
]
}
},
schema: { default_value: 'Code' }
},
{
field: 'date_created',
type: 'timestamp',
meta: { special: ['date-created'], interface: 'datetime', readonly: true, hidden: true },
schema: {}
},
{
field: 'date_updated',
type: 'timestamp',
meta: { special: ['date-updated'], interface: 'datetime', readonly: true, hidden: true },
schema: {}
},
{
field: 'translations',
type: 'alias',
meta: {
special: ['translations'],
interface: 'translations',
options: { languageField: 'languages_code' }
}
}
];
console.log('Adding fields to hobbies:');
for (const field of hobbyFields) {
try {
await directusRequest('fields/hobbies', 'POST', field);
console.log(`${field.field}`);
} catch (error) {
console.log(` ⚠️ ${field.field} (might already exist)`);
}
}
const translationFields = [
{
field: 'hobbies_id',
type: 'uuid',
meta: { hidden: true },
schema: {}
},
{
field: 'languages_code',
type: 'string',
meta: { interface: 'select-dropdown-m2o' },
schema: {}
},
{
field: 'title',
type: 'string',
meta: {
interface: 'input',
note: 'Hobby title'
},
schema: {}
},
{
field: 'description',
type: 'text',
meta: {
interface: 'input-multiline',
note: 'Hobby description (optional)'
},
schema: {}
}
];
console.log('\nAdding fields to hobbies_translations:');
for (const field of translationFields) {
try {
await directusRequest('fields/hobbies_translations', 'POST', field);
console.log(`${field.field}`);
} catch (error) {
console.log(` ⚠️ ${field.field} (might already exist)`);
}
}
}
async function createHobbyRelations() {
console.log('\n🔗 Creating Relations...\n');
const relations = [
{
collection: 'hobbies_translations',
field: 'hobbies_id',
related_collection: 'hobbies',
meta: {
one_field: 'translations',
sort_field: null,
one_deselect_action: 'delete'
},
schema: { on_delete: 'CASCADE' }
},
{
collection: 'hobbies_translations',
field: 'languages_code',
related_collection: 'languages',
meta: {
one_field: null,
sort_field: null,
one_deselect_action: 'nullify'
},
schema: { on_delete: 'SET NULL' }
}
];
for (let i = 0; i < relations.length; i++) {
try {
await directusRequest('relations', 'POST', relations[i]);
console.log(` ✅ Relation ${i + 1}/${relations.length}`);
} catch (error) {
console.log(` ⚠️ Relation ${i + 1}/${relations.length} (might already exist)`);
}
}
}
async function main() {
console.log('\n╔════════════════════════════════════════╗');
console.log('║ Directus Hobbies Setup via API ║');
console.log('╚════════════════════════════════════════╝\n');
try {
await createHobbiesCollections();
await createHobbyFields();
await createHobbyRelations();
console.log('\n╔════════════════════════════════════════╗');
console.log('║ ✅ Setup Complete! ║');
console.log('╚════════════════════════════════════════╝\n');
console.log('🎉 Hobbies Collection ist bereit!\n');
console.log('Nächste Schritte:');
console.log(' 1. Führe aus: node scripts/migrate-hobbies-to-directus.js');
console.log(' 2. Verifiziere: https://cms.dk0.dev/admin/content/hobbies\n');
} catch (error) {
console.error('\n❌ Setup failed:', error);
process.exit(1);
}
}
main();