- 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.
152 lines
4.1 KiB
JavaScript
152 lines
4.1 KiB
JavaScript
#!/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();
|