feat(app): stats added in to check if build in last build and also if theres a pending file
This commit is contained in:
@@ -1,16 +1,13 @@
|
||||
import type { Express, Request, Response } from "express";
|
||||
|
||||
import healthRoutes from "./routes/healthRoutes.js";
|
||||
import { setupAuthRoutes } from "../auth/routes/routes.js";
|
||||
import { setupAdminRoutes } from "../admin/routes.js";
|
||||
import { setupSystemRoutes } from "../system/routes.js";
|
||||
|
||||
export const setupRoutes = (app: Express, basePath: string) => {
|
||||
// Root / health check
|
||||
app.use(basePath + "/api/system/health", healthRoutes);
|
||||
|
||||
// all routes
|
||||
setupAuthRoutes(app, basePath);
|
||||
setupAdminRoutes(app, basePath);
|
||||
setupSystemRoutes(app, basePath);
|
||||
|
||||
// always try to go to the app weather we are in dev or in production.
|
||||
app.get(basePath + "/", (req: Request, res: Response) => {
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
// GET /health
|
||||
router.get("/", (req, res) => {
|
||||
res.json({ status: "ok", uptime: process.uptime() });
|
||||
});
|
||||
|
||||
export default router;
|
||||
6
app/src/internal/system/routes.ts
Normal file
6
app/src/internal/system/routes.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { Express, Request, Response } from "express";
|
||||
import stats from "./routes/stats.js";
|
||||
|
||||
export const setupSystemRoutes = (app: Express, basePath: string) => {
|
||||
app.use(basePath + "/api/system/stats", stats);
|
||||
};
|
||||
34
app/src/internal/system/routes/stats.ts
Normal file
34
app/src/internal/system/routes/stats.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { Router } from "express";
|
||||
import { tryCatch } from "../../../pkg/utils/tryCatch.js";
|
||||
import { db } from "../../../pkg/db/db.js";
|
||||
import {
|
||||
serverStats,
|
||||
type ServerStats,
|
||||
} from "../../../pkg/db/schema/serverstats.js";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { format } from "date-fns-tz";
|
||||
import { checkBuildUpdate } from "../utlis/checkForBuild.js";
|
||||
|
||||
const router = Router();
|
||||
|
||||
// GET /health
|
||||
router.get("/", async (req, res) => {
|
||||
const { data, error } = await tryCatch(
|
||||
db.select().from(serverStats).where(eq(serverStats.id, "serverStats"))
|
||||
);
|
||||
|
||||
if (error || !data) {
|
||||
res.status(400).json({ error: error });
|
||||
}
|
||||
|
||||
const statData = data as ServerStats[];
|
||||
res.json({
|
||||
status: "ok",
|
||||
uptime: process.uptime(),
|
||||
build: statData[0]?.build,
|
||||
pendingUpdateFile: await checkBuildUpdate(["."]),
|
||||
lastUpdate: format(statData[0].lastUpdate!, "MM/dd/yyyy HH:mm"),
|
||||
});
|
||||
});
|
||||
|
||||
export default router;
|
||||
28
app/src/internal/system/utlis/checkForBuild.ts
Normal file
28
app/src/internal/system/utlis/checkForBuild.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { readdir } from "fs/promises";
|
||||
import { resolve, join } from "path";
|
||||
|
||||
/**
|
||||
* Looks in one or more relative/absolute directories for a .zip file.
|
||||
* Returns the **full path** to the first .zip file found, or null if none.
|
||||
*/
|
||||
export async function checkBuildUpdate(dirs: string[]): Promise<string | null> {
|
||||
for (const inputDir of dirs) {
|
||||
const dir = resolve(inputDir); // resolves "../../" relative to cwd
|
||||
try {
|
||||
const files = await readdir(dir);
|
||||
const zipFile = files.find((file) =>
|
||||
file.toLowerCase().endsWith(".zip")
|
||||
);
|
||||
if (zipFile) {
|
||||
//return join(dir, zipFile);
|
||||
return zipFile;
|
||||
}
|
||||
} catch (err) {
|
||||
// Ignore if directory doesn't exist, allow search to continue
|
||||
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
12
app/src/pkg/db/schema/serverstats.ts
Normal file
12
app/src/pkg/db/schema/serverstats.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { InferInsertModel, InferSelectModel } from "drizzle-orm";
|
||||
import { integer, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||
import type z from "zod";
|
||||
|
||||
export const serverStats = pgTable("serverStats", {
|
||||
id: text("id").primaryKey().default("serverStats"),
|
||||
build: integer("build").notNull().default(1),
|
||||
lastUpdate: timestamp("lastUpdate").defaultNow(),
|
||||
});
|
||||
|
||||
export type ServerStats = InferSelectModel<typeof serverStats>; // SELECT type
|
||||
//export type NewServerStats = InferInsertModel<typeof serverStats, "insert">; // INSERT type
|
||||
Reference in New Issue
Block a user