Import source: backend/src/app
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
import express from 'express';
|
||||
import cors from 'cors';
|
||||
import helmet from 'helmet';
|
||||
import cookieParser from 'cookie-parser';
|
||||
import compression from 'compression';
|
||||
import { pinoHttp } from 'pino-http';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join } from 'node:path';
|
||||
import yaml from 'js-yaml';
|
||||
import fs from 'node:fs';
|
||||
import swaggerUi from 'swagger-ui-express';
|
||||
import { env } from './config/env.js';
|
||||
import { errorHandler, notFoundHandler } from './middleware/errorHandler.js';
|
||||
import { sessionMiddleware } from './middleware/session.js';
|
||||
import { authRouter } from './routes/auth.js';
|
||||
import { dashboardRouter } from './routes/dashboard.js';
|
||||
import { adminRouter } from './routes/admin.js';
|
||||
import { filesRouter } from './routes/files.js';
|
||||
import { linksRouter } from './routes/links.js';
|
||||
import { analyticsRouter } from './routes/analytics.js';
|
||||
import { store } from './services/store.js';
|
||||
import { csrfProtection } from './middleware/csrf.js';
|
||||
import { checkGdriveHealth } from './utils/gdrive.js';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
// yaml.load uses DEFAULT_SCHEMA in js-yaml v4 — no arbitrary code execution
|
||||
const openapiSpec = yaml.load(
|
||||
fs.readFileSync(join(__dirname, 'openapi.yaml'), 'utf8'),
|
||||
{ schema: yaml.DEFAULT_SCHEMA },
|
||||
) as object;
|
||||
|
||||
export async function createApp() {
|
||||
await store.init();
|
||||
|
||||
const app = express();
|
||||
app.disable('x-powered-by');
|
||||
app.set('trust proxy', env.nodeEnv === 'production' ? 1 : false);
|
||||
|
||||
app.use(helmet({
|
||||
crossOriginEmbedderPolicy: false,
|
||||
contentSecurityPolicy: env.nodeEnv === 'production'
|
||||
? {
|
||||
directives: {
|
||||
defaultSrc: ["'none'"],
|
||||
baseUri: ["'none'"],
|
||||
frameAncestors: ["'none'"],
|
||||
formAction: ["'none'"],
|
||||
},
|
||||
}
|
||||
: false,
|
||||
}));
|
||||
app.use(compression());
|
||||
app.use(cors({
|
||||
origin(origin, callback) {
|
||||
if (env.nodeEnv !== 'production' || !origin || origin === env.frontendUrl) {
|
||||
callback(null, true);
|
||||
return;
|
||||
}
|
||||
callback(new Error('Not allowed by CORS'));
|
||||
},
|
||||
credentials: true,
|
||||
}));
|
||||
app.use(pinoHttp({
|
||||
enabled: env.nodeEnv !== 'test',
|
||||
redact: ['req.headers.authorization', 'req.headers.cookie'],
|
||||
}));
|
||||
app.use(express.json({ limit: '1mb' }));
|
||||
app.use(cookieParser());
|
||||
app.use(csrfProtection);
|
||||
app.use(sessionMiddleware);
|
||||
app.use('/api', (_req, res, next) => {
|
||||
res.setHeader('Cache-Control', 'no-store');
|
||||
next();
|
||||
});
|
||||
|
||||
app.get('/health', async (_req, res) => {
|
||||
const [dbOk, gdriveOk] = await Promise.all([
|
||||
store.read().then(() => true).catch(() => false),
|
||||
env.nodeEnv === 'test' ? Promise.resolve(true) : checkGdriveHealth(),
|
||||
]);
|
||||
|
||||
const allOk = dbOk && gdriveOk;
|
||||
res.status(allOk ? 200 : 503).json({
|
||||
status: allOk ? 'ok' : 'degraded',
|
||||
db: dbOk ? 'ok' : 'error',
|
||||
storage: gdriveOk ? 'ok' : 'error',
|
||||
uptime: process.uptime(),
|
||||
version: '0.1.0',
|
||||
});
|
||||
});
|
||||
|
||||
// Swagger UI — only mounted outside production or behind admin routes
|
||||
if (env.nodeEnv !== 'production') {
|
||||
app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(openapiSpec));
|
||||
}
|
||||
// Always expose the raw spec for tooling
|
||||
app.get('/api/openapi.json', (_req, res) => res.json(openapiSpec));
|
||||
|
||||
app.use('/api/auth', authRouter);
|
||||
app.use('/api/admin', adminRouter);
|
||||
app.use('/api/v1', analyticsRouter);
|
||||
app.use('/api/v1/files', filesRouter);
|
||||
app.use('/api/v1/links', linksRouter);
|
||||
app.use('/api/v1/dashboard', dashboardRouter);
|
||||
|
||||
app.use(notFoundHandler);
|
||||
app.use(errorHandler);
|
||||
|
||||
return app;
|
||||
}
|
||||
Reference in New Issue
Block a user