mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: add Swagger/OpenAPI documentation at /api/docs
Registers @fastify/swagger and @fastify/swagger-ui, adds /api/docs to public auth paths, and wires up static serving + cleanup cron in index.ts.
This commit is contained in:
@@ -1,10 +1,14 @@
|
|||||||
import Fastify from "fastify";
|
import Fastify from "fastify";
|
||||||
import cors from "@fastify/cors";
|
import cors from "@fastify/cors";
|
||||||
import rateLimit from "@fastify/rate-limit";
|
import rateLimit from "@fastify/rate-limit";
|
||||||
|
import swagger from "@fastify/swagger";
|
||||||
|
import swaggerUi from "@fastify/swagger-ui";
|
||||||
import { env } from "./config.js";
|
import { env } from "./config.js";
|
||||||
import { APP_VERSION } from "@stirling-image/shared";
|
import { APP_VERSION } from "@stirling-image/shared";
|
||||||
import { runMigrations } from "./db/migrate.js";
|
import { runMigrations } from "./db/migrate.js";
|
||||||
import { ensureDefaultAdmin, authRoutes, authMiddleware } from "./plugins/auth.js";
|
import { ensureDefaultAdmin, authRoutes, authMiddleware } from "./plugins/auth.js";
|
||||||
|
import { registerStatic } from "./plugins/static.js";
|
||||||
|
import { startCleanupCron } from "./lib/cleanup.js";
|
||||||
|
|
||||||
// Run before anything else
|
// Run before anything else
|
||||||
runMigrations();
|
runMigrations();
|
||||||
@@ -25,6 +29,22 @@ await app.register(rateLimit, {
|
|||||||
timeWindow: "1 minute",
|
timeWindow: "1 minute",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Swagger / OpenAPI documentation
|
||||||
|
await app.register(swagger, {
|
||||||
|
openapi: {
|
||||||
|
info: {
|
||||||
|
title: "Stirling Image API",
|
||||||
|
description: "API for Stirling Image — self-hosted image processing suite",
|
||||||
|
version: APP_VERSION,
|
||||||
|
},
|
||||||
|
servers: [{ url: `http://localhost:${env.PORT}` }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await app.register(swaggerUi, {
|
||||||
|
routePrefix: "/api/docs",
|
||||||
|
});
|
||||||
|
|
||||||
// Auth middleware (must be registered before routes it protects)
|
// Auth middleware (must be registered before routes it protects)
|
||||||
await authMiddleware(app);
|
await authMiddleware(app);
|
||||||
|
|
||||||
@@ -41,6 +61,14 @@ app.get("/api/v1/health", async () => ({
|
|||||||
ai: {},
|
ai: {},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Serve SPA in production
|
||||||
|
if (process.env.NODE_ENV === "production") {
|
||||||
|
await registerStatic(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start workspace cleanup cron
|
||||||
|
startCleanupCron();
|
||||||
|
|
||||||
// Start
|
// Start
|
||||||
try {
|
try {
|
||||||
await app.listen({ port: env.PORT, host: "0.0.0.0" });
|
await app.listen({ port: env.PORT, host: "0.0.0.0" });
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ function extractToken(request: FastifyRequest): string | null {
|
|||||||
|
|
||||||
// ── Auth middleware ────────────────────────────────────────────────
|
// ── Auth middleware ────────────────────────────────────────────────
|
||||||
|
|
||||||
const PUBLIC_PATHS = ["/api/v1/health", "/api/auth/"];
|
const PUBLIC_PATHS = ["/api/v1/health", "/api/auth/", "/api/docs"];
|
||||||
|
|
||||||
function isPublicRoute(url: string): boolean {
|
function isPublicRoute(url: string): boolean {
|
||||||
return PUBLIC_PATHS.some((path) => url.startsWith(path));
|
return PUBLIC_PATHS.some((path) => url.startsWith(path));
|
||||||
|
|||||||
Reference in New Issue
Block a user