AeThex-OS/server/download-routes.ts
MrPiglr 66ad61b8a0 fix(server): add root healthcheck endpoint for Railway deployment
- Add root '/' endpoint that responds with JSON status
- Make download routes handle missing installers gracefully
- Add error handling around download routes registration
- Add logging for download routes initialization

Fixes Railway healthcheck failures by ensuring server responds at root path
2026-02-12 12:55:59 -07:00

129 lines
3.6 KiB
TypeScript

import express from 'express';
import path from 'path';
import fs from 'fs';
const router = express.Router();
// Desktop app download endpoint
router.get('/desktop', async (req, res) => {
try {
// Path to the installer
const installerPath = path.join(
process.cwd(),
'shell',
'aethex-shell',
'src-tauri',
'target',
'release',
'bundle',
'nsis',
'AeThex-OS_0.1.0_x64-setup.exe'
);
// Check if file exists
if (!fs.existsSync(installerPath)) {
console.log('[Download] Installer not found at', installerPath);
return res.status(404).json({
error: 'Installer not available',
message: 'The desktop installer is not yet available. It will be uploaded soon.',
note: 'For development: Run "npm run build:tauri" in shell/aethex-shell to build the installer'
});
}
// Get file stats
const stats = fs.statSync(installerPath);
// Set headers
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', 'attachment; filename="AeThex-OS-setup.exe"');
res.setHeader('Content-Length', stats.size);
// Stream the file
const fileStream = fs.createReadStream(installerPath);
fileStream.pipe(res);
fileStream.on('error', (error) => {
console.error('Error streaming installer:', error);
if (!res.headersSent) {
res.status(500).json({ error: 'Failed to download installer' });
}
});
// Log download
console.log(`[Download] Desktop installer downloaded by ${req.ip}`);
} catch (error) {
console.error('Error serving installer:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
// Get latest version info (for auto-update checks)
router.get('/version', async (req, res) => {
try {
// Read version from package.json
const packagePath = path.join(
process.cwd(),
'shell',
'aethex-shell',
'package.json'
);
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
res.json({
version: packageJson.version,
releaseDate: new Date().toISOString(),
downloadUrl: `${req.protocol}://${req.get('host')}/api/download/desktop`,
releaseNotes: [
'Initial MVP release',
'Full IDE with Monaco editor',
'Terminal integration',
'AeThex Language compiler',
'Compliance tools built-in'
],
minimumVersion: '0.1.0'
});
} catch (error) {
console.error('Error fetching version info:', error);
res.status(500).json({ error: 'Failed to fetch version info' });
}
});
// MSI installer download
router.get('/desktop/msi', async (req, res) => {
try {
const installerPath = path.join(
process.cwd(),
'shell',
'aethex-shell',
'src-tauri',
'target',
'release',
'bundle',
'msi',
'AeThex-OS_0.1.0_x64_en-US.msi'
);
if (!fs.existsSync(installerPath)) {
return res.status(404).json({ error: 'MSI installer not found' });
}
const stats = fs.statSync(installerPath);
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', 'attachment; filename="AeThex-OS-setup.msi"');
res.setHeader('Content-Length', stats.size);
const fileStream = fs.createReadStream(installerPath);
fileStream.pipe(res);
console.log(`[Download] MSI installer downloaded by ${req.ip}`);
} catch (error) {
console.error('Error serving MSI installer:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
export default router;