import { accessSync, constants, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'fs'; import { dirname, isAbsolute, join, resolve } from 'path'; import { fileURLToPath } from 'url'; import { randomUUID } from 'crypto'; export const APP_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..'); function envPath(name, fallback) { const value = String(process.env[name] || '').trim(); if (!value) return resolve(fallback); return resolve(isAbsolute(value) ? value : join(APP_ROOT, value)); } export const DATA_ROOT = envPath('VENDOO_DATA_DIR', APP_ROOT); export const DB_PATH = envPath('VENDOO_DB_PATH', join(DATA_ROOT, 'db', 'vendoo.db')); export const UPLOADS_DIR = envPath('VENDOO_UPLOADS_DIR', join(DATA_ROOT, 'uploads')); export const BACKUP_DIR = envPath('VENDOO_BACKUP_DIR', join(DATA_ROOT, 'backups')); export const OPERATIONS_DIR = envPath('VENDOO_OPERATIONS_DIR', join(DATA_ROOT, 'operations')); export const LOG_DIR = envPath('VENDOO_LOG_DIR', join(DATA_ROOT, 'logs')); export const CONFIG_PATH = envPath('VENDOO_CONFIG_PATH', join(DATA_ROOT, 'config', 'vendoo.env')); export const MODULES_DIR = envPath('VENDOO_MODULES_DIR', join(DATA_ROOT, 'modules')); export const MODULE_STATE_PATH = envPath('VENDOO_MODULE_STATE_PATH', join(DATA_ROOT, 'config', 'modules-state.json')); export const APP_VERSION = JSON.parse(readFileSync(join(APP_ROOT, 'package.json'), 'utf8')).version; export function ensureRuntimeDirectories() { const directories = [dirname(DB_PATH), UPLOADS_DIR, BACKUP_DIR, OPERATIONS_DIR, LOG_DIR, dirname(CONFIG_PATH), MODULES_DIR, dirname(MODULE_STATE_PATH)]; for (const directory of directories) mkdirSync(directory, { recursive: true }); return directories; } export function verifyRuntimeWritable() { ensureRuntimeDirectories(); const checks = []; for (const directory of [dirname(DB_PATH), UPLOADS_DIR, BACKUP_DIR, OPERATIONS_DIR, LOG_DIR, dirname(CONFIG_PATH), MODULES_DIR, dirname(MODULE_STATE_PATH)]) { try { accessSync(directory, constants.R_OK | constants.W_OK); const probe = join(directory, `.vendoo-write-${process.pid}-${randomUUID()}.tmp`); writeFileSync(probe, 'ok', { flag: 'wx' }); unlinkSync(probe); checks.push({ path: directory, writable: true }); } catch (error) { checks.push({ path: directory, writable: false, error: error.message }); } } return checks; } export function runtimePathSummary() { return { app_root: APP_ROOT, data_root: DATA_ROOT, database: DB_PATH, uploads: UPLOADS_DIR, backups: BACKUP_DIR, operations: OPERATIONS_DIR, logs: LOG_DIR, runtime_config: CONFIG_PATH, modules: MODULES_DIR, module_state: MODULE_STATE_PATH, }; } ensureRuntimeDirectories();