Extends the Hono adminRouter with four new read-only mesh admin modules:
meshes, sessions, invites, audit. Each ships {queries,router}.ts following
the existing users/organizations/customers pattern (paginated Drizzle
transactions, getOrderByFromSort sorting, ilike search, enum filters).
- GET /admin/meshes — paginated list with owner join + member count subquery
- GET /admin/meshes/:id — detail: members, presences, invites, last 50 audit
events (returns {mesh: null,...} shell on not-found to stay single-shape
for Hono RPC inference)
- GET /admin/sessions — live WS presences across every mesh, joined to
member/mesh for display, status + active/disconnected filters
- GET /admin/invites — invite tokens w/ mesh + createdBy user joins,
revoked/expired filters
- GET /admin/audit — mesh audit log with eventType/meshId/date filters
Summary endpoint extended: new GET /admin/summary/mesh returns
{meshes, activeMeshes, totalPresences, activePresences, messages24h}.
Messages24h derived from audit_log where event_type='message_sent'
in the past 24h.
Schemas live in packages/api/src/schema/mesh-admin.ts, re-exported from
the schema barrel. All mesh/role/transport enums mirror the DB enums
from packages/db/src/schema/mesh.ts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
import { Hono } from "hono";
|
|
|
|
import { enforceAdmin, enforceAuth } from "../../middleware";
|
|
|
|
import { auditRouter } from "./audit/router";
|
|
import { getMessages24hCount } from "./audit/queries";
|
|
import { getCustomersCount } from "./customers/queries";
|
|
import { customersRouter } from "./customers/router";
|
|
import { invitesRouter } from "./invites/router";
|
|
import {
|
|
getActiveMeshesCount,
|
|
getMeshesCount,
|
|
} from "./meshes/queries";
|
|
import { meshesRouter } from "./meshes/router";
|
|
import { getOrganizationsCount } from "./organizations/queries";
|
|
import { organizationsRouter } from "./organizations/router";
|
|
import {
|
|
getActivePresencesCount,
|
|
getPresencesCount,
|
|
} from "./sessions/queries";
|
|
import { sessionsRouter } from "./sessions/router";
|
|
import { getUsersCount } from "./users/queries";
|
|
import { usersRouter } from "./users/router";
|
|
|
|
export const adminRouter = new Hono()
|
|
.use(enforceAuth)
|
|
.use(enforceAdmin)
|
|
.route("/users", usersRouter)
|
|
.route("/organizations", organizationsRouter)
|
|
.route("/customers", customersRouter)
|
|
.route("/meshes", meshesRouter)
|
|
.route("/sessions", sessionsRouter)
|
|
.route("/invites", invitesRouter)
|
|
.route("/audit", auditRouter)
|
|
.get("/summary", async (c) => {
|
|
const [users, organizations, customers] = await Promise.all([
|
|
getUsersCount(),
|
|
getOrganizationsCount(),
|
|
getCustomersCount(),
|
|
]);
|
|
|
|
return c.json({ users, organizations, customers });
|
|
})
|
|
.get("/summary/mesh", async (c) => {
|
|
const [meshes, activeMeshes, totalPresences, activePresences, messages24h] =
|
|
await Promise.all([
|
|
getMeshesCount(),
|
|
getActiveMeshesCount(),
|
|
getPresencesCount(),
|
|
getActivePresencesCount(),
|
|
getMessages24hCount(),
|
|
]);
|
|
|
|
return c.json({
|
|
meshes,
|
|
activeMeshes,
|
|
totalPresences,
|
|
activePresences,
|
|
messages24h,
|
|
});
|
|
});
|