Skip to main content

@repo/db

Functions

overviewToQuery

Applies DataGrid filters, sorting, and pagination to a Drizzle select query. Put fixed constraints on the initial query; overview filters are combined with the existing where clause.

return overviewToQuery(query.where(eq(table.status, 'active')).$dynamic(), table, data)

getOr404

This function simply takes a function and throws a 404 if the result is null or undefined

import { getOr404 } from '@repo/db'

const item = await getOr404(organizationRepository.get(session, params.id))

Audit Logs

@repo/db/audit — schema, hook, repository

import { auditLogsTable, createAuditHook, createAuditLog } from '@repo/db/audit'

export const auditTrail = createAuditHook({
getChangedBy: () => getSession()?.entity.id,
auditTable: auditLogsTable,
logger,
})

@repo/db/audit/server — query builders

import { buildQueries } from '@repo/db/audit/server'

export const { getAuditLogQuery } = buildQueries(getGlobalDb)

@repo/db/client — UI components

<script lang='ts'>
import { AuditLogButton } from '@repo/db/client'
</script>

<!-- Via DetailHeader (preferred) -->
<DetailHeader title='User' {deleteForm} getAuditLogs={getAuditLogQuery} table='users' />

<!-- Standalone -->
<AuditLogButton query={getAuditLogQuery} id={params.id} table='example_models' />

Props:

  • query: (args: { id: string; table: string }) => Promise<AuditLogEntry[]> — query function
  • id: string — record ID
  • table: string — table name
  • hiddenKeys?: Set<string> — snapshot keys to hide (default: updatedBy, createdBy)

Nested snapshot objects and arrays are expandable. Object fields show scalar values first; arrays retain their original order. The dialog keeps a viewport gutter on small screens.