/** * User Context Module * Manages the active user context for per-user config isolation */ import path from "path" import os from "os" import { existsSync, mkdirSync } from "fs" const CONFIG_ROOT = path.join(os.homedir(), ".config", "codenomad") const USERS_ROOT = path.join(CONFIG_ROOT, "users") // Active user ID (set by the main process or HTTP header) let activeUserId: string | null = null /** * Set the active user ID */ export function setActiveUserId(userId: string | null): void { activeUserId = userId console.log(`[UserContext] Active user set to: ${userId || "(none)"}`) } /** * Get the active user ID */ export function getActiveUserId(): string | null { return activeUserId } /** * Get the data root for a specific user * Falls back to global config if no user is set */ export function getUserDataRoot(userId?: string): string { const effectiveUserId = userId || activeUserId if (effectiveUserId) { const userDir = path.join(USERS_ROOT, effectiveUserId) return userDir } // Prioritize environment variable if set (from Electron) const override = process.env.CODENOMAD_USER_DIR if (override && override.trim().length > 0) { return path.resolve(override) } // Fallback to global config root return CONFIG_ROOT } /** * Get the integrations directory for the current or specified user */ export function getUserIntegrationsDir(userId?: string): string { const userRoot = getUserDataRoot(userId) const integrationsDir = path.join(userRoot, "integrations") // Ensure directory exists if (!existsSync(integrationsDir)) { try { mkdirSync(integrationsDir, { recursive: true }) console.log(`[UserContext] Created integrations dir: ${integrationsDir}`) } catch (e) { console.error(`[UserContext] Failed to create integrations dir:`, e) } } return integrationsDir } /** * Get the instances directory for the current or specified user */ export function getUserInstancesDir(userId?: string): string { const userRoot = getUserDataRoot(userId) return path.join(userRoot, "instances") } /** * Get the config file path for a specific integration */ export function getIntegrationConfigPath(integrationId: string, userId?: string): string { const integrationsDir = getUserIntegrationsDir(userId) return path.join(integrationsDir, `${integrationId}-config.json`) } /** * Extract user ID from request headers */ export function getUserIdFromRequest(request: { headers?: Record }): string | null { const header = request.headers?.["x-user-id"] if (typeof header === "string" && header.length > 0) { return header } if (Array.isArray(header) && header.length > 0) { return header[0] } return activeUserId }