import fs from 'fs-extra'; import path from 'path'; import inquirer from 'inquirer'; import { fileURLToPath } from 'url'; import dotenv from 'dotenv'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const rootDir = path.resolve(__dirname, '..'); const CACHE_DIR = path.join(rootDir, '.cache'); const CONFIG_PATH = path.join(CACHE_DIR, 'config.json'); const MEDIA_TYPES = ['movie', 'show']; const ASSET_TYPES = ['poster', 'backdrop']; dotenv.config({ path: path.resolve(__dirname, '..', '..', '.env') }); export const initConfig = async () => { const existingConfig = await fs.pathExists(CONFIG_PATH) ? await fs.readJson(CONFIG_PATH) : {}; const config = { ...existingConfig }; if (config.storageDir) { const { updateStorage } = await inquirer.prompt([{ type: 'confirm', name: 'updateStorage', message: `Storage directory is already set to "${config.storageDir}". Do you want to update it?`, default: false }]); if (updateStorage) { const { storageDir } = await inquirer.prompt([{ name: 'storageDir', message: 'Where is your storage root directory?', validate: fs.pathExists }]); config.storageDir = storageDir; } } else { const { storageDir } = await inquirer.prompt([{ name: 'storageDir', message: 'Where is your storage root directory?', validate: fs.pathExists }]); config.storageDir = storageDir; } const { customize } = await inquirer.prompt([{ type: 'confirm', name: 'customize', message: 'Do you want to customize default media paths?', default: false }]); config.mediaPaths = {}; for (const mediaType of MEDIA_TYPES) { config.mediaPaths[mediaType] = {}; for (const assetType of ASSET_TYPES) { const mediaFolder = `${mediaType}s`; const assetFolder = assetType === 'poster' ? '' : `/${assetType}s`; const defaultPath = `Media assets/${mediaFolder}${assetFolder}`.replace(/\/$/, ''); let subpath = defaultPath; if (customize) { const response = await inquirer.prompt([{ name: 'subpath', message: `Subpath for ${mediaType}/${assetType} (relative to storage root):`, default: defaultPath }]); subpath = response.subpath; } config.mediaPaths[mediaType][assetType] = subpath; } } config.artistPath = customize ? ( await inquirer.prompt([ { name: 'artistPath', message: 'Subpath for artist images (relative to storage root):', default: 'Media assets/artists' } ]) ).artistPath : 'Media assets/artists'; config.albumPath = customize ? ( await inquirer.prompt([ { name: 'albumPath', message: 'Subpath for album images (relative to storage root):', default: 'Media assets/albums' } ]) ).albumPath : 'Media assets/albums'; config.bookPath = customize ? ( await inquirer.prompt([ { name: 'bookPath', message: 'Subpath for book images (relative to storage root):', default: 'Media assets/books' } ]) ).bookPath : 'Media assets/books'; if (config.directus?.apiUrl) { const { updateApiUrl } = await inquirer.prompt([{ type: 'confirm', name: 'updateApiUrl', message: `Directus API URL is already set to "${config.directus.apiUrl}". Do you want to update it?`, default: false }]); if (updateApiUrl) { const { apiUrl } = await inquirer.prompt([{ name: 'apiUrl', message: 'Enter your Directus instance URL:', validate: input => input.startsWith('http') || 'Must be a valid URL' }]); config.directus.apiUrl = apiUrl; } } else { const { apiUrl } = await inquirer.prompt([{ name: 'apiUrl', message: 'Enter your Directus URL:', validate: input => input.startsWith('http') || 'Must be a valid URL' }]); config.directus = { ...(config.directus || {}), apiUrl }; } config.globals = await fetchGlobals(); await fs.ensureDir(CACHE_DIR); await fs.writeJson(CONFIG_PATH, config, { spaces: 2 }); console.log(`✅ Config saved to ${CONFIG_PATH}`); }; export const loadConfig = async () => { if (!await fs.pathExists(CONFIG_PATH)) { console.error('❌ Config not found. Run `coryd init` first.'); process.exit(1); } return await fs.readJson(CONFIG_PATH); }; const fetchGlobals = async () => { const POSTGREST_URL = process.env.POSTGREST_URL; const POSTGREST_API_KEY = process.env.POSTGREST_API_KEY; if (!POSTGREST_URL || !POSTGREST_API_KEY) { console.warn('⚠️ Missing POSTGREST_URL or POSTGREST_API_KEY in env, skipping globals fetch.'); return {}; } try { const res = await fetch(`${POSTGREST_URL}/optimized_globals?select=*`, { method: 'GET', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${POSTGREST_API_KEY}` } }); if (!res.ok) throw new Error(await res.text()); const data = await res.json(); return data[0] || {}; } catch (err) { console.error('❌ Error fetching globals:', err.message); return {}; } };