feat: Add browser documentation

This commit is contained in:
2026-04-29 17:15:01 +02:00
parent d261bac0ed
commit 3d81c34159
29 changed files with 19981 additions and 40 deletions

View File

@@ -1,4 +1,9 @@
import { createServer, IncomingMessage, Server, ServerResponse } from 'http';
import {
createServer,
IncomingMessage,
Server,
ServerResponse
} from 'http';
import { createReadStream } from 'fs';
import { AddressInfo } from 'net';
import { pipeline } from 'stream/promises';
@@ -26,6 +31,7 @@ export interface LocalApiSnapshot {
error: string | null;
exposeOnLan: boolean;
scalarEnabled: boolean;
docusaurusEnabled: boolean;
}
let server: Server | null = null;
@@ -41,6 +47,7 @@ function pickBindHost(settings: LocalApiSettings): string {
function buildBaseUrl(host: string, port: number): string {
const safeHost = host === '0.0.0.0' ? '127.0.0.1' : host;
return `http://${safeHost}:${port}`;
}
@@ -64,7 +71,8 @@ export function getLocalApiSnapshot(): LocalApiSnapshot {
baseUrl: currentBindHost && currentBindPort ? buildBaseUrl(currentBindHost, currentBindPort) : null,
error: currentError,
exposeOnLan: settings.exposeOnLan,
scalarEnabled: settings.scalarEnabled
scalarEnabled: settings.scalarEnabled,
docusaurusEnabled: settings.docusaurusEnabled
};
}
@@ -101,7 +109,6 @@ async function handleRequest(req: IncomingMessage, res: ServerResponse, settings
remoteAddress: req.socket.remoteAddress ?? '',
bearerToken: getBearerToken(req.headers)
};
const { match, methodNotAllowed } = matchRoute(requestContext.method, requestContext.pathname);
if (!match) {
@@ -110,6 +117,7 @@ async function handleRequest(req: IncomingMessage, res: ServerResponse, settings
} else {
sendJson(res, 404, { error: 'Not found', errorCode: 'NOT_FOUND' });
}
return;
}
@@ -122,9 +130,9 @@ async function handleRequest(req: IncomingMessage, res: ServerResponse, settings
}
}
const dataSource = getDataSource();
const dataSource = getDataSource() ?? null;
if (!dataSource || !dataSource.isInitialized) {
if (match.requiresDatabase && (!dataSource || !dataSource.isInitialized)) {
sendJson(res, 503, { error: 'Database not initialised', errorCode: 'DB_UNAVAILABLE' });
return;
}
@@ -142,6 +150,7 @@ async function handleRequest(req: IncomingMessage, res: ServerResponse, settings
if (bodyCache === undefined) {
bodyCache = await readJsonBody<unknown>(req);
}
return bodyCache;
}
});
@@ -167,6 +176,7 @@ async function handleRequest(req: IncomingMessage, res: ServerResponse, settings
if (!(error instanceof HttpError)) {
console.error('[LocalApi] Request handler error:', error);
}
sendError(res, error);
}
}
@@ -190,6 +200,7 @@ export async function startLocalApiServer(settings: LocalApiSettings): Promise<S
const httpServer = createServer((req, res) => {
void handleRequest(req, res, activeSettings!).catch((error) => {
console.error('[LocalApi] Unhandled request error:', error);
try {
sendError(res, error);
} catch {