#!/usr/bin/env node /** * Setup script to initialize the settings collection in Directus * Usage: node directus/setup-settings.js * * This script: * 1. Creates the 'settings' collection * 2. Adds all required fields * 3. Seeds initial data with default values * * Note: Local dev only - no authentication */ const API_URL = process.env.VITE_API_URL || 'http://localhost:8055'; async function createCollection() { console.log('šŸ“¦ Creating settings collection...'); try { const response = await fetch(`${API_URL}/collections`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ collection: 'settings', icon: 'settings', note: 'Global kiosk configuration and settings', fields: [ { field: 'id', type: 'uuid', data_type: 'uuid', primary_key: true, readonly: true, }, { field: 'key', type: 'string', data_type: 'string', required: true, note: 'Unique key identifying this setting group', }, { field: 'title', type: 'string', data_type: 'string', required: true, default_value: 'Guest', note: 'Displayed welcome title', }, { field: 'use_ip_location', type: 'boolean', data_type: 'boolean', default_value: false, note: 'Use IP geolocation or manual location', }, { field: 'manual_location', type: 'string', data_type: 'string', note: 'Manual location string', }, { field: 'idle_timeout_seconds', type: 'integer', data_type: 'integer', default_value: 300, note: 'Seconds before idle screen', }, { field: 'plex_enabled', type: 'boolean', data_type: 'boolean', default_value: true, note: 'Enable Plex integration', }, { field: 'restaurants_enabled', type: 'boolean', data_type: 'boolean', default_value: true, note: 'Show restaurants section', }, { field: 'attractions_enabled', type: 'boolean', data_type: 'boolean', default_value: true, note: 'Show attractions section', }, { field: 'brand_color', type: 'string', data_type: 'string', default_value: '#1f2937', note: 'Primary brand color', }, { field: 'metadata', type: 'json', data_type: 'json', note: 'Custom metadata and settings', }, ], }), }); if (!response.ok) { const error = await response.json(); // Collection might already exist, which is fine if (error.errors?.[0]?.message?.includes('already exists')) { console.log('ā„¹ļø Collection already exists'); return true; } throw new Error(`Failed to create collection: ${error.errors?.[0]?.message || response.statusText}`); } console.log('āœ… Collection created'); return true; } catch (error) { console.error('āŒ Collection creation failed:', error.message); return false; } } async function seedData() { console.log('🌱 Seeding settings data...'); try { // First check if data already exists const checkResponse = await fetch(`${API_URL}/items/settings?filter={"key":"general"}`, { headers: { 'Content-Type': 'application/json', }, }); if (checkResponse.ok) { const checkData = await checkResponse.json(); if (checkData.data?.length > 0) { console.log('ā„¹ļø Settings already exist, updating...'); // Update existing const settingId = checkData.data[0].id; const updateResponse = await fetch(`${API_URL}/items/settings/${settingId}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ title: 'Guest', use_ip_location: false, manual_location: 'Your Hotel', idle_timeout_seconds: 300, plex_enabled: true, restaurants_enabled: true, attractions_enabled: true, brand_color: '#1f2937', metadata: {}, }), }); if (!updateResponse.ok) { throw new Error(`Failed to update settings: ${updateResponse.statusText}`); } console.log('āœ… Settings updated'); return true; } } // Create new settings record const response = await fetch(`${API_URL}/items/settings`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ key: 'general', title: 'Guest', use_ip_location: false, manual_location: 'Your Hotel', idle_timeout_seconds: 300, plex_enabled: true, restaurants_enabled: true, attractions_enabled: true, brand_color: '#1f2937', metadata: {}, }), }); if (!response.ok) { throw new Error(`Failed to seed data: ${response.statusText}`); } console.log('āœ… Settings record created'); return true; } catch (error) { console.error('āŒ Seeding failed:', error.message); return false; } } async function main() { console.log(`\nšŸš€ Setting up Hotel Pi configuration...\n`); console.log(`API URL: ${API_URL}\n`); try { const collectionOk = await createCollection(); if (collectionOk) { await seedData(); console.log('\nāœ… Setup complete! Your settings are ready in Directus.\n'); console.log('šŸ“ You can now edit settings in Directus admin panel:'); console.log(` ${API_URL}/admin/collections/settings\n`); } } catch (error) { console.error('\nāŒ Setup failed:', error.message); process.exit(1); } } main();