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.
This commit is contained in:
285
scripts/setup-directus-hobbies.js
Normal file
285
scripts/setup-directus-hobbies.js
Normal file
@@ -0,0 +1,285 @@
|
||||
#!/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();
|
||||
Reference in New Issue
Block a user