@notes-sync/service
Version:
Background service for AI-powered note synchronization
162 lines • 6.35 kB
JavaScript
;
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