0%
balqalam Logo
balqalam
FeaturesCommunityPricingDocumentation
Login
  • Introduction
  • Pitch
  • Hogwarts
  • Live Demo
  • MVP
  • Roadmap
  • Launch Sprint
  • PRD
  • Get Started
  • Localhost
  • Architecture
  • Structure
  • Pattern
  • Page
  • Layout
  • Content
  • Types
  • Config
  • Actions
  • Queries
  • Authorization
  • Validation
  • Form
  • Table
  • Detail
  • Card
  • Util
  • Hooks
  • List Params
  • Views
  • README.md
  • ISSUE.md
  • Technology Stack
  • Database
  • File
  • CDN Assets
  • Entry Points
  • Dashboard
  • Authentication
  • Credentials
  • OAuth
  • Flow Diagrams
  • Multi-Tenancy
  • Offline
  • Onboarding
  • Onboarding Videos
  • Add Values
  • Admission
  • Application
  • Attendance
  • Compliance
  • Profile
  • Exams
  • Exam Wizard
  • Timetable
  • Classrooms
  • Notifications
  • Conference
  • LMS (Lumos)
Finance
  • Finance
  • Fee Management
  • Invoice
  • Wallet
  • Salary
  • Payroll
  • Timesheet
  • Expenses
  • Budget
  • Receipt
  • Accounts
  • Banking
  • Reports
  • Dashboard
  • Permissions
  • Messages
  • Integration Flow
  • Provision
  • AI Document Processing
  • Document Intelligence
  • Internationalization
  • Translation
  • Translation Guide
  • Icons
  • Docs Factory
  • Inspiration
  • Listings
  • Teachers
  • Students
  • Catalog
  • Library
  • Contributing
  • Code of conduct
  • GitHub Workflow
  • Database Seeds
  • Database Safety
  • Test Accounts
  • Playwright
  • Prettier
  • Block Rebound
Sales & GTM
  • Marketing Brief
  • Sales
  • Go-to-market
  • Marketing
  • Admission — Feature Spotlight
  • Pilot Program
  • Leads
  • Proposal
  • Outreach Templates
  • Case Study
  • Competitors
  • Landing-page teardown
  • Competitor FAQ
  • Business model
  • Shared economy
  • Traction
Fundraising & Ecosystem
  • Get Support
  • Investor Deck
  • Data Room
  • Investors
  • Accelerators
  • Incubators
  • Grants
  • Sponsors
  • Partners
  • Competitions & Hackathons
  • Universities & Training Centers

Queries

PreviousNext

Read-only database query modules colocated with each feature.

queries.ts holds read-only database queries. Mutations live in actions.ts. Reads and writes never share a file.

Categories

CategoryShapeReference
CRUD entitySingle-model queries: getList, getDetail, getStats (200–350 lines)listings/teachers/queries.ts
Multi-entity domainMultiple related models with separate select / where / listadmission/queries.ts

Rules

#Rule
1schoolId as the first parameter — multi-tenant isolation enforced at the signature
2as const on select objects — locks the shape so TypeScript narrows correctly
3Promise.all for parallel reads (list + count)
4Named exports only
5No mutations — db.create/update/delete belong in actions.ts
6No formatting helpers — move to util.ts
7Stay under ~400 lines — split into queries/list.ts, queries/detail.ts
8import "server-only" so misuse fails at build time

Canonical example

import "server-only"
 
import type { Prisma } from "@prisma/client"
 
import { db } from "@/lib/db"
 
const teacherListSelect = {
  id: true,
  firstName: true,
  lastName: true,
  email: true,
  phone: true,
  active: true,
} as const
 
export interface TeacherQueryParams {
  q?: string
  active?: boolean
  page?: number
  pageSize?: number
}
 
export async function getTeacherList(
  schoolId: string,
  params: Partial<TeacherQueryParams> = {}
) {
  const { q, active, page = 1, pageSize = 20 } = params
  const where: Prisma.TeacherWhereInput = {
    schoolId,
    ...(active !== undefined && { active }),
    ...(q && {
      OR: [{ firstName: { contains: q } }, { lastName: { contains: q } }],
    }),
  }
 
  const [data, total] = await Promise.all([
    db.teacher.findMany({
      where,
      select: teacherListSelect,
      skip: (page - 1) * pageSize,
      take: pageSize,
      orderBy: { lastName: "asc" },
    }),
    db.teacher.count({ where }),
  ])
 
  return { data, total, page, pageSize }
}
 
export async function getTeacherDetail(schoolId: string, id: string) {
  return db.teacher.findUnique({
    where: { id_schoolId: { id, schoolId } },
    select: { ...teacherListSelect, qualifications: true, classes: true },
  })
}

Anti-patterns

  • Reads in actions.ts — ~70% of features still mix them. Move to queries.ts.
  • Missing queries.ts — ~25 features have reads in actions.ts but no queries.ts.
  • Inline db.model.findMany() without select (~25 features).
  • PaginationParams / SortParam redefined (17 files) — lift to src/lib/types.ts.
  • Formatters in queries.ts — move to util.ts.
  • Returning Prisma payloads directly — wrap in feature DTOs from types.ts.

Naming

  • File: queries.ts.
  • Functions: get<Entity><Variant> — getTeacherList, getTeacherDetail, getTeacherStats.
  • Select objects: <entity><Variant>Select — teacherListSelect, teacherDetailSelect.

See also

  • Pattern
  • Actions
  • Types
  • List Params
ActionsAuthorization

On This Page

CategoriesRulesCanonical exampleAnti-patternsNamingSee also

Built by Databayt ·

Welcome to balqalam.

A great journey is about to begin.