#!/usr/bin/env bun /** * Profile Management System * * Manages numerology profiles stored in ~/.numerology/profiles/ * Each profile contains name and birthdate for easy reuse across all tools. * * Usage: * import { loadProfile, saveProfile, listProfiles, deleteProfile } from './profile-manager'; */ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, unlinkSync } from 'fs'; import { join } from 'path'; import { homedir } from 'os'; export interface Profile { name: string; birthdate: string; created: string; updated: string; } const PROFILES_DIR = join(homedir(), '.numerology', 'profiles'); /** * Ensure profiles directory exists */ function ensureProfilesDir(): void { if (!existsSync(PROFILES_DIR)) { mkdirSync(PROFILES_DIR, { recursive: true }); } } /** * Generate profile filename from identifier */ function getProfilePath(identifier: string): string { // Sanitize identifier to create safe filename const safeName = identifier.toLowerCase().replace(/[^a-z0-9-_]/g, '-'); return join(PROFILES_DIR, `${safeName}.json`); } /** * Save a profile */ export function saveProfile(identifier: string, name: string, birthdate: string): void { ensureProfilesDir(); const profilePath = getProfilePath(identifier); const now = new Date().toISOString(); // Check if profile exists to preserve created date let created = now; if (existsSync(profilePath)) { try { const existing = JSON.parse(readFileSync(profilePath, 'utf-8')) as Profile; created = existing.created; } catch { // If file is corrupted, use current time } } const profile: Profile = { name, birthdate, created, updated: now }; writeFileSync(profilePath, JSON.stringify(profile, null, 2)); } /** * Load a profile */ export function loadProfile(identifier: string): Profile | null { const profilePath = getProfilePath(identifier); if (!existsSync(profilePath)) { return null; } try { const data = readFileSync(profilePath, 'utf-8'); return JSON.parse(data) as Profile; } catch (error) { console.error(`Error reading profile '${identifier}':`, error); return null; } } /** * List all profiles */ export function listProfiles(): Array<{ identifier: string; profile: Profile }> { ensureProfilesDir(); const profiles: Array<{ identifier: string; profile: Profile }> = []; try { const files = readdirSync(PROFILES_DIR); for (const file of files) { if (file.endsWith('.json')) { const identifier = file.replace('.json', ''); const profile = loadProfile(identifier); if (profile) { profiles.push({ identifier, profile }); } } } } catch (error) { console.error('Error listing profiles:', error); } return profiles; } /** * Delete a profile */ export function deleteProfile(identifier: string): boolean { const profilePath = getProfilePath(identifier); if (!existsSync(profilePath)) { return false; } try { unlinkSync(profilePath); return true; } catch (error) { console.error(`Error deleting profile '${identifier}':`, error); return false; } } /** * Check if a profile exists */ export function profileExists(identifier: string): boolean { return existsSync(getProfilePath(identifier)); } /** * Get profile identifier from name (for auto-generation) */ export function generateIdentifier(name: string): string { // Generate identifier from first name const firstName = name.split(' ')[0]; return firstName.toLowerCase().replace(/[^a-z0-9]/g, ''); }