102 lines
2.6 KiB
TypeScript
102 lines
2.6 KiB
TypeScript
import express from 'express';
|
|
import { CatalogDatabase } from '../database/store.js';
|
|
import { dashboard, page, table } from './views.js';
|
|
|
|
export function createWebApp(databasePath: string) {
|
|
const app = express();
|
|
|
|
app.get('/', (_req, res, next) => {
|
|
withDatabase(databasePath, (db) => res.send(dashboard(db.dashboardCounts()))).catch(next);
|
|
});
|
|
|
|
app.get('/links', (_req, res, next) => {
|
|
withDatabase(databasePath, (db) =>
|
|
res.send(
|
|
page(
|
|
'Links',
|
|
`<h1>Links</h1>${table(db.contentLinks(), [
|
|
['newsletter', 'Newsletter'],
|
|
['issueDate', 'Issue Date'],
|
|
['category', 'Category'],
|
|
['title', 'Title'],
|
|
['url', 'URL'],
|
|
['description', 'Description']
|
|
])}`
|
|
)
|
|
)
|
|
).catch(next);
|
|
});
|
|
|
|
app.get('/sponsors', (_req, res, next) => {
|
|
withDatabase(databasePath, (db) =>
|
|
res.send(
|
|
page(
|
|
'Sponsored Links',
|
|
`<h1>Sponsored Links</h1>${table(db.sponsoredLinks(), [
|
|
['newsletter', 'Newsletter'],
|
|
['sponsor', 'Sponsor'],
|
|
['description', 'Description']
|
|
])}`
|
|
)
|
|
)
|
|
).catch(next);
|
|
});
|
|
|
|
app.get('/dead-links', (_req, res, next) => {
|
|
withDatabase(databasePath, (db) =>
|
|
res.send(
|
|
page(
|
|
'Dead Links',
|
|
`<h1>Dead Links</h1>${table(db.deadLinks(), [
|
|
['url', 'URL'],
|
|
['status', 'Status'],
|
|
['source', 'Source'],
|
|
['date', 'Date']
|
|
])}`
|
|
)
|
|
)
|
|
).catch(next);
|
|
});
|
|
|
|
app.get('/runs', (_req, res, next) => {
|
|
withDatabase(databasePath, (db) =>
|
|
res.send(
|
|
page(
|
|
'Runs',
|
|
`<h1>Runs</h1>${table(db.runs(), [
|
|
['started_at', 'Started'],
|
|
['mode', 'Mode'],
|
|
['newsletters_processed', 'Newsletters'],
|
|
['links_extracted', 'Links'],
|
|
['sponsors', 'Sponsors'],
|
|
['dead_links', 'Dead Links'],
|
|
['errors', 'Errors']
|
|
])}`
|
|
)
|
|
)
|
|
).catch(next);
|
|
});
|
|
|
|
app.use(
|
|
(error: Error, _req: express.Request, res: express.Response, _next: express.NextFunction) => {
|
|
console.error(error);
|
|
res.status(500).send(page('Error', '<h1>Error</h1><p>Something went wrong.</p>'));
|
|
}
|
|
);
|
|
|
|
return app;
|
|
}
|
|
|
|
async function withDatabase(
|
|
databasePath: string,
|
|
callback: (database: CatalogDatabase) => void
|
|
): Promise<void> {
|
|
const db = new CatalogDatabase(databasePath);
|
|
try {
|
|
db.migrate();
|
|
callback(db);
|
|
} finally {
|
|
db.close();
|
|
}
|
|
}
|