refactor(api): extract audit log procedures
This commit is contained in:
@@ -1,145 +1,55 @@
|
||||
import { z } from "zod";
|
||||
import { createTRPCRouter, controllerProcedure } from "../trpc.js";
|
||||
import {
|
||||
auditLogActivitySummaryInputSchema,
|
||||
auditLogByEntityInputSchema,
|
||||
auditLogEntryByIdInputSchema,
|
||||
auditLogListInputSchema,
|
||||
auditLogTimelineInputSchema,
|
||||
} from "./audit-log-inputs.js";
|
||||
import {
|
||||
formatAuditDetailEntry,
|
||||
formatAuditListEntry,
|
||||
getAuditActivitySummary,
|
||||
getAuditEntriesByEntity,
|
||||
getAuditEntryById,
|
||||
getAuditTimeline,
|
||||
listAuditEntries,
|
||||
toAuditListInput,
|
||||
toAuditTimelineInput,
|
||||
} from "./audit-log-support.js";
|
||||
|
||||
// ─── Router ───────────────────────────────────────────────────────────────────
|
||||
getAuditLogActivitySummary,
|
||||
getAuditLogEntriesByEntity,
|
||||
getAuditLogEntriesByEntityDetail,
|
||||
getAuditLogEntryById,
|
||||
getAuditLogEntryByIdDetail,
|
||||
getAuditLogTimeline,
|
||||
getAuditLogTimelineDetail,
|
||||
listAuditLogEntries,
|
||||
listAuditLogEntriesDetail,
|
||||
} from "./audit-log-procedure-support.js";
|
||||
|
||||
export const auditLogRouter = createTRPCRouter({
|
||||
/**
|
||||
* Paginated, filterable list of audit log entries.
|
||||
* Cursor-based pagination using createdAt + id.
|
||||
*/
|
||||
list: controllerProcedure
|
||||
.input(auditLogListInputSchema)
|
||||
.query(async ({ ctx, input }) => {
|
||||
return listAuditEntries(ctx.db, toAuditListInput({
|
||||
entityType: input.entityType,
|
||||
entityId: input.entityId,
|
||||
userId: input.userId,
|
||||
action: input.action,
|
||||
source: input.source,
|
||||
startDate: input.startDate,
|
||||
endDate: input.endDate,
|
||||
search: input.search,
|
||||
limit: input.limit,
|
||||
cursor: input.cursor,
|
||||
}));
|
||||
}),
|
||||
.query(({ ctx, input }) => listAuditLogEntries(ctx, input)),
|
||||
|
||||
listDetail: controllerProcedure
|
||||
.input(auditLogListInputSchema)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const result = await listAuditEntries(ctx.db, toAuditListInput({
|
||||
entityType: input.entityType,
|
||||
entityId: input.entityId,
|
||||
userId: input.userId,
|
||||
action: input.action,
|
||||
source: input.source,
|
||||
startDate: input.startDate,
|
||||
endDate: input.endDate,
|
||||
search: input.search,
|
||||
limit: input.limit,
|
||||
cursor: input.cursor,
|
||||
}));
|
||||
return {
|
||||
items: result.items.map(formatAuditListEntry),
|
||||
nextCursor: result.nextCursor ?? null,
|
||||
};
|
||||
}),
|
||||
.query(({ ctx, input }) => listAuditLogEntriesDetail(ctx, input)),
|
||||
|
||||
/**
|
||||
* Get a single audit entry with full changes JSONB (for expand/detail view).
|
||||
*/
|
||||
getById: controllerProcedure
|
||||
.input(z.object({ id: z.string() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
return getAuditEntryById(ctx.db, input.id);
|
||||
}),
|
||||
.input(auditLogEntryByIdInputSchema)
|
||||
.query(({ ctx, input }) => getAuditLogEntryById(ctx, input)),
|
||||
|
||||
getByIdDetail: controllerProcedure
|
||||
.input(z.object({ id: z.string() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const entry = await getAuditEntryById(ctx.db, input.id);
|
||||
return formatAuditDetailEntry(entry);
|
||||
}),
|
||||
.input(auditLogEntryByIdInputSchema)
|
||||
.query(({ ctx, input }) => getAuditLogEntryByIdDetail(ctx, input)),
|
||||
|
||||
/**
|
||||
* Get all audit entries for a specific entity (e.g. a project or resource).
|
||||
*/
|
||||
getByEntity: controllerProcedure
|
||||
.input(auditLogByEntityInputSchema)
|
||||
.query(async ({ ctx, input }) => {
|
||||
return getAuditEntriesByEntity(ctx.db, input);
|
||||
}),
|
||||
.query(({ ctx, input }) => getAuditLogEntriesByEntity(ctx, input)),
|
||||
|
||||
getByEntityDetail: controllerProcedure
|
||||
.input(auditLogByEntityInputSchema)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const entries = await getAuditEntriesByEntity(ctx.db, input);
|
||||
return {
|
||||
entityType: input.entityType,
|
||||
entityId: input.entityId,
|
||||
entityName: entries[0]?.entityName ?? null,
|
||||
itemCount: entries.length,
|
||||
items: entries.map(formatAuditDetailEntry),
|
||||
};
|
||||
}),
|
||||
.query(({ ctx, input }) => getAuditLogEntriesByEntityDetail(ctx, input)),
|
||||
|
||||
/**
|
||||
* Timeline view: entries grouped by date (YYYY-MM-DD).
|
||||
*/
|
||||
getTimeline: controllerProcedure
|
||||
.input(auditLogTimelineInputSchema)
|
||||
.query(async ({ ctx, input }) => {
|
||||
return getAuditTimeline(ctx.db, toAuditTimelineInput({
|
||||
startDate: input.startDate,
|
||||
endDate: input.endDate,
|
||||
limit: input.limit,
|
||||
}));
|
||||
}),
|
||||
.query(({ ctx, input }) => getAuditLogTimeline(ctx, input)),
|
||||
|
||||
getTimelineDetail: controllerProcedure
|
||||
.input(auditLogTimelineInputSchema)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const timeline = await getAuditTimeline(ctx.db, toAuditTimelineInput({
|
||||
startDate: input.startDate,
|
||||
endDate: input.endDate,
|
||||
limit: input.limit,
|
||||
}));
|
||||
return Object.fromEntries(
|
||||
Object.entries(timeline).map(([dateKey, entries]) => [
|
||||
dateKey,
|
||||
entries.map(formatAuditDetailEntry),
|
||||
]),
|
||||
);
|
||||
}),
|
||||
.query(({ ctx, input }) => getAuditLogTimelineDetail(ctx, input)),
|
||||
|
||||
/**
|
||||
* Activity summary: counts by entity type, action, and user for a date range.
|
||||
*/
|
||||
getActivitySummary: controllerProcedure
|
||||
.input(
|
||||
z.object({
|
||||
startDate: z.date().optional(),
|
||||
endDate: z.date().optional(),
|
||||
}),
|
||||
)
|
||||
.query(async ({ ctx, input }) => {
|
||||
return getAuditActivitySummary(ctx.db, input);
|
||||
}),
|
||||
.input(auditLogActivitySummaryInputSchema)
|
||||
.query(({ ctx, input }) => getAuditLogActivitySummary(ctx, input)),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user