Merge remote-tracking branch 'public-gh/master' into paperclip-subissues

* public-gh/master:
  hide version until loaded
  add app version label
This commit is contained in:
Dotta
2026-03-17 09:54:30 -05:00
5 changed files with 22 additions and 2 deletions

View File

@@ -2,6 +2,7 @@ import { describe, it, expect } from "vitest";
import express from "express"; import express from "express";
import request from "supertest"; import request from "supertest";
import { healthRoutes } from "../routes/health.js"; import { healthRoutes } from "../routes/health.js";
import { serverVersion } from "../version.js";
describe("GET /health", () => { describe("GET /health", () => {
const app = express(); const app = express();
@@ -10,6 +11,6 @@ describe("GET /health", () => {
it("returns 200 with status ok", async () => { it("returns 200 with status ok", async () => {
const res = await request(app).get("/health"); const res = await request(app).get("/health");
expect(res.status).toBe(200); expect(res.status).toBe(200);
expect(res.body).toEqual({ status: "ok" }); expect(res.body).toEqual({ status: "ok", version: serverVersion });
}); });
}); });

View File

@@ -3,6 +3,7 @@ import type { Db } from "@paperclipai/db";
import { and, count, eq, gt, isNull, sql } from "drizzle-orm"; import { and, count, eq, gt, isNull, sql } from "drizzle-orm";
import { instanceUserRoles, invites } from "@paperclipai/db"; import { instanceUserRoles, invites } from "@paperclipai/db";
import type { DeploymentExposure, DeploymentMode } from "@paperclipai/shared"; import type { DeploymentExposure, DeploymentMode } from "@paperclipai/shared";
import { serverVersion } from "../version.js";
export function healthRoutes( export function healthRoutes(
db?: Db, db?: Db,
@@ -22,7 +23,7 @@ export function healthRoutes(
router.get("/", async (_req, res) => { router.get("/", async (_req, res) => {
if (!db) { if (!db) {
res.json({ status: "ok" }); res.json({ status: "ok", version: serverVersion });
return; return;
} }
@@ -56,6 +57,7 @@ export function healthRoutes(
res.json({ res.json({
status: "ok", status: "ok",
version: serverVersion,
deploymentMode: opts.deploymentMode, deploymentMode: opts.deploymentMode,
deploymentExposure: opts.deploymentExposure, deploymentExposure: opts.deploymentExposure,
authReady: opts.authReady, authReady: opts.authReady,

10
server/src/version.ts Normal file
View File

@@ -0,0 +1,10 @@
import { createRequire } from "node:module";
type PackageJson = {
version?: string;
};
const require = createRequire(import.meta.url);
const pkg = require("../package.json") as PackageJson;
export const serverVersion = pkg.version ?? "0.0.0";

View File

@@ -1,5 +1,6 @@
export type HealthStatus = { export type HealthStatus = {
status: "ok"; status: "ok";
version?: string;
deploymentMode?: "local_trusted" | "authenticated"; deploymentMode?: "local_trusted" | "authenticated";
deploymentExposure?: "private" | "public"; deploymentExposure?: "private" | "public";
authReady?: boolean; authReady?: boolean;

View File

@@ -297,6 +297,9 @@ export function Layout() {
<BookOpen className="h-4 w-4 shrink-0" /> <BookOpen className="h-4 w-4 shrink-0" />
<span className="truncate">Documentation</span> <span className="truncate">Documentation</span>
</a> </a>
{health?.version && (
<span className="px-2 text-xs text-muted-foreground shrink-0">v{health.version}</span>
)}
<Button variant="ghost" size="icon-sm" className="text-muted-foreground shrink-0" asChild> <Button variant="ghost" size="icon-sm" className="text-muted-foreground shrink-0" asChild>
<Link <Link
to={instanceSettingsTarget} to={instanceSettingsTarget}
@@ -347,6 +350,9 @@ export function Layout() {
<BookOpen className="h-4 w-4 shrink-0" /> <BookOpen className="h-4 w-4 shrink-0" />
<span className="truncate">Documentation</span> <span className="truncate">Documentation</span>
</a> </a>
{health?.version && (
<span className="px-2 text-xs text-muted-foreground shrink-0">v{health.version}</span>
)}
<Button variant="ghost" size="icon-sm" className="text-muted-foreground shrink-0" asChild> <Button variant="ghost" size="icon-sm" className="text-muted-foreground shrink-0" asChild>
<Link <Link
to={instanceSettingsTarget} to={instanceSettingsTarget}