feat: add Fastify API server with health check and env config

This commit is contained in:
Siddharth Kumar Sah
2026-03-22 02:46:34 +08:00
parent 19e48203bb
commit 1e7fb11da0
6 changed files with 1185 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
import "dotenv/config";
import { loadEnv } from "./lib/env.js";
export const env = loadEnv();
+36
View File
@@ -0,0 +1,36 @@
import Fastify from "fastify";
import cors from "@fastify/cors";
import rateLimit from "@fastify/rate-limit";
import { env } from "./config.js";
import { APP_VERSION } from "@stirling-image/shared";
const app = Fastify({
logger: true,
bodyLimit: env.MAX_UPLOAD_SIZE_MB * 1024 * 1024,
});
// Plugins
await app.register(cors, { origin: true });
await app.register(rateLimit, {
max: env.RATE_LIMIT_PER_MIN,
timeWindow: "1 minute",
});
// Health check
app.get("/api/v1/health", async () => ({
status: "healthy",
version: APP_VERSION,
uptime: process.uptime().toFixed(0) + "s",
storage: { mode: env.STORAGE_MODE, available: "N/A" },
queue: { active: 0, pending: 0 },
ai: {},
}));
// Start
try {
await app.listen({ port: env.PORT, host: "0.0.0.0" });
console.log(`Stirling Image API running on port ${env.PORT}`);
} catch (err) {
app.log.error(err);
process.exit(1);
}
+30
View File
@@ -0,0 +1,30 @@
import { z } from "zod";
const envSchema = z.object({
PORT: z.coerce.number().default(1349),
AUTH_ENABLED: z
.enum(["true", "false"])
.default("true")
.transform((v) => v === "true"),
DEFAULT_USERNAME: z.string().default("admin"),
DEFAULT_PASSWORD: z.string().default("admin"),
STORAGE_MODE: z.enum(["local", "s3"]).default("local"),
FILE_MAX_AGE_HOURS: z.coerce.number().default(24),
CLEANUP_INTERVAL_MINUTES: z.coerce.number().default(30),
MAX_UPLOAD_SIZE_MB: z.coerce.number().default(100),
MAX_BATCH_SIZE: z.coerce.number().default(200),
CONCURRENT_JOBS: z.coerce.number().default(3),
MAX_MEGAPIXELS: z.coerce.number().default(100),
RATE_LIMIT_PER_MIN: z.coerce.number().default(100),
DB_PATH: z.string().default("./data/stirling.db"),
WORKSPACE_PATH: z.string().default("./tmp/workspace"),
DEFAULT_THEME: z.enum(["light", "dark"]).default("light"),
DEFAULT_LOCALE: z.string().default("en"),
APP_NAME: z.string().default("Stirling Image"),
});
export type Env = z.infer<typeof envSchema>;
export function loadEnv(): Env {
return envSchema.parse(process.env);
}