Files
backend/src/website-docs/website-docs.controller.ts
T
Alireza HassaniandCursor 016cc15bf0 Add website API docs, SSL api-hosts, and git-only deploy workflow.
Serve public storefront docs at /docs/website, expose api.{domain} hosts for API SSL sync, and require push-then-pull deploys instead of rsync.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 21:39:51 +03:30

59 lines
1.6 KiB
TypeScript

import {
Controller,
Get,
NotFoundException,
Param,
Res,
} from '@nestjs/common';
import type { Response } from 'express';
import { createReadStream, existsSync } from 'fs';
import { basename, extname, join } from 'path';
import { resolveWebsiteDocsRoot } from './website-docs.paths';
const ALLOWED_FILES = new Set([
'index.html',
'openapi.json',
'AI_PROMPT.md',
'Meshkee-Website-API.postman_collection.json',
'Meshkee-Website-API.global.postman_environment.json',
]);
const CONTENT_TYPES: Record<string, string> = {
'.html': 'text/html; charset=utf-8',
'.json': 'application/json; charset=utf-8',
'.md': 'text/markdown; charset=utf-8',
};
@Controller('docs/website')
export class WebsiteDocsController {
private readonly root = resolveWebsiteDocsRoot();
@Get()
getIndex(@Res() res: Response) {
return this.sendFile(res, 'index.html');
}
@Get(':fileName')
getFile(@Param('fileName') fileName: string, @Res() res: Response) {
const safe = basename(fileName);
if (!ALLOWED_FILES.has(safe)) {
throw new NotFoundException(`Unknown docs file: ${fileName}`);
}
return this.sendFile(res, safe);
}
private sendFile(res: Response, fileName: string) {
const filePath = join(this.root, fileName);
if (!existsSync(filePath)) {
throw new NotFoundException(
`Website docs not found on server (${fileName}). Deploy docs/website-api/ with the API.`,
);
}
const type = CONTENT_TYPES[extname(fileName)] ?? 'application/octet-stream';
res.setHeader('Content-Type', type);
res.setHeader('Cache-Control', 'public, max-age=300');
createReadStream(filePath).pipe(res);
}
}