UNPKG

@notes-sync/service

Version:

Background service for AI-powered note synchronization

162 lines 6.35 kB
#!/usr/bin/env node "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.main = main; const server_1 = require("./server"); const watcher_1 = require("./watcher"); const config_1 = require("./config"); const git_1 = require("./git"); const logger_1 = require("./logger"); const note_interactor_1 = require("./note-interactor"); const ai_service_1 = require("./ai/ai-service"); const wake_detect_1 = require("./wake-detect"); const path_1 = __importDefault(require("path")); // Handle install/uninstall commands if (process.argv.includes('install')) { require(path_1.default.join(__dirname, '..', 'scripts', 'install-service.js')); // The install script will handle its own exit } else if (process.argv.includes('uninstall')) { require(path_1.default.join(__dirname, '..', 'scripts', 'uninstall-service.js')); // The uninstall script will handle its own exit } else { // Only run the main service if not installing/uninstalling main().catch(error => { logger_1.Logger.error(`Service failed: ${error.message}`); process.exit(1); }); } async function main() { logger_1.Logger.log('Notes Sync Service starting...'); // Load configuration const config = (0, config_1.loadConfig)(); logger_1.Logger.log(`Config loaded: watching ${config.notesDir}`); /////////////////////////// // GIT INIT ////////////////////////// if (!(0, git_1.isGitRepo)(config.notesDir)) { logger_1.Logger.error(`NOTES_DIR is not a Git repo: ${config.notesDir}`); process.exit(1); } const git = (0, git_1.createGit)(config.notesDir); const hasOrigin = await (0, git_1.hasOriginRemote)(git); if (!hasOrigin) { logger_1.Logger.error('No "origin" remote configured. Please set it to your GitHub repo.'); process.exit(1); } /////////////////////////// // SYNC INIT ////////////////////////// await (0, git_1.safeSync)(git, 'initial'); // Setup debounced sync let debounceTimer = null; let pendingEvents = 0; const scheduleSync = (reason) => { pendingEvents += 1; if (debounceTimer) clearTimeout(debounceTimer); debounceTimer = setTimeout(async () => { const count = pendingEvents; pendingEvents = 0; await (0, git_1.safeSync)(git, `${reason}:${count}`); }, config.debounceMs); }; /////////////////////////// // INIT AI SERVICE ////////////////////////// let aiService; if (config.ai) { try { aiService = new ai_service_1.AIService(config.ai); if (aiService.isEnabled()) { logger_1.Logger.log(`AI Service initialized with ${config.ai.provider} provider`); } else { logger_1.Logger.log('AI Service initialized but disabled (no API key)'); } } catch (error) { logger_1.Logger.error(`Failed to initialize AI service: ${error.message}`); } } /////////////////////////// // INIT NOTE INTERACTOR ////////////////////////// const noteInteractor = new note_interactor_1.NoteInteractor(config.notesDir, config.notesFile || 'Daily.md', aiService); // Auto-create today's section on startup (if enabled) if (config.autoCreateDaily !== false) { // Default to true logger_1.Logger.log('Checking for missing daily sections...'); const result = await noteInteractor.autoCreateDailySection(); if (result.created) { logger_1.Logger.log(`Daily section auto-created: ${result.reason}`); scheduleSync('auto-daily-startup'); } else { logger_1.Logger.log(`Daily section check: ${result.reason}`); } } /////////////////////////// // SETUP WAKE DETECTION ////////////////////////// if (config.wakeDetection?.enabled !== false) { // Default to true const wakeConfig = config.wakeDetection || { enabled: true, intervalMs: 20000, thresholdMs: 20000, }; const intervalMs = wakeConfig.intervalMs || 20000; const thresholdMs = wakeConfig.thresholdMs || 20000; logger_1.Logger.log(`Starting wake detection (interval: ${intervalMs}ms, threshold: ${thresholdMs}ms)`); wake_detect_1.WakeDetector.onWake(async () => { logger_1.Logger.log('Wake detected! Checking for new daily section...'); // Auto-create daily section on wake const result = await noteInteractor.autoCreateDailySection(); if (result.created) { logger_1.Logger.log(`Daily section created on wake: ${result.reason}`); scheduleSync('auto-daily-wake'); } else { logger_1.Logger.log(`No daily section needed: ${result.reason}`); } }); wake_detect_1.WakeDetector.start(intervalMs); } /////////////////////////// // START HTTP SERVER ////////////////////////// const server = (0, server_1.createServer)(config, scheduleSync, noteInteractor); try { await server.listen({ port: config.server.port, host: config.server.host }); logger_1.Logger.log(`Server listening on http://${config.server.host}:${config.server.port}`); } catch (err) { logger_1.Logger.error('Failed to start server:', err); process.exit(1); } /////////////////////////// // START FILE WATCHER ////////////////////////// const watcher = new watcher_1.FileWatcher(); watcher.start(config.notesDir, config.glob, config.ignore, () => { scheduleSync('file-change'); }); /////////////////////////// // SHUTDOWN HANDLING ////////////////////////// const shutdown = async (signal) => { logger_1.Logger.log(`${signal} received, shutting down gracefully...`); watcher.stop(); wake_detect_1.WakeDetector.stop(); await server.close(); process.exit(0); }; process.on('SIGINT', () => shutdown('SIGINT')); process.on('SIGTERM', () => shutdown('SIGTERM')); } //# sourceMappingURL=main.js.map