fix(types): flatten tRPC Zod schema types to resolve TS2589 inference depth errors

Cast Zod schemas with .refine()/.superRefine() to z.ZodType<InferredType> at the
procedure level. This short-circuits TypeScript's deep type recursion through
tRPC's middleware chain, eliminating 4 of 5 @ts-expect-error TS2589 suppressions
in web components (VacationModal, ProjectModal, UsersClient, CountriesClient).

Applied same pattern to allocation, timeline, staffing, dashboard, project, and
resource query/mutation procedures to reduce client-side type depth.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-10 15:28:12 +02:00
parent 0d79f97d7a
commit 9bd3781c03
21 changed files with 460 additions and 304 deletions
+32 -31
View File
@@ -1,3 +1,4 @@
import type { Prisma } from "@capakraken/db";
import {
deleteDemandRequirement,
fillOpenDemand,
@@ -10,6 +11,11 @@ import {
PermissionKey,
UpdateDemandRequirementSchema,
} from "@capakraken/shared";
import type {
CreateDemandRequirementInput,
FillDemandRequirementInput,
FillOpenDemandByAllocationInput,
} from "@capakraken/shared";
import { z } from "zod";
import { findUniqueOrThrow } from "../../db/helpers.js";
import {
@@ -25,41 +31,34 @@ import {
invalidateDashboardCacheInBackground,
} from "./effects.js";
import { DEMAND_INCLUDE } from "./shared.js";
import {
buildCreateDemandRequirementInput,
getDemandRequirementByIdOrThrow,
} from "./support.js";
import {
managerProcedure,
requirePermission,
} from "../../trpc.js";
import { buildCreateDemandRequirementInput, getDemandRequirementByIdOrThrow } from "./support.js";
import { managerProcedure, requirePermission } from "../../trpc.js";
export const allocationDemandProcedures = {
createDemandRequirement: managerProcedure
.input(CreateDemandRequirementSchema)
.input(CreateDemandRequirementSchema as z.ZodType<CreateDemandRequirementInput>)
.mutation(async ({ ctx, input }) => {
requirePermission(ctx, PermissionKey.MANAGE_ALLOCATIONS);
return createDemandRequirementWithEffects(ctx.db, input);
}),
createDemand: managerProcedure
.input(z.object({
projectId: z.string(),
role: z.string().optional(),
roleId: z.string().optional(),
headcount: z.number().int().positive().default(1),
hoursPerDay: z.number().min(0.5).max(24),
startDate: z.coerce.date(),
endDate: z.coerce.date(),
budgetCents: z.number().int().min(0).optional(),
metadata: z.record(z.string(), z.unknown()).optional(),
}))
.input(
z.object({
projectId: z.string(),
role: z.string().optional(),
roleId: z.string().optional(),
headcount: z.number().int().positive().default(1),
hoursPerDay: z.number().min(0.5).max(24),
startDate: z.coerce.date(),
endDate: z.coerce.date(),
budgetCents: z.number().int().min(0).optional(),
metadata: z.record(z.string(), z.unknown()).optional(),
}),
)
.mutation(async ({ ctx, input }) => {
requirePermission(ctx, PermissionKey.MANAGE_ALLOCATIONS);
return createDemandRequirementWithEffects(
ctx.db,
buildCreateDemandRequirementInput(input),
);
return createDemandRequirementWithEffects(ctx.db, buildCreateDemandRequirementInput(input));
}),
updateDemandRequirement: managerProcedure
@@ -110,7 +109,7 @@ export const allocationDemandProcedures = {
entityType: "DemandRequirement",
entityId: input.id,
action: "DELETE",
changes: { before: existing } as unknown as import("@capakraken/db").Prisma.InputJsonValue,
changes: { before: existing } as unknown as Prisma.InputJsonValue,
},
});
});
@@ -127,17 +126,19 @@ export const allocationDemandProcedures = {
}),
fillDemandRequirement: managerProcedure
.input(FillDemandRequirementSchema)
.input(FillDemandRequirementSchema as z.ZodType<FillDemandRequirementInput>)
.mutation(async ({ ctx, input }) => {
requirePermission(ctx, PermissionKey.MANAGE_ALLOCATIONS);
return fillDemandRequirementWithEffects(ctx.db, input);
}),
assignResourceToDemand: managerProcedure
.input(z.object({
demandRequirementId: z.string(),
resourceId: z.string(),
}))
.input(
z.object({
demandRequirementId: z.string(),
resourceId: z.string(),
}),
)
.mutation(async ({ ctx, input }) => {
requirePermission(ctx, PermissionKey.MANAGE_ALLOCATIONS);
const result = await fillDemandRequirementWithEffects(ctx.db, input);
@@ -153,7 +154,7 @@ export const allocationDemandProcedures = {
}),
fillOpenDemandByAllocation: managerProcedure
.input(FillOpenDemandByAllocationSchema)
.input(FillOpenDemandByAllocationSchema as z.ZodType<FillOpenDemandByAllocationInput>)
.mutation(async ({ ctx, input }) => {
requirePermission(ctx, PermissionKey.MANAGE_ALLOCATIONS);