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:
2026-01-23 02:53:31 +01:00
parent 7604e00e0f
commit e431ff50fc
28 changed files with 5253 additions and 23 deletions

View File

@@ -0,0 +1,151 @@
#!/usr/bin/env node
/**
* Setup tech stack items in Directus
* Creates tech_stack_items collection and populates it with data
*/
const https = require('https');
const DIRECTUS_URL = 'https://cms.dk0.dev';
const DIRECTUS_TOKEN = process.env.DIRECTUS_STATIC_TOKEN || '';
if (!DIRECTUS_TOKEN) {
console.error('❌ DIRECTUS_STATIC_TOKEN not set');
process.exit(1);
}
// Tech stack items to create
const techStackItems = [
// Frontend & Mobile (category 1)
{ category: '1', name: 'Next.js', sort: 1 },
{ category: '1', name: 'Tailwind CSS', sort: 2 },
{ category: '1', name: 'Flutter', sort: 3 },
// Backend & DevOps (category 2)
{ category: '2', name: 'Docker Swarm', sort: 1 },
{ category: '2', name: 'Traefik', sort: 2 },
{ category: '2', name: 'Nginx Proxy Manager', sort: 3 },
{ category: '2', name: 'Redis', sort: 4 },
// Tools & Automation (category 3)
{ category: '3', name: 'Git', sort: 1 },
{ category: '3', name: 'CI/CD', sort: 2 },
{ category: '3', name: 'n8n', sort: 3 },
{ category: '3', name: 'Self-hosted Services', sort: 4 },
// Security & Admin (category 4)
{ category: '4', name: 'CrowdSec', sort: 1 },
{ category: '4', name: 'Suricata', sort: 2 },
{ category: '4', name: 'Mailcow', sort: 3 },
];
async function makeRequest(method, endpoint, body = null) {
return new Promise((resolve, reject) => {
const url = new URL(endpoint, DIRECTUS_URL);
const options = {
hostname: url.hostname,
port: 443,
path: url.pathname + url.search,
method: method,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${DIRECTUS_TOKEN}`,
},
};
const req = https.request(options, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => {
try {
const parsed = JSON.parse(data);
if (res.statusCode >= 400) {
reject(new Error(`HTTP ${res.statusCode}: ${data}`));
} else {
resolve(parsed);
}
} catch (e) {
resolve(data);
}
});
});
req.on('error', reject);
if (body) req.write(JSON.stringify(body));
req.end();
});
}
async function checkCollectionExists() {
try {
const response = await makeRequest('GET', '/api/items/tech_stack_items?limit=1');
if (response.data !== undefined) {
console.log('✅ Collection tech_stack_items already exists');
return true;
}
} catch (e) {
if (e.message.includes('does not exist') || e.message.includes('ROUTE_NOT_FOUND')) {
console.log(' Collection tech_stack_items does not exist yet');
return false;
}
throw e;
}
return false;
}
async function addTechStackItems() {
console.log(`📝 Adding ${techStackItems.length} tech stack items...`);
let created = 0;
for (const item of techStackItems) {
try {
const response = await makeRequest('POST', '/api/items/tech_stack_items', {
category: item.category,
name: item.name,
sort: item.sort,
status: 'published'
});
if (response.data) {
created++;
console.log(` ✅ Created: ${item.name} (category ${item.category})`);
}
} catch (error) {
console.error(` ❌ Failed to create "${item.name}":`, error.message);
}
}
console.log(`\n✅ Successfully created ${created}/${techStackItems.length} items`);
return created === techStackItems.length;
}
async function main() {
try {
console.log('🚀 Setting up Tech Stack in Directus...\n');
const exists = await checkCollectionExists();
if (exists) {
// Count existing items
const response = await makeRequest('GET', '/api/items/tech_stack_items?limit=1000');
const count = response.data?.length || 0;
if (count > 0) {
console.log(`✅ Tech stack already populated with ${count} items`);
return;
}
}
// Add items
await addTechStackItems();
console.log('\n✅ Tech stack setup complete!');
} catch (error) {
console.error('❌ Error setting up tech stack:', error.message);
process.exit(1);
}
}
main();