39948-vm/backend/watcher.ts
2026-07-01 15:45:38 +02:00

109 lines
2.6 KiB
TypeScript

import chokidar from 'chokidar';
import { exec } from 'node:child_process';
import type { ExecException } from 'node:child_process';
import nodemon from 'nodemon';
import { logger } from './src/utils/logger.ts';
const nodeEnv = process.env.NODE_ENV || 'dev_stage';
const childEnv = buildChildEnv(process.env, nodeEnv);
const log = logger.child({ module: 'watcher' });
function buildChildEnv(
env: NodeJS.ProcessEnv,
fallbackNodeEnv: string,
): Record<string, string> {
const child: Record<string, string> = {};
for (const [key, value] of Object.entries(env)) {
if (value !== undefined) {
child[key] = value;
}
}
child.NODE_ENV = fallbackNodeEnv;
return child;
}
function logCommandResult(
error: ExecException | null,
stdout: string,
stderr: string,
successMessage: string,
): void {
const output = stdout.trim();
const errorOutput = stderr.trim();
if (output) {
log.info({ output }, successMessage);
}
if (error) {
log.error(
{ err: error, stderr: errorOutput },
'Watched database command failed',
);
} else if (errorOutput) {
log.warn({ stderr: errorOutput }, 'Watched database command wrote stderr');
}
}
const migrationsWatcher = chokidar.watch('./src/db/migrations', {
persistent: true,
ignoreInitial: true,
usePolling: true,
interval: 1000,
});
migrationsWatcher.on('error', (error) => {
log.error({ err: error }, 'Migrations watcher failed');
});
migrationsWatcher.on('add', (filePath) => {
log.info({ filePath }, 'New migration file detected');
exec('npm run db:migrate', { env: childEnv }, (error, stdout, stderr) => {
logCommandResult(error, stdout, stderr, 'Migration command completed');
});
});
const seedersWatcher = chokidar.watch('./src/db/seeders', {
persistent: true,
ignoreInitial: true,
usePolling: true,
interval: 1000,
});
seedersWatcher.on('error', (error) => {
log.error({ err: error }, 'Seeders watcher failed');
});
seedersWatcher.on('add', (filePath) => {
log.info({ filePath }, 'New seed file detected');
exec('npm run db:seed', { env: childEnv }, (error, stdout, stderr) => {
logCommandResult(error, stdout, stderr, 'Seeder command completed');
});
});
nodemon({
script: './src/index.ts',
exec: 'node',
env: childEnv,
watch: ['./src'],
ext: 'js,ts,json',
ignore: [
'./src/db/migrations',
'./src/db/seeders',
'./dist',
'./node_modules',
],
delay: 500,
});
nodemon.on('start', () => {
log.info({ nodeEnv }, 'Nodemon started');
});
nodemon.on('restart', (files) => {
log.info({ files }, 'Nodemon restarted due to file changes');
});
nodemon.on('crash', () => {
log.error('Nodemon app crashed');
});