project-nomad/admin/app/validators/drug_reference.ts

41 lines
1.5 KiB
TypeScript

import vine from '@vinejs/vine'
import { PRODUCT_TYPES } from '../../types/drug_reference.js'
/**
* Drug Reference v1 — request validators.
*
* Mirrors the stl_library validators: vine, minimal, typed at the edge.
*/
const PRODUCT_TYPE_VALUES = Object.values(PRODUCT_TYPES) as [string, ...string[]]
/** GET /api/drug-reference/search */
export const searchDrugValidator = vine.compile(
vine.object({
q: vine.string().trim().minLength(1).maxLength(200),
product_type: vine.enum(PRODUCT_TYPE_VALUES).optional(),
// Administration-route filter (openFDA `route`, e.g. ORAL, TOPICAL). Matched
// with LIKE because the column holds a comma-joined list; the UI sends
// curated values, the cap just bounds free input.
route: vine.string().trim().minLength(2).maxLength(40).optional(),
sort: vine.enum(['relevance', 'name'] as const).optional(),
limit: vine.number().min(1).max(200).optional(),
offset: vine.number().min(0).optional(),
scope: vine.enum(['name', 'indication'] as const).optional(),
})
)
/**
* GET /api/drug-reference/interactions?ids=1,2,3
*
* Accepts `ids` as a comma-separated string. The controller parses the actual
* id values via parseCompareIds (dedupe, drop non-positive-int, cap at 5).
* Vine validates only that `ids` is a non-empty string; the pure helper does
* the real semantic validation so it can be unit-tested without a running app.
*/
export const interactionsValidator = vine.compile(
vine.object({
ids: vine.string().trim().minLength(1).maxLength(200).optional(),
})
)