117 lines
3.4 KiB
TypeScript
117 lines
3.4 KiB
TypeScript
import { DateTime } from 'luxon'
|
|
import { BaseModel, column, SnakeCaseNamingStrategy } from '@adonisjs/lucid/orm'
|
|
|
|
/**
|
|
* Drug Reference v1 — openFDA drug label catalog entry.
|
|
*
|
|
* One row per FDA `set_id` (stable GUID for a labeling, across all revisions).
|
|
* Re-ingesting updates existing rows idempotently via `set_id` UNIQUE key.
|
|
*
|
|
* Enum-ish columns (product_type) are plain varchars validated at the edge —
|
|
* the stl_files / inventory_items convention: no native DB enums, so the
|
|
* schema can evolve without ALTER TABLE.
|
|
*
|
|
* All section-text columns are optional: label records frequently omit
|
|
* sections (e.g. OTC labels have no `boxed_warning`). The mapper returns
|
|
* null for any absent or empty section.
|
|
*/
|
|
export default class DrugLabel extends BaseModel {
|
|
static table = 'drug_labels'
|
|
static namingStrategy = new SnakeCaseNamingStrategy()
|
|
|
|
@column({ isPrimary: true })
|
|
declare id: number
|
|
|
|
/** openFDA set_id — stable GUID across label revisions. Idempotent upsert key. */
|
|
@column()
|
|
declare set_id: string
|
|
|
|
/** openFDA id — per-revision GUID for provenance. */
|
|
@column()
|
|
declare spl_id: string | null
|
|
|
|
@column()
|
|
declare version: string | null
|
|
|
|
/** openfda.brand_name[0] — first element only. */
|
|
@column()
|
|
declare brand_name: string | null
|
|
|
|
/** openfda.generic_name joined with ", " (labels can list several). */
|
|
@column()
|
|
declare generic_name: string | null
|
|
|
|
/** openfda.manufacturer_name[0]. */
|
|
@column()
|
|
declare manufacturer: string | null
|
|
|
|
/** openfda.product_ndc joined with ", ". */
|
|
@column()
|
|
declare product_ndc: string | null
|
|
|
|
/** openfda.route joined with ", ". */
|
|
@column()
|
|
declare route: string | null
|
|
|
|
/**
|
|
* openfda.product_type[0]. Drives OTC vs Rx badge + filter.
|
|
* Expected values: 'HUMAN OTC DRUG' | 'HUMAN PRESCRIPTION DRUG'.
|
|
*/
|
|
@column()
|
|
declare product_type: string | null
|
|
|
|
/**
|
|
* Normalized brand+generic blob for FULLTEXT and LIKE search.
|
|
* Built by normalizeDrugName() at ingest time; never re-computed on read.
|
|
* Max 768 chars — stays inside InnoDB utf8mb4 index key-length budget.
|
|
*/
|
|
@column()
|
|
declare searchable_name: string | null
|
|
|
|
/** Flattened indications_and_usage sections, joined with \n\n. */
|
|
@column()
|
|
declare indications: string | null
|
|
|
|
/** Flattened dosage_and_administration sections. */
|
|
@column()
|
|
declare dosage: string | null
|
|
|
|
/** Flattened warnings sections. */
|
|
@column()
|
|
declare warnings: string | null
|
|
|
|
/** Flattened boxed_warning sections (absent on most OTC labels). */
|
|
@column()
|
|
declare boxed_warning: string | null
|
|
|
|
/**
|
|
* Flattened drug_interactions label text.
|
|
* Single-drug label info only — NOT a pairwise cross-drug checker.
|
|
*/
|
|
@column()
|
|
declare drug_interactions: string | null
|
|
|
|
/** Flattened contraindications sections. */
|
|
@column()
|
|
declare contraindications: string | null
|
|
|
|
/** Flattened when_using sections (common on OTC labels). */
|
|
@column()
|
|
declare when_using: string | null
|
|
|
|
/** Flattened stop_use sections (common on OTC labels). */
|
|
@column()
|
|
declare stop_use: string | null
|
|
|
|
/**
|
|
* Parsed from effective_time (YYYYMMDD → YYYY-MM-DD).
|
|
* Stored as a plain date string, not a Luxon DateTime, because
|
|
* the source format is just a date (no time component).
|
|
*/
|
|
@column()
|
|
declare source_updated_at: string | null
|
|
|
|
@column.dateTime({ autoCreate: true, autoUpdate: true, columnName: 'ingested_at' })
|
|
declare ingested_at: DateTime
|
|
}
|