feat(cms): improve catalog, editorial recovery and operations
CI / check (push) Successful in 52s
CI / deploy (push) Successful in 2m10s
CI / publish-container (push) Failing after 1m18s

This commit is contained in:
Simo committed 2026-09-09 19:36:15 +02:00
1 parent 2fead134e6
commit c389c3893d
122 files changed
+8137 -703

No files matched your search

+111
View File
@@ -0,0 +1,111 @@
import "server-only";
import { constants } from "node:fs";
import { access, readdir } from "node:fs/promises";
import path from "node:path";
import { sql } from "drizzle-orm";
import {
type DiagnosticState,
migrationState,
workerState,
} from "@/lib/admin/installation-state";
import { fetchOpsHealth } from "@/lib/admin/ops-health";
import { db } from "@/lib/db";
import { redis } from "@/lib/redis";
import { siteSettings } from "@/lib/services/site-settings";
export async function inspectInstallation() {
const started = performance.now();
const [health, storage, expected, applied, heartbeat, renderer] =
await Promise.all([
fetchOpsHealth(),
Promise.all(
["storage", "public/nitro-assets", "public/swf"].map(async (name) => ({
name,
state: await access(
path.join(process.cwd(), name),
constants.R_OK | constants.W_OK,
)
.then(() => "ok" as const)
.catch(() => "failed" as const),
})),
),
readdir(path.join(process.cwd(), "drizzle/migrations"))
.then((files) =>
files
.filter((name) => name.endsWith(".sql"))
.map((name) => name.slice(0, -4)),
)
.catch(() => []),
db
.execute(sql`SELECT migration FROM cms_migrations`)
.then(([rows]) =>
(rows as unknown as { migration: string }[]).map(
(row) => row.migration,
),
)
.catch(() => null),
redis
? redis.get("cms:jobs-worker:heartbeat").catch(() => null)
: Promise.resolve(null),
siteSettings.get("nitro_client_url", "").catch(() => ""),
]);
const migration = migrationState(expected, applied);
const release = process.env.NEXT_PUBLIC_CMS_RELEASE ?? "unknown";
const rows: Array<{ key: string; state: DiagnosticState; detail?: string }> =
[
{
key: "release",
state: /^[a-f0-9]{40}$/i.test(release) ? "ok" : "unknown",
detail: /^[a-f0-9]{40}$/i.test(release) ? release : undefined,
},
{
key: "database",
state: health.dbOk ? "ok" : "failed",
detail: health.dbOk ? `${health.dbLatencyMs} ms` : undefined,
},
{
key: "redis",
state:
health.redisOk === null
? "missing"
: health.redisOk
? "ok"
: "failed",
},
{ key: "emulator", state: health.emulatorOk ? "ok" : "failed" },
{
key: "storage",
state: storage.every((item) => item.state === "ok") ? "ok" : "failed",
detail:
storage
.filter((item) => item.state !== "ok")
.map((item) => item.name)
.join(", ") || undefined,
},
{
key: "migrations",
state: migration.state,
detail:
migration.pending === null ? undefined : String(migration.pending),
},
{
key: "worker",
state: workerState(heartbeat),
detail:
heartbeat && Number.isFinite(Date.parse(heartbeat))
? new Date(heartbeat).toISOString()
: undefined,
},
{
key: "renderer",
state: health.dbOk ? "ok" : "unknown",
detail: health.dbOk && !renderer ? "/nitro-client/" : undefined,
},
{ key: "registry", state: "unknown" },
];
return {
rows,
checkedAt: new Date().toISOString(),
durationMs: Math.round(performance.now() - started),
};
}