perf(api): add explicit Prisma selects on hot read paths

Replaces full model includes with field-scoped selects on the resource
list (listStaff) query. Avoids fetching large JSONB columns
(availability, valueScoreBreakdown) and unused scalar fields (aiSummary,
portfolioUrl, fte, resourceType, postalCode, etc.) when only
identity/rate fields are needed.

Adds RESOURCE_LIST_SELECT constant to packages/api/src/db/selects.ts
covering all fields actually consumed by ResourcesClient, FillOpenDemandModal,
EstimateWizard, EstimateWorkspaceDraftEditor, and ScenarioPlanner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-09 19:24:55 +02:00
parent d3bfa8ca98
commit 6f3bdd81e8
2 changed files with 41 additions and 4 deletions
@@ -1,7 +1,7 @@
import { FieldType, ResourceType } from "@capakraken/shared";
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { ROLE_BRIEF_SELECT } from "../db/selects.js";
import { RESOURCE_LIST_SELECT, ROLE_BRIEF_SELECT } from "../db/selects.js";
import { buildDynamicFieldWhereClauses } from "./custom-field-filters.js";
import {
anonymizeResources,
@@ -167,7 +167,8 @@ export async function listStaffResources(
const rawResources = await (includeRoles
? ctx.db.resource.findMany({
where,
include: {
select: {
...RESOURCE_LIST_SELECT,
resourceRoles: {
include: { role: { select: ROLE_BRIEF_SELECT } },
},
@@ -176,6 +177,7 @@ export async function listStaffResources(
})
: ctx.db.resource.findMany({
where,
select: RESOURCE_LIST_SELECT,
orderBy: [{ displayName: "asc" }, { id: "asc" }],
}));
@@ -264,13 +266,17 @@ export async function listStaffResources(
includeRoles
? ctx.db.resource.findMany({
...baseQuery,
include: {
select: {
...RESOURCE_LIST_SELECT,
resourceRoles: {
include: { role: { select: ROLE_BRIEF_SELECT } },
},
},
})
: ctx.db.resource.findMany(baseQuery),
: ctx.db.resource.findMany({
...baseQuery,
select: RESOURCE_LIST_SELECT,
}),
ctx.db.resource.count({ where }),
]);