Files
bible-app/watch-and-build.js
T
christianandClaude Opus 5 0db5e9b07d Bible App 1.4.34 — full source
First commit on the local Gitea server, made after moving the tree off the
Windows machine. Build outputs, node_modules and the AI models stay out
(see .gitignore); everything the installer build needs is tracked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-24 13:05:20 -04:00

141 lines
3.9 KiB
JavaScript

// Auto-build script that watches for file changes and runs build-installer.bat
// Note: Using CommonJS require() - rename to .cjs if package.json has "type": "module"
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
// Directories/files to watch
const watchPaths = [
'app.js',
'main.cjs',
'main.js',
'preload.cjs',
'preload.js',
'server.js',
'index.html',
'styles.css',
'init.js',
'*.js',
'*.html',
'*.css',
'*.json'
];
// Directories to ignore
const ignorePaths = [
'node_modules',
'dist',
'dist-installer',
'.git',
'Notes',
'Graphics',
'Announcements'
];
let buildTimeout = null;
let isBuilding = false;
const DEBOUNCE_MS = 3000; // Wait 3 seconds after last change before building
console.log('=== Bible App Auto-Builder ===');
console.log('Watching for file changes...');
console.log('Press Ctrl+C to stop\n');
// Simple file watcher using fs.watch
function watchDirectory(dir) {
try {
const watcher = fs.watch(dir, { recursive: true }, (eventType, filename) => {
if (!filename) return;
const fullPath = path.join(dir, filename);
// Check if path should be ignored
const shouldIgnore = ignorePaths.some(ignore =>
fullPath.includes(ignore) || filename.includes(ignore)
);
if (shouldIgnore) return;
// Only watch for changes to relevant files
const ext = path.extname(filename).toLowerCase();
const isRelevantFile = ['.js', '.html', '.css', '.json', '.cjs'].includes(ext) ||
['app.js', 'main.cjs', 'main.js', 'server.js', 'index.html', 'styles.css'].includes(filename);
if (!isRelevantFile && ext !== '') return;
// Ignore temporary files
if (filename.includes('~') || filename.startsWith('.')) return;
console.log(`\n[${new Date().toLocaleTimeString()}] Change detected: ${filename}`);
// Debounce: clear previous timeout and set new one
if (buildTimeout) {
clearTimeout(buildTimeout);
}
buildTimeout = setTimeout(() => {
if (!isBuilding) {
runBuild();
}
}, DEBOUNCE_MS);
});
return watcher;
} catch (err) {
// Directory might not exist or not accessible
return null;
}
}
function runBuild() {
if (isBuilding) {
console.log('Build already in progress, skipping...');
return;
}
isBuilding = true;
console.log('\n=== Starting automatic build ===');
console.log(`[${new Date().toLocaleTimeString()}] Running build-installer.bat...\n`);
const buildProcess = spawn('build-installer.bat', [], {
cwd: __dirname,
shell: true,
stdio: 'inherit'
});
buildProcess.on('close', (code) => {
isBuilding = false;
if (code === 0) {
console.log(`\n[${new Date().toLocaleTimeString()}] Build completed successfully!`);
} else {
console.log(`\n[${new Date().toLocaleTimeString()}] Build failed with code ${code}`);
}
console.log('Watching for more changes...\n');
});
buildProcess.on('error', (err) => {
isBuilding = false;
console.error(`\n[${new Date().toLocaleTimeString()}] Build error:`, err.message);
console.log('Watching for more changes...\n');
});
}
// Start watching the current directory
const watcher = watchDirectory(__dirname);
if (!watcher) {
console.error('Failed to start file watcher');
process.exit(1);
}
// Handle cleanup
process.on('SIGINT', () => {
console.log('\n\nStopping file watcher...');
if (watcher) watcher.close();
if (buildTimeout) clearTimeout(buildTimeout);
process.exit(0);
});
console.log('File watcher started. Make changes to your files to trigger automatic builds.');
console.log('(Changes are debounced - build starts 3 seconds after last change)\n');