90 lines
2.6 KiB
JavaScript
90 lines
2.6 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const net = require('net');
|
|
|
|
const root = process.cwd();
|
|
const envPath = path.join(root, '.env');
|
|
|
|
function parseEnv(filePath) {
|
|
if (!fs.existsSync(filePath)) return {};
|
|
const lines = fs.readFileSync(filePath, 'utf8').split(/\r?\n/);
|
|
const env = {};
|
|
|
|
for (const raw of lines) {
|
|
const line = raw.trim();
|
|
if (!line || line.startsWith('#')) continue;
|
|
const idx = line.indexOf('=');
|
|
if (idx <= 0) continue;
|
|
|
|
const key = line.slice(0, idx).trim();
|
|
let value = line.slice(idx + 1).trim();
|
|
|
|
// Strip trailing comments for unquoted values.
|
|
if (!value.startsWith('"') && !value.startsWith("'")) {
|
|
const hashIdx = value.indexOf(' #');
|
|
if (hashIdx >= 0) value = value.slice(0, hashIdx).trim();
|
|
}
|
|
|
|
env[key] = value;
|
|
}
|
|
|
|
return env;
|
|
}
|
|
|
|
function checkPortOpen(port, host = '127.0.0.1', timeoutMs = 500) {
|
|
return new Promise(resolve => {
|
|
const socket = new net.Socket();
|
|
let settled = false;
|
|
|
|
const done = (isOpen) => {
|
|
if (settled) return;
|
|
settled = true;
|
|
socket.destroy();
|
|
resolve(isOpen);
|
|
};
|
|
|
|
socket.setTimeout(timeoutMs);
|
|
socket.once('connect', () => done(true));
|
|
socket.once('timeout', () => done(false));
|
|
socket.once('error', () => done(false));
|
|
socket.connect(Number(port), host);
|
|
});
|
|
}
|
|
|
|
async function run() {
|
|
const env = parseEnv(envPath);
|
|
|
|
const backendPort = env.PORT_BACKEND || '4000';
|
|
const frontendPort = env.PORT_FRONTEND_DEV || '5173';
|
|
const frontendFallback = env.PORT_FRONTEND_DEV_FALLBACK || '5174';
|
|
|
|
const ports = [
|
|
{ name: 'Backend API', key: 'PORT_BACKEND', value: backendPort },
|
|
{ name: 'Frontend dev', key: 'PORT_FRONTEND_DEV', value: frontendPort },
|
|
{ name: 'Frontend fallback', key: 'PORT_FRONTEND_DEV_FALLBACK', value: frontendFallback },
|
|
];
|
|
|
|
console.log('[ports] Dedicated ports for this project');
|
|
console.log(`[ports] Source: ${envPath}`);
|
|
console.log('');
|
|
|
|
for (const p of ports) {
|
|
const isOpen = await checkPortOpen(p.value);
|
|
const state = isOpen ? 'IN USE' : 'free';
|
|
console.log(`[ports] ${p.key}=${p.value} (${p.name}) -> ${state}`);
|
|
}
|
|
|
|
console.log('');
|
|
console.log(`[ports] APP_URL=${env.APP_URL || `http://localhost:${frontendPort}`}`);
|
|
console.log(`[ports] API_BASE=${env.API_BASE || `http://localhost:${backendPort}/api`}`);
|
|
console.log(`[ports] VITE_API_URL=${env.VITE_API_URL || `http://localhost:${backendPort}/api`}`);
|
|
if (env.CORS_ORIGIN) console.log(`[ports] CORS_ORIGIN=${env.CORS_ORIGIN}`);
|
|
}
|
|
|
|
run().catch(err => {
|
|
console.error(`[ports] Failed: ${err.message}`);
|
|
process.exit(1);
|
|
});
|