refactor(api): extract role read procedures

This commit is contained in:
2026-03-31 21:22:44 +02:00
parent cba4d44f16
commit 884f1012c9
5 changed files with 345 additions and 84 deletions
@@ -2,17 +2,34 @@ import { CreateRoleSchema, PermissionKey, UpdateRoleSchema } from "@capakraken/s
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { findUniqueOrThrow } from "../db/helpers.js";
import { RESOURCE_BRIEF_SELECT } from "../db/selects.js";
import { emitRoleCreated, emitRoleDeleted, emitRoleUpdated } from "../sse/event-bus.js";
import type { TRPCContext } from "../trpc.js";
import { requirePermission } from "../trpc.js";
import {
appendZeroAllocationCount,
assertRoleNameAvailable,
attachRolePlanningEntryCounts,
attachSingleRolePlanningEntryCount,
buildRoleCreateData,
buildRoleUpdateData,
buildRoleListWhere,
findRoleByIdentifier,
} from "./role-support.js";
export const RoleListInputSchema = z.object({
isActive: z.boolean().optional(),
search: z.string().optional(),
});
export const RoleIdentifierInputSchema = z.object({
identifier: z.string(),
});
export const ResolveRoleIdentifierInputSchema = z.object({
identifier: z.string().trim().min(1),
});
export const RoleIdInputSchema = z.object({
id: z.string(),
});
@@ -26,6 +43,91 @@ type RoleMutationContext = Pick<TRPCContext, "db" | "dbUser"> & {
permissions: Set<PermissionKey>;
};
type RoleReadContext = Pick<TRPCContext, "db">;
export async function listRoles(
ctx: RoleReadContext,
input: z.infer<typeof RoleListInputSchema>,
) {
const roles = await ctx.db.role.findMany({
where: buildRoleListWhere(input),
include: {
_count: {
select: { resourceRoles: true },
},
},
orderBy: { name: "asc" },
});
return attachRolePlanningEntryCounts(ctx.db, roles);
}
export async function resolveRoleByIdentifier(
ctx: RoleReadContext,
input: z.infer<typeof ResolveRoleIdentifierInputSchema>,
) {
const select = {
id: true,
name: true,
color: true,
isActive: true,
} as const;
return findRoleByIdentifier<{
id: string;
name: string;
color: string | null;
isActive: boolean;
}>(ctx.db, input.identifier, select);
}
export async function getRoleByIdentifier(
ctx: RoleReadContext,
input: z.infer<typeof RoleIdentifierInputSchema>,
) {
const select = {
id: true,
name: true,
description: true,
color: true,
isActive: true,
_count: { select: { resourceRoles: true } },
} as const;
const role = await findRoleByIdentifier<{
id: string;
name: string;
description: string | null;
color: string | null;
isActive: boolean;
_count: { resourceRoles: number };
}>(ctx.db, input.identifier, select);
return attachSingleRolePlanningEntryCount(ctx.db, role);
}
export async function getRoleById(
ctx: RoleReadContext,
input: z.infer<typeof RoleIdInputSchema>,
) {
const role = await findUniqueOrThrow(
ctx.db.role.findUnique({
where: { id: input.id },
include: {
_count: { select: { resourceRoles: true } },
resourceRoles: {
include: {
resource: { select: RESOURCE_BRIEF_SELECT },
},
},
},
}),
"Role",
);
return attachSingleRolePlanningEntryCount(ctx.db, role);
}
export async function createRole(
ctx: RoleMutationContext,
input: z.infer<typeof CreateRoleSchema>,