mirror of
https://github.com/TheBinaryNinja/tvapp2.git
synced 2026-06-11 23:05:41 -04:00
79 lines
3.2 KiB
JavaScript
79 lines
3.2 KiB
JavaScript
import { existsSync } from 'node:fs';
|
|
import { resolve, dirname } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import express from 'express';
|
|
import { loadConfig } from './config.js';
|
|
import { connect, disconnect } from './db.js';
|
|
import { healthRouter } from './routes/health.js';
|
|
import { playlistsRouter } from './routes/playlists.js';
|
|
import { epgSourcesRouter } from './routes/epgSources.js';
|
|
import { channelsRouter } from './routes/channels.js';
|
|
import { activeStreamsRouter } from './routes/activeStreams.js';
|
|
import { customPlaylistsRouter } from './routes/customPlaylists.js';
|
|
import { programsRouter } from './routes/programs.js';
|
|
import { activityRouter } from './routes/activity.js';
|
|
import { streamSessionsRouter } from './routes/streamSessions.js';
|
|
import { sourcesRouter } from './routes/sources.js';
|
|
import { bootInitSources } from './sources/seed.js';
|
|
async function main() {
|
|
const config = loadConfig();
|
|
try {
|
|
await connect(config.mongoUri);
|
|
}
|
|
catch (err) {
|
|
console.error('[startup] failed to connect to mongo:', err.message);
|
|
process.exit(1);
|
|
}
|
|
// Ingest the established (Default) source playlists: guarantee each from its committed bundle
|
|
// (idempotent), then kick a non-blocking live sync. Runs in both Docker variants via this single
|
|
// boot path. A failure here must not prevent the API from serving.
|
|
try {
|
|
await bootInitSources();
|
|
}
|
|
catch (err) {
|
|
console.error('[startup] source init error (continuing):', err.message);
|
|
}
|
|
const app = express();
|
|
app.use(express.json());
|
|
app.use('/api/health', healthRouter);
|
|
app.use('/api/playlists', playlistsRouter);
|
|
app.use('/api/epg-sources', epgSourcesRouter);
|
|
app.use('/api/channels', channelsRouter);
|
|
app.use('/api/active-streams', activeStreamsRouter);
|
|
app.use('/api/custom-playlists', customPlaylistsRouter);
|
|
app.use('/api/epg-programs', programsRouter);
|
|
app.use('/api/activity', activityRouter);
|
|
app.use('/api/stream-sessions', streamSessionsRouter);
|
|
// Generic source API (manifest, stream proxy, status, sync/reset) — mounted at root since its
|
|
// paths span /api/sources and /api/v1.
|
|
app.use(sourcesRouter);
|
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
const publicDir = resolve(here, '..', 'public');
|
|
if (existsSync(publicDir)) {
|
|
app.use(express.static(publicDir));
|
|
app.get(/^\/(?!api\/).*/, (_req, res) => {
|
|
res.sendFile(resolve(publicDir, 'index.html'));
|
|
});
|
|
console.info(`[http] serving SPA from ${publicDir}`);
|
|
}
|
|
app.use((err, _req, res, _next) => {
|
|
console.error('[api] error:', err.message);
|
|
res.status(500).json({ error: 'internal_error' });
|
|
});
|
|
const server = app.listen(config.port, () => {
|
|
console.info(`[api] listening on :${config.port}`);
|
|
});
|
|
const shutdown = async (signal) => {
|
|
console.info(`[shutdown] received ${signal}`);
|
|
server.close();
|
|
await disconnect();
|
|
process.exit(0);
|
|
};
|
|
process.on('SIGTERM', () => void shutdown('SIGTERM'));
|
|
process.on('SIGINT', () => void shutdown('SIGINT'));
|
|
}
|
|
main().catch((err) => {
|
|
console.error('[startup] fatal:', err);
|
|
process.exit(1);
|
|
});
|
|
//# sourceMappingURL=index.js.map
|