mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-07-14 18:15:56 -04:00
refactor: move system health procedure from system to admin router
- Rename `system.health` → `admin.systemHealth` and gate it behind the admin middleware - Remove `tmdbConfigured` from `system.status` response; update description to reflect its purpose - Update all call sites on web and native to use `orpc.admin.systemHealth` - Rename and relocate the docs page from `system/system.health.mdx` to `admin/admin.systemHealth.mdx`
This commit is contained in:
@@ -86,7 +86,7 @@ export default function SettingsScreen() {
|
||||
hasPassword && !(authConfig.data?.passwordLoginDisabled ?? true);
|
||||
|
||||
const systemHealth = useQuery({
|
||||
...orpc.system.health.queryOptions(),
|
||||
...orpc.admin.systemHealth.queryOptions(),
|
||||
enabled: isAdmin,
|
||||
});
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
purgeMetadataCache as purgeMetadataFn,
|
||||
} from "@sofa/core/cache";
|
||||
import { getSetting, setSetting } from "@sofa/core/settings";
|
||||
import { getSystemHealth } from "@sofa/core/system-health";
|
||||
import { isTelemetryEnabled } from "@sofa/core/telemetry";
|
||||
import {
|
||||
getCachedUpdateCheck,
|
||||
@@ -173,3 +174,11 @@ export const purgeMetadataCache = os.admin.purgeMetadataCache
|
||||
export const purgeImageCache = os.admin.purgeImageCache
|
||||
.use(admin)
|
||||
.handler(async () => purgeImagesFn());
|
||||
|
||||
// ─── System Health ───────────────────────────────────────────────
|
||||
|
||||
export const systemHealth = os.admin.systemHealth
|
||||
.use(admin)
|
||||
.handler(async () => {
|
||||
return await getSystemHealth();
|
||||
});
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
import { getSystemHealth } from "@sofa/core/system-health";
|
||||
import { isTmdbConfigured } from "@sofa/tmdb/config";
|
||||
import { os } from "../context";
|
||||
import { admin, authed } from "../middleware";
|
||||
import { authed } from "../middleware";
|
||||
|
||||
export const status = os.system.status.use(authed).handler(() => {
|
||||
return {
|
||||
tmdbConfigured: isTmdbConfigured(),
|
||||
publicApiUrl: process.env.PUBLIC_API_URL || "https://public-api.sofa.watch",
|
||||
};
|
||||
});
|
||||
|
||||
export const health = os.system.health.use(admin).handler(async () => {
|
||||
return await getSystemHealth();
|
||||
});
|
||||
|
||||
@@ -55,7 +55,6 @@ export const implementedRouter = {
|
||||
publicInfo: system.publicInfo,
|
||||
authConfig: system.authConfig,
|
||||
status: status.status,
|
||||
health: status.health,
|
||||
},
|
||||
integrations: {
|
||||
list: integrations.list,
|
||||
@@ -81,6 +80,7 @@ export const implementedRouter = {
|
||||
triggerJob: admin.triggerJob,
|
||||
purgeMetadataCache: admin.purgeMetadataCache,
|
||||
purgeImageCache: admin.purgeImageCache,
|
||||
systemHealth: admin.systemHealth,
|
||||
},
|
||||
account: {
|
||||
updateName: account.updateName,
|
||||
|
||||
@@ -29,7 +29,7 @@ export function CacheSection() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const invalidateHealth = () =>
|
||||
queryClient.invalidateQueries({ queryKey: orpc.system.health.key() });
|
||||
queryClient.invalidateQueries({ queryKey: orpc.admin.systemHealth.key() });
|
||||
|
||||
const purgeMetadata = useMutation(
|
||||
orpc.admin.purgeMetadataCache.mutationOptions({
|
||||
|
||||
@@ -130,11 +130,11 @@ function LiveTimeAgo({
|
||||
export function SystemHealthCards() {
|
||||
const queryClient = useQueryClient();
|
||||
const { data, isPending, isFetching } = useQuery(
|
||||
orpc.system.health.queryOptions(),
|
||||
orpc.admin.systemHealth.queryOptions(),
|
||||
);
|
||||
const isRefreshing = isFetching;
|
||||
const refresh = () =>
|
||||
queryClient.invalidateQueries({ queryKey: orpc.system.health.key() });
|
||||
queryClient.invalidateQueries({ queryKey: orpc.admin.systemHealth.key() });
|
||||
|
||||
if (isPending || !data) return <SkeletonCards />;
|
||||
|
||||
|
||||
+3
-3
@@ -9,11 +9,11 @@ _openapi:
|
||||
contents:
|
||||
- content: >-
|
||||
Comprehensive health check covering database, TMDB connectivity, cron
|
||||
jobs, image cache, backups, and environment. Admin only.
|
||||
jobs, image cache, backups, and environment.
|
||||
---
|
||||
|
||||
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
|
||||
|
||||
Comprehensive health check covering database, TMDB connectivity, cron jobs, image cache, backups, and environment. Admin only.
|
||||
Comprehensive health check covering database, TMDB connectivity, cron jobs, image cache, backups, and environment.
|
||||
|
||||
<APIPage document={"./public/openapi.json"} operations={[{"path":"/system/health","method":"get"}]} />
|
||||
<APIPage document={"./public/openapi.json"} operations={[{"path":"/admin/system-health","method":"get"}]} />
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Get system status
|
||||
title: Get internal system config
|
||||
full: true
|
||||
_openapi:
|
||||
method: GET
|
||||
@@ -8,12 +8,12 @@ _openapi:
|
||||
headings: []
|
||||
contents:
|
||||
- content: >-
|
||||
Quick check of whether TMDB is configured. Does not require
|
||||
Returns internal configuration such as the public API URL. Requires
|
||||
authentication.
|
||||
---
|
||||
|
||||
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
|
||||
|
||||
Quick check of whether TMDB is configured. Does not require authentication.
|
||||
Returns internal configuration such as the public API URL. Requires authentication.
|
||||
|
||||
<APIPage document={"./public/openapi.json"} operations={[{"path":"/system/status","method":"get"}]} />
|
||||
+97
-61
@@ -4287,60 +4287,28 @@
|
||||
"/system/status": {
|
||||
"get": {
|
||||
"operationId": "system.status",
|
||||
"summary": "Get system status",
|
||||
"description": "Quick check of whether TMDB is configured. Does not require authentication.",
|
||||
"summary": "Get internal system config",
|
||||
"description": "Returns internal configuration such as the public API URL. Requires authentication.",
|
||||
"tags": [
|
||||
"System"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "TMDB configuration status",
|
||||
"description": "Internal system configuration",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"tmdbConfigured": {
|
||||
"type": "boolean",
|
||||
"description": "Whether a TMDB API token is configured"
|
||||
},
|
||||
"publicApiUrl": {
|
||||
"type": "string",
|
||||
"description": "Base URL of the centralized public API"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"tmdbConfigured",
|
||||
"publicApiUrl"
|
||||
],
|
||||
"description": "Quick TMDB configuration check"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"session": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/system/health": {
|
||||
"get": {
|
||||
"operationId": "system.health",
|
||||
"summary": "Get system health report",
|
||||
"description": "Comprehensive health check covering database, TMDB connectivity, cron jobs, image cache, backups, and environment. Admin only.",
|
||||
"tags": [
|
||||
"System"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Full system health report",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/SystemHealth"
|
||||
"description": "Internal system configuration for authenticated clients"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5620,6 +5588,33 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/admin/system-health": {
|
||||
"get": {
|
||||
"operationId": "admin.systemHealth",
|
||||
"summary": "Get system health report",
|
||||
"description": "Comprehensive health check covering database, TMDB connectivity, cron jobs, image cache, backups, and environment.",
|
||||
"tags": [
|
||||
"Admin"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Full system health report",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/SystemHealth"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"session": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/account/name": {
|
||||
"put": {
|
||||
"operationId": "account.updateName",
|
||||
@@ -5831,10 +5826,12 @@
|
||||
},
|
||||
"watchedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "ISO 8601 timestamp"
|
||||
},
|
||||
"watchedOn": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "YYYY-MM-DD date-only"
|
||||
}
|
||||
},
|
||||
@@ -5865,16 +5862,22 @@
|
||||
"type": "number"
|
||||
},
|
||||
"seasonNumber": {
|
||||
"type": "number"
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"episodeNumber": {
|
||||
"type": "number"
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"watchedAt": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"watchedOn": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -5951,10 +5954,12 @@
|
||||
"description": "Sofa 1-5 star rating"
|
||||
},
|
||||
"ratedAt": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"ratedOn": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -6087,10 +6092,12 @@
|
||||
},
|
||||
"watchedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "ISO 8601 timestamp"
|
||||
},
|
||||
"watchedOn": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "YYYY-MM-DD date-only"
|
||||
}
|
||||
},
|
||||
@@ -6121,16 +6128,22 @@
|
||||
"type": "number"
|
||||
},
|
||||
"seasonNumber": {
|
||||
"type": "number"
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"episodeNumber": {
|
||||
"type": "number"
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"watchedAt": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"watchedOn": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -6207,10 +6220,12 @@
|
||||
"description": "Sofa 1-5 star rating"
|
||||
},
|
||||
"ratedAt": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"ratedOn": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -6276,10 +6291,12 @@
|
||||
},
|
||||
"watchedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "ISO 8601 timestamp"
|
||||
},
|
||||
"watchedOn": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "YYYY-MM-DD date-only"
|
||||
}
|
||||
},
|
||||
@@ -6310,16 +6327,22 @@
|
||||
"type": "number"
|
||||
},
|
||||
"seasonNumber": {
|
||||
"type": "number"
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"episodeNumber": {
|
||||
"type": "number"
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"watchedAt": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"watchedOn": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -6396,10 +6419,12 @@
|
||||
"description": "Sofa 1-5 star rating"
|
||||
},
|
||||
"ratedAt": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"ratedOn": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -6532,10 +6557,12 @@
|
||||
},
|
||||
"watchedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "ISO 8601 timestamp"
|
||||
},
|
||||
"watchedOn": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "YYYY-MM-DD date-only"
|
||||
}
|
||||
},
|
||||
@@ -6566,16 +6593,22 @@
|
||||
"type": "number"
|
||||
},
|
||||
"seasonNumber": {
|
||||
"type": "number"
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"episodeNumber": {
|
||||
"type": "number"
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"watchedAt": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"watchedOn": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -6652,10 +6685,12 @@
|
||||
"description": "Sofa 1-5 star rating"
|
||||
},
|
||||
"ratedAt": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"ratedOn": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -7145,7 +7180,8 @@
|
||||
"type": {
|
||||
"enum": [
|
||||
"progress",
|
||||
"complete"
|
||||
"complete",
|
||||
"timeout"
|
||||
]
|
||||
},
|
||||
"job": {
|
||||
|
||||
@@ -406,23 +406,12 @@ export const contract = {
|
||||
method: "GET",
|
||||
path: "/system/status",
|
||||
tags: ["System"],
|
||||
summary: "Get system status",
|
||||
summary: "Get internal system config",
|
||||
description:
|
||||
"Quick check of whether TMDB is configured. Does not require authentication.",
|
||||
successDescription: "TMDB configuration status",
|
||||
"Returns internal configuration such as the public API URL. Requires authentication.",
|
||||
successDescription: "Internal system configuration",
|
||||
})
|
||||
.output(SystemStatusOutput),
|
||||
health: oc
|
||||
.route({
|
||||
method: "GET",
|
||||
path: "/system/health",
|
||||
tags: ["System"],
|
||||
summary: "Get system health report",
|
||||
description:
|
||||
"Comprehensive health check covering database, TMDB connectivity, cron jobs, image cache, backups, and environment. Admin only.",
|
||||
successDescription: "Full system health report",
|
||||
})
|
||||
.output(SystemHealthOutput),
|
||||
},
|
||||
integrations: {
|
||||
list: oc
|
||||
@@ -653,6 +642,17 @@ export const contract = {
|
||||
})
|
||||
.input(z.void())
|
||||
.output(PurgeImageCacheOutput),
|
||||
systemHealth: oc
|
||||
.route({
|
||||
method: "GET",
|
||||
path: "/admin/system-health",
|
||||
tags: ["Admin"],
|
||||
summary: "Get system health report",
|
||||
description:
|
||||
"Comprehensive health check covering database, TMDB connectivity, cron jobs, image cache, backups, and environment.",
|
||||
successDescription: "Full system health report",
|
||||
})
|
||||
.output(SystemHealthOutput),
|
||||
},
|
||||
account: {
|
||||
updateName: oc
|
||||
|
||||
@@ -884,12 +884,11 @@ export const SystemHealthSchema = z
|
||||
|
||||
export const SystemStatusOutput = z
|
||||
.object({
|
||||
tmdbConfigured: z
|
||||
.boolean()
|
||||
.describe("Whether a TMDB API token is configured"),
|
||||
publicApiUrl: z.string().describe("Base URL of the centralized public API"),
|
||||
})
|
||||
.meta({ description: "Quick TMDB configuration check" });
|
||||
.meta({
|
||||
description: "Internal system configuration for authenticated clients",
|
||||
});
|
||||
|
||||
export const SystemHealthOutput = SystemHealthSchema;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user