selfhostedbg-web/scripts/dev-with-port.js

80 lines
2.1 KiB
JavaScript

/**
* Astro server launcher with automatic port detection
* Checks if port 5000 is available, falls back to 5001 if occupied
* Supports both 'dev' and 'preview' commands
*/
import { spawn } from 'node:child_process';
import { createServer } from 'node:net';
import { fileURLToPath } from 'node:url';
import path from 'node:path';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const projectRoot = path.resolve(__dirname, '..');
function checkPort(port) {
return new Promise((resolve) => {
const server = createServer();
server.listen(port, () => {
server.once('close', () => {
resolve(true); // Port is available
});
server.close();
});
server.on('error', () => {
resolve(false); // Port is occupied
});
});
}
async function getAvailablePort() {
const port5000Available = await checkPort(5000);
if (port5000Available) {
return 5000;
} else {
// Port 5000 is occupied (likely AirPlay on macOS)
console.log('⚠️ Port 5000 is occupied, using port 5001 instead');
return 5001;
}
}
async function main() {
// Get command from first argument (defaults to 'dev')
const command = process.argv[2] || 'dev';
if (!['dev', 'preview'].includes(command)) {
console.error(`Invalid command: ${command}. Must be 'dev' or 'preview'.`);
process.exit(1);
}
const port = await getAvailablePort();
// Use pnpm exec to ensure we use the local Astro installation
// On Windows, use 'pnpm.cmd', on Unix use 'pnpm'
const pnpmCmd = process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm';
// Spawn astro with the detected port
const astroProcess = spawn(pnpmCmd, ['exec', 'astro', command, '--host', '0.0.0.0', '--port', port.toString()], {
cwd: projectRoot,
stdio: 'inherit',
shell: true
});
astroProcess.on('error', (error) => {
console.error(`Failed to start Astro ${command} server:`, error);
process.exit(1);
});
astroProcess.on('exit', (code) => {
process.exit(code || 0);
});
}
main().catch((error) => {
console.error('Error:', error);
process.exit(1);
});