@erosolaraijs/cure 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/bin/cure.d.ts +2 -5
  2. package/dist/bin/cure.d.ts.map +1 -1
  3. package/dist/bin/cure.js +360 -129
  4. package/dist/bin/cure.js.map +1 -1
  5. package/dist/clinician/decisionSupport.d.ts +325 -0
  6. package/dist/clinician/decisionSupport.d.ts.map +1 -0
  7. package/dist/clinician/decisionSupport.js +604 -0
  8. package/dist/clinician/decisionSupport.js.map +1 -0
  9. package/dist/clinician/index.d.ts +5 -0
  10. package/dist/clinician/index.d.ts.map +1 -0
  11. package/dist/clinician/index.js +5 -0
  12. package/dist/clinician/index.js.map +1 -0
  13. package/dist/compliance/index.d.ts +5 -0
  14. package/dist/compliance/index.d.ts.map +1 -0
  15. package/dist/compliance/index.js +5 -0
  16. package/dist/compliance/index.js.map +1 -0
  17. package/dist/index.d.ts +65 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +102 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/integrations/clinicalTrials/index.d.ts +5 -0
  22. package/dist/integrations/clinicalTrials/index.d.ts.map +1 -0
  23. package/dist/integrations/clinicalTrials/index.js +5 -0
  24. package/dist/integrations/clinicalTrials/index.js.map +1 -0
  25. package/dist/integrations/ehr/index.d.ts +5 -0
  26. package/dist/integrations/ehr/index.d.ts.map +1 -0
  27. package/dist/integrations/ehr/index.js +5 -0
  28. package/dist/integrations/ehr/index.js.map +1 -0
  29. package/dist/integrations/genomics/index.d.ts +5 -0
  30. package/dist/integrations/genomics/index.d.ts.map +1 -0
  31. package/dist/integrations/genomics/index.js +5 -0
  32. package/dist/integrations/genomics/index.js.map +1 -0
  33. package/dist/ml/index.d.ts +5 -0
  34. package/dist/ml/index.d.ts.map +1 -0
  35. package/dist/ml/index.js +5 -0
  36. package/dist/ml/index.js.map +1 -0
  37. package/dist/ml/outcomePredictor.d.ts +297 -0
  38. package/dist/ml/outcomePredictor.d.ts.map +1 -0
  39. package/dist/ml/outcomePredictor.js +823 -0
  40. package/dist/ml/outcomePredictor.js.map +1 -0
  41. package/dist/orchestrator/index.d.ts +5 -0
  42. package/dist/orchestrator/index.d.ts.map +1 -0
  43. package/dist/orchestrator/index.js +5 -0
  44. package/dist/orchestrator/index.js.map +1 -0
  45. package/dist/orchestrator/realWorldOncology.d.ts +351 -0
  46. package/dist/orchestrator/realWorldOncology.d.ts.map +1 -0
  47. package/dist/orchestrator/realWorldOncology.js +425 -0
  48. package/dist/orchestrator/realWorldOncology.js.map +1 -0
  49. package/dist/patient/index.d.ts +5 -0
  50. package/dist/patient/index.d.ts.map +1 -0
  51. package/dist/patient/index.js +5 -0
  52. package/dist/patient/index.js.map +1 -0
  53. package/dist/patient/patientPortal.d.ts +337 -0
  54. package/dist/patient/patientPortal.d.ts.map +1 -0
  55. package/dist/patient/patientPortal.js +667 -0
  56. package/dist/patient/patientPortal.js.map +1 -0
  57. package/dist/safety/drugInteractions.d.ts +230 -0
  58. package/dist/safety/drugInteractions.d.ts.map +1 -0
  59. package/dist/safety/drugInteractions.js +697 -0
  60. package/dist/safety/drugInteractions.js.map +1 -0
  61. package/dist/safety/index.d.ts +5 -0
  62. package/dist/safety/index.d.ts.map +1 -0
  63. package/dist/safety/index.js +5 -0
  64. package/dist/safety/index.js.map +1 -0
  65. package/dist/validation/index.d.ts +5 -0
  66. package/dist/validation/index.d.ts.map +1 -0
  67. package/dist/validation/index.js +5 -0
  68. package/dist/validation/index.js.map +1 -0
  69. package/dist/validation/retrospectiveValidator.d.ts +246 -0
  70. package/dist/validation/retrospectiveValidator.d.ts.map +1 -0
  71. package/dist/validation/retrospectiveValidator.js +602 -0
  72. package/dist/validation/retrospectiveValidator.js.map +1 -0
  73. package/package.json +1 -1
  74. package/src/bin/cure.ts +412 -143
  75. package/src/clinician/decisionSupport.ts +949 -0
  76. package/src/clinician/index.ts +11 -0
  77. package/src/compliance/index.ts +19 -0
  78. package/src/integrations/clinicalTrials/index.ts +21 -0
  79. package/src/integrations/ehr/index.ts +32 -0
  80. package/src/integrations/genomics/index.ts +23 -0
  81. package/src/ml/index.ts +15 -0
  82. package/src/orchestrator/index.ts +11 -0
  83. package/src/orchestrator/realWorldOncology.ts +803 -0
  84. package/src/patient/index.ts +14 -0
  85. package/src/patient/patientPortal.ts +1039 -0
  86. package/src/safety/index.ts +14 -0
  87. package/src/validation/index.ts +10 -0
@@ -0,0 +1,697 @@
1
+ /**
2
+ * Drug Interaction and Safety Checking System
3
+ *
4
+ * Provides comprehensive drug safety checks:
5
+ * - Drug-drug interactions
6
+ * - Contraindication checking
7
+ * - Dosing validation
8
+ * - Allergy cross-reactivity
9
+ * - Organ function-based adjustments
10
+ * - Pregnancy/lactation safety
11
+ * - QT prolongation risk assessment
12
+ * - CYP450 interaction analysis
13
+ *
14
+ * Data sources would include:
15
+ * - FDA drug labels
16
+ * - DrugBank
17
+ * - PharmGKB
18
+ * - Clinical Pharmacology databases
19
+ */
20
+ import { EventEmitter } from 'events';
21
+ // ═══════════════════════════════════════════════════════════════════════════════
22
+ // DRUG SAFETY SERVICE
23
+ // ═══════════════════════════════════════════════════════════════════════════════
24
+ export class DrugSafetyService extends EventEmitter {
25
+ interactionDatabase = new Map();
26
+ contraindicationDatabase = new Map();
27
+ dosingGuidelines = new Map();
28
+ allergenCrossReactivity = new Map();
29
+ qtProlongingDrugs = new Set();
30
+ blackBoxWarnings = new Map();
31
+ constructor() {
32
+ super();
33
+ this.initializeDatabases();
34
+ }
35
+ /**
36
+ * Perform comprehensive safety check
37
+ */
38
+ async performSafetyCheck(patient, proposedDrugs) {
39
+ const alerts = [];
40
+ const recommendations = [];
41
+ // Get all drugs (current + proposed)
42
+ const allDrugs = [
43
+ ...patient.currentMedications.map(m => m.drug),
44
+ ...proposedDrugs.map(d => d.drug)
45
+ ];
46
+ // 1. Check drug-drug interactions
47
+ const interactionAlerts = await this.checkDrugInteractions(allDrugs);
48
+ alerts.push(...interactionAlerts);
49
+ // 2. Check contraindications based on patient conditions
50
+ const contraindicationAlerts = await this.checkContraindications(proposedDrugs.map(d => d.drug), patient);
51
+ alerts.push(...contraindicationAlerts);
52
+ // 3. Check allergies and cross-reactivity
53
+ const allergyAlerts = await this.checkAllergies(proposedDrugs.map(d => d.drug), patient.allergies);
54
+ alerts.push(...allergyAlerts);
55
+ // 4. Check dosing based on organ function
56
+ const dosingAlerts = await this.checkDosing(proposedDrugs, patient);
57
+ alerts.push(...dosingAlerts);
58
+ // 5. Check QT prolongation risk
59
+ const qtAlerts = await this.checkQTProlongation(allDrugs, patient);
60
+ alerts.push(...qtAlerts);
61
+ // 6. Check pregnancy/lactation
62
+ if (patient.demographics.pregnant || patient.demographics.breastfeeding) {
63
+ const pregnancyAlerts = await this.checkPregnancySafety(proposedDrugs.map(d => d.drug), patient);
64
+ alerts.push(...pregnancyAlerts);
65
+ }
66
+ // 7. Check black box warnings
67
+ const blackBoxAlerts = await this.checkBlackBoxWarnings(proposedDrugs.map(d => d.drug));
68
+ alerts.push(...blackBoxAlerts);
69
+ // 8. Check pharmacogenomic considerations
70
+ if (patient.geneticFactors) {
71
+ const pgxAlerts = await this.checkPharmacogenomics(proposedDrugs.map(d => d.drug), patient.geneticFactors);
72
+ alerts.push(...pgxAlerts);
73
+ }
74
+ // Count alerts by severity
75
+ const criticalAlerts = alerts.filter(a => a.severity === 'critical').length;
76
+ const highAlerts = alerts.filter(a => a.severity === 'high').length;
77
+ const moderateAlerts = alerts.filter(a => a.severity === 'moderate').length;
78
+ const lowAlerts = alerts.filter(a => a.severity === 'low').length;
79
+ // Determine overall risk
80
+ let overallRisk;
81
+ if (criticalAlerts > 0)
82
+ overallRisk = 'critical';
83
+ else if (highAlerts > 0)
84
+ overallRisk = 'high';
85
+ else if (moderateAlerts > 0)
86
+ overallRisk = 'moderate';
87
+ else if (lowAlerts > 0)
88
+ overallRisk = 'low';
89
+ else
90
+ overallRisk = 'minimal';
91
+ // Generate recommendations
92
+ for (const alert of alerts.filter(a => a.severity === 'critical' || a.severity === 'high')) {
93
+ recommendations.push(alert.recommendation);
94
+ }
95
+ // Determine if safe to proceed
96
+ const safe = criticalAlerts === 0 && !alerts.some(a => !a.overridable);
97
+ // Emit event
98
+ this.emit('safety-check-completed', { patientId: patient.patientId, safe, alertCount: alerts.length });
99
+ return {
100
+ safe,
101
+ alerts: alerts.sort((a, b) => {
102
+ const severityOrder = { critical: 0, high: 1, moderate: 2, low: 3 };
103
+ return severityOrder[a.severity] - severityOrder[b.severity];
104
+ }),
105
+ summary: {
106
+ criticalAlerts,
107
+ highAlerts,
108
+ moderateAlerts,
109
+ lowAlerts,
110
+ overallRisk
111
+ },
112
+ recommendations
113
+ };
114
+ }
115
+ /**
116
+ * Check drug-drug interactions
117
+ */
118
+ async checkDrugInteractions(drugs) {
119
+ const alerts = [];
120
+ const checkedPairs = new Set();
121
+ for (let i = 0; i < drugs.length; i++) {
122
+ for (let j = i + 1; j < drugs.length; j++) {
123
+ const drug1 = drugs[i].toLowerCase();
124
+ const drug2 = drugs[j].toLowerCase();
125
+ const pairKey = [drug1, drug2].sort().join('|');
126
+ if (checkedPairs.has(pairKey))
127
+ continue;
128
+ checkedPairs.add(pairKey);
129
+ const interaction = this.findInteraction(drug1, drug2);
130
+ if (interaction) {
131
+ alerts.push({
132
+ id: `DDI-${Date.now()}-${i}-${j}`,
133
+ type: 'interaction',
134
+ severity: this.mapInteractionSeverity(interaction.severity),
135
+ title: `Drug Interaction: ${drugs[i]} + ${drugs[j]}`,
136
+ description: interaction.clinicalEffect,
137
+ affectedDrugs: [drugs[i], drugs[j]],
138
+ recommendation: interaction.management,
139
+ overridable: interaction.severity !== 'contraindicated',
140
+ requiresDocumentation: interaction.severity === 'major' || interaction.severity === 'contraindicated',
141
+ references: interaction.references
142
+ });
143
+ }
144
+ }
145
+ }
146
+ return alerts;
147
+ }
148
+ /**
149
+ * Check contraindications
150
+ */
151
+ async checkContraindications(drugs, patient) {
152
+ const alerts = [];
153
+ // Check renal contraindications
154
+ if (patient.renalFunction.gfr < 30) {
155
+ const renalContraindicated = ['metformin', 'nsaids', 'lithium', 'gadolinium'];
156
+ for (const drug of drugs) {
157
+ if (renalContraindicated.some(c => drug.toLowerCase().includes(c))) {
158
+ alerts.push({
159
+ id: `CI-RENAL-${Date.now()}`,
160
+ type: 'contraindication',
161
+ severity: patient.renalFunction.gfr < 15 ? 'critical' : 'high',
162
+ title: `Renal Contraindication: ${drug}`,
163
+ description: `${drug} is contraindicated or requires significant dose adjustment with GFR ${patient.renalFunction.gfr} mL/min`,
164
+ affectedDrugs: [drug],
165
+ recommendation: `Consider alternative therapy or significant dose reduction. Consult nephrology if essential.`,
166
+ overridable: patient.renalFunction.gfr >= 15,
167
+ requiresDocumentation: true
168
+ });
169
+ }
170
+ }
171
+ }
172
+ // Check hepatic contraindications
173
+ if (patient.hepaticFunction.childPughClass === 'C') {
174
+ const hepaticContraindicated = ['methotrexate', 'valproic-acid', 'isoniazid', 'ketoconazole'];
175
+ for (const drug of drugs) {
176
+ if (hepaticContraindicated.some(c => drug.toLowerCase().includes(c))) {
177
+ alerts.push({
178
+ id: `CI-HEPATIC-${Date.now()}`,
179
+ type: 'contraindication',
180
+ severity: 'critical',
181
+ title: `Hepatic Contraindication: ${drug}`,
182
+ description: `${drug} is contraindicated in Child-Pugh Class C liver disease`,
183
+ affectedDrugs: [drug],
184
+ recommendation: `Avoid use. Consider alternative therapy.`,
185
+ overridable: false,
186
+ requiresDocumentation: true
187
+ });
188
+ }
189
+ }
190
+ }
191
+ // Check cardiac contraindications
192
+ if (patient.cardiacStatus.lvef && patient.cardiacStatus.lvef < 40) {
193
+ const cardiacCaution = ['anthracycline', 'trastuzumab', 'sunitinib', 'sorafenib'];
194
+ for (const drug of drugs) {
195
+ if (cardiacCaution.some(c => drug.toLowerCase().includes(c))) {
196
+ alerts.push({
197
+ id: `CI-CARDIAC-${Date.now()}`,
198
+ type: 'contraindication',
199
+ severity: 'high',
200
+ title: `Cardiac Caution: ${drug}`,
201
+ description: `${drug} has cardiotoxicity risk. Patient LVEF is ${patient.cardiacStatus.lvef}%`,
202
+ affectedDrugs: [drug],
203
+ recommendation: `Baseline and serial cardiac monitoring required. Consider cardiology consultation.`,
204
+ overridable: true,
205
+ requiresDocumentation: true
206
+ });
207
+ }
208
+ }
209
+ }
210
+ return alerts;
211
+ }
212
+ /**
213
+ * Check allergy cross-reactivity
214
+ */
215
+ async checkAllergies(drugs, allergies) {
216
+ const alerts = [];
217
+ for (const allergy of allergies) {
218
+ for (const drug of drugs) {
219
+ const crossReactivity = this.checkCrossReactivity(allergy.allergen, drug);
220
+ if (crossReactivity.crossReactivity) {
221
+ const severity = allergy.severity === 'severe' && crossReactivity.riskLevel === 'high'
222
+ ? 'critical'
223
+ : allergy.severity === 'severe' || crossReactivity.riskLevel === 'high'
224
+ ? 'high'
225
+ : 'moderate';
226
+ alerts.push({
227
+ id: `ALLERGY-${Date.now()}`,
228
+ type: 'allergy',
229
+ severity,
230
+ title: `Allergy Alert: ${drug}`,
231
+ description: `Patient allergic to ${allergy.allergen}. ${drug} has ${crossReactivity.riskLevel} cross-reactivity risk.`,
232
+ affectedDrugs: [drug],
233
+ recommendation: crossReactivity.recommendation,
234
+ overridable: allergy.severity !== 'severe' || crossReactivity.riskLevel !== 'high',
235
+ requiresDocumentation: true
236
+ });
237
+ }
238
+ }
239
+ }
240
+ return alerts;
241
+ }
242
+ /**
243
+ * Check dosing based on organ function
244
+ */
245
+ async checkDosing(drugs, patient) {
246
+ const alerts = [];
247
+ for (const drugOrder of drugs) {
248
+ const guidelines = this.dosingGuidelines.get(drugOrder.drug.toLowerCase());
249
+ if (!guidelines)
250
+ continue;
251
+ for (const guideline of guidelines) {
252
+ // Check renal adjustment
253
+ if (guideline.renalAdjustment) {
254
+ for (const adj of guideline.renalAdjustment) {
255
+ if (patient.renalFunction.gfr < adj.gfrThreshold) {
256
+ alerts.push({
257
+ id: `DOSE-RENAL-${Date.now()}`,
258
+ type: 'dosing',
259
+ severity: 'moderate',
260
+ title: `Dose Adjustment Required: ${drugOrder.drug}`,
261
+ description: `Patient GFR ${patient.renalFunction.gfr} requires dose adjustment`,
262
+ affectedDrugs: [drugOrder.drug],
263
+ recommendation: adj.adjustment,
264
+ overridable: true,
265
+ requiresDocumentation: true
266
+ });
267
+ break;
268
+ }
269
+ }
270
+ }
271
+ // Check hepatic adjustment
272
+ if (guideline.hepaticAdjustment && patient.hepaticFunction.childPughClass) {
273
+ const adj = guideline.hepaticAdjustment.find(a => a.childPughClass === patient.hepaticFunction.childPughClass);
274
+ if (adj) {
275
+ alerts.push({
276
+ id: `DOSE-HEPATIC-${Date.now()}`,
277
+ type: 'dosing',
278
+ severity: patient.hepaticFunction.childPughClass === 'C' ? 'high' : 'moderate',
279
+ title: `Hepatic Dose Adjustment: ${drugOrder.drug}`,
280
+ description: `Child-Pugh Class ${patient.hepaticFunction.childPughClass} requires dose adjustment`,
281
+ affectedDrugs: [drugOrder.drug],
282
+ recommendation: adj.adjustment,
283
+ overridable: patient.hepaticFunction.childPughClass !== 'C',
284
+ requiresDocumentation: true
285
+ });
286
+ }
287
+ }
288
+ // Check age-based adjustment
289
+ if (guideline.ageAdjustment) {
290
+ for (const adj of guideline.ageAdjustment) {
291
+ if (patient.demographics.age >= adj.ageThreshold) {
292
+ alerts.push({
293
+ id: `DOSE-AGE-${Date.now()}`,
294
+ type: 'dosing',
295
+ severity: 'low',
296
+ title: `Age-Based Consideration: ${drugOrder.drug}`,
297
+ description: `Patient age ${patient.demographics.age} may require adjustment`,
298
+ affectedDrugs: [drugOrder.drug],
299
+ recommendation: adj.adjustment,
300
+ overridable: true,
301
+ requiresDocumentation: false
302
+ });
303
+ break;
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
+ return alerts;
310
+ }
311
+ /**
312
+ * Check QT prolongation risk
313
+ */
314
+ async checkQTProlongation(drugs, patient) {
315
+ const alerts = [];
316
+ const qtDrugs = drugs.filter(d => this.qtProlongingDrugs.has(d.toLowerCase()));
317
+ if (qtDrugs.length > 0) {
318
+ // Check baseline QTc
319
+ const baselineQTc = patient.cardiacStatus.qtcInterval;
320
+ let riskLevel = 'moderate';
321
+ if (baselineQTc && baselineQTc > 500) {
322
+ riskLevel = 'critical';
323
+ }
324
+ else if (baselineQTc && baselineQTc > 470) {
325
+ riskLevel = 'high';
326
+ }
327
+ else if (qtDrugs.length >= 2) {
328
+ riskLevel = 'high';
329
+ }
330
+ // Check for additional risk factors
331
+ const riskFactors = [];
332
+ if (patient.demographics.gender === 'female')
333
+ riskFactors.push('Female gender');
334
+ if (patient.demographics.age > 65)
335
+ riskFactors.push('Age > 65');
336
+ if (patient.cardiacStatus.arrhythmiaHistory)
337
+ riskFactors.push('Arrhythmia history');
338
+ // Would also check electrolytes (K, Mg) if available
339
+ if (qtDrugs.length >= 2 || riskLevel === 'critical' || riskLevel === 'high') {
340
+ alerts.push({
341
+ id: `QT-${Date.now()}`,
342
+ type: 'qt-prolongation',
343
+ severity: riskLevel,
344
+ title: `QT Prolongation Risk: ${qtDrugs.join(', ')}`,
345
+ description: `${qtDrugs.length} QT-prolonging drug(s) ordered. ${riskFactors.length > 0 ? 'Risk factors: ' + riskFactors.join(', ') : ''}`,
346
+ affectedDrugs: qtDrugs,
347
+ recommendation: `Monitor QTc. Consider ECG at baseline and after steady state. Avoid if QTc > 500ms.`,
348
+ overridable: riskLevel !== 'critical',
349
+ requiresDocumentation: true
350
+ });
351
+ }
352
+ }
353
+ return alerts;
354
+ }
355
+ /**
356
+ * Check pregnancy and lactation safety
357
+ */
358
+ async checkPregnancySafety(drugs, patient) {
359
+ const alerts = [];
360
+ // Known teratogenic drugs
361
+ const categoryX = [
362
+ 'methotrexate', 'thalidomide', 'lenalidomide', 'pomalidomide',
363
+ 'isotretinoin', 'warfarin', 'ribavirin', 'leflunomide'
364
+ ];
365
+ const categoryD = [
366
+ 'doxorubicin', 'cyclophosphamide', 'imatinib', 'tamoxifen',
367
+ 'carbamazepine', 'phenytoin', 'valproic acid', 'lithium'
368
+ ];
369
+ for (const drug of drugs) {
370
+ const drugLower = drug.toLowerCase();
371
+ if (categoryX.some(x => drugLower.includes(x))) {
372
+ alerts.push({
373
+ id: `PREG-X-${Date.now()}`,
374
+ type: 'pregnancy',
375
+ severity: 'critical',
376
+ title: `Pregnancy Contraindication: ${drug}`,
377
+ description: `${drug} is absolutely contraindicated in pregnancy (Category X equivalent)`,
378
+ affectedDrugs: [drug],
379
+ recommendation: `Do not use. Use alternative therapy. Ensure contraception.`,
380
+ overridable: false,
381
+ requiresDocumentation: true
382
+ });
383
+ }
384
+ else if (categoryD.some(d => drugLower.includes(d))) {
385
+ alerts.push({
386
+ id: `PREG-D-${Date.now()}`,
387
+ type: 'pregnancy',
388
+ severity: 'high',
389
+ title: `Pregnancy Risk: ${drug}`,
390
+ description: `${drug} has evidence of fetal risk but may be used if benefit outweighs risk`,
391
+ affectedDrugs: [drug],
392
+ recommendation: `Document informed consent. Discuss risks with patient. Consider alternatives.`,
393
+ overridable: true,
394
+ requiresDocumentation: true
395
+ });
396
+ }
397
+ }
398
+ return alerts;
399
+ }
400
+ /**
401
+ * Check black box warnings
402
+ */
403
+ async checkBlackBoxWarnings(drugs) {
404
+ const alerts = [];
405
+ for (const drug of drugs) {
406
+ const warnings = this.blackBoxWarnings.get(drug.toLowerCase());
407
+ if (warnings && warnings.length > 0) {
408
+ alerts.push({
409
+ id: `BBW-${Date.now()}`,
410
+ type: 'black-box',
411
+ severity: 'high',
412
+ title: `Black Box Warning: ${drug}`,
413
+ description: warnings.join('; '),
414
+ affectedDrugs: [drug],
415
+ recommendation: `Ensure appropriate monitoring and patient education. Document informed consent.`,
416
+ overridable: true,
417
+ requiresDocumentation: true
418
+ });
419
+ }
420
+ }
421
+ return alerts;
422
+ }
423
+ /**
424
+ * Check pharmacogenomic considerations
425
+ */
426
+ async checkPharmacogenomics(drugs, genetics) {
427
+ const alerts = [];
428
+ // DPYD and fluoropyrimidines
429
+ if (genetics.dpyd && genetics.dpyd !== 'normal') {
430
+ const fluoropyrimidines = ['5-fu', 'fluorouracil', 'capecitabine'];
431
+ const affected = drugs.filter(d => fluoropyrimidines.some(f => d.toLowerCase().includes(f)));
432
+ if (affected.length > 0) {
433
+ const severity = genetics.dpyd === 'deficient' ? 'critical' : 'high';
434
+ alerts.push({
435
+ id: `PGX-DPYD-${Date.now()}`,
436
+ type: 'organ-function',
437
+ severity,
438
+ title: `DPYD Deficiency: ${affected.join(', ')}`,
439
+ description: `Patient is DPYD ${genetics.dpyd}. High risk of severe/fatal toxicity with fluoropyrimidines.`,
440
+ affectedDrugs: affected,
441
+ recommendation: genetics.dpyd === 'deficient'
442
+ ? 'Contraindicated. Use alternative therapy.'
443
+ : 'Reduce dose by 50%. Consider alternative.',
444
+ overridable: genetics.dpyd !== 'deficient',
445
+ requiresDocumentation: true
446
+ });
447
+ }
448
+ }
449
+ // UGT1A1 and irinotecan
450
+ if (genetics.ugt1a1 === '*28/*28') {
451
+ const irinotecan = drugs.filter(d => d.toLowerCase().includes('irinotecan'));
452
+ if (irinotecan.length > 0) {
453
+ alerts.push({
454
+ id: `PGX-UGT1A1-${Date.now()}`,
455
+ type: 'organ-function',
456
+ severity: 'high',
457
+ title: `UGT1A1 Polymorphism: Irinotecan`,
458
+ description: `Patient is UGT1A1*28/*28. Increased risk of severe neutropenia and diarrhea.`,
459
+ affectedDrugs: irinotecan,
460
+ recommendation: `Reduce initial dose by 1 level. Monitor closely.`,
461
+ overridable: true,
462
+ requiresDocumentation: true
463
+ });
464
+ }
465
+ }
466
+ // TPMT and thiopurines
467
+ if (genetics.tpmt && genetics.tpmt !== 'normal') {
468
+ const thiopurines = ['azathioprine', '6-mercaptopurine', 'thioguanine'];
469
+ const affected = drugs.filter(d => thiopurines.some(t => d.toLowerCase().includes(t)));
470
+ if (affected.length > 0) {
471
+ const severity = genetics.tpmt === 'poor' ? 'critical' : 'high';
472
+ alerts.push({
473
+ id: `PGX-TPMT-${Date.now()}`,
474
+ type: 'organ-function',
475
+ severity,
476
+ title: `TPMT Deficiency: ${affected.join(', ')}`,
477
+ description: `Patient is TPMT ${genetics.tpmt} metabolizer. Risk of severe myelosuppression.`,
478
+ affectedDrugs: affected,
479
+ recommendation: genetics.tpmt === 'poor'
480
+ ? 'Reduce dose by 90% or use alternative.'
481
+ : 'Reduce dose by 50%. Monitor CBC closely.',
482
+ overridable: genetics.tpmt !== 'poor',
483
+ requiresDocumentation: true
484
+ });
485
+ }
486
+ }
487
+ return alerts;
488
+ }
489
+ /**
490
+ * Get recommended alternatives for a contraindicated drug
491
+ */
492
+ getAlternatives(drug, reason, patientProfile) {
493
+ const alternatives = [];
494
+ // Drug class-based alternatives
495
+ const alternativeMap = {
496
+ // Chemotherapy
497
+ 'cisplatin': ['carboplatin', 'oxaliplatin'],
498
+ 'doxorubicin': ['liposomal doxorubicin', 'epirubicin'],
499
+ 'ifosfamide': ['cyclophosphamide'],
500
+ // Targeted therapy
501
+ 'osimertinib': ['afatinib', 'erlotinib', 'gefitinib'],
502
+ 'alectinib': ['brigatinib', 'lorlatinib', 'crizotinib'],
503
+ // Immunotherapy (generally fewer direct alternatives)
504
+ 'pembrolizumab': ['nivolumab', 'atezolizumab'],
505
+ 'nivolumab': ['pembrolizumab', 'atezolizumab'],
506
+ // Supportive care
507
+ 'ondansetron': ['granisetron', 'palonosetron'],
508
+ 'metoclopramide': ['prochlorperazine', 'promethazine']
509
+ };
510
+ const drugLower = drug.toLowerCase();
511
+ for (const [key, alts] of Object.entries(alternativeMap)) {
512
+ if (drugLower.includes(key)) {
513
+ alternatives.push(...alts);
514
+ break;
515
+ }
516
+ }
517
+ // Filter alternatives based on patient's contraindications
518
+ return alternatives.filter(alt => {
519
+ const interaction = this.findInteraction(alt, drug);
520
+ if (interaction?.severity === 'contraindicated')
521
+ return false;
522
+ return true;
523
+ });
524
+ }
525
+ // ═══════════════════════════════════════════════════════════════════════════════
526
+ // HELPER METHODS
527
+ // ═══════════════════════════════════════════════════════════════════════════════
528
+ initializeDatabases() {
529
+ // Initialize drug interactions (simplified - production would have comprehensive database)
530
+ this.addInteraction({
531
+ drug1: 'pembrolizumab',
532
+ drug2: 'corticosteroids',
533
+ severity: 'moderate',
534
+ type: 'pharmacodynamic',
535
+ mechanism: 'High-dose corticosteroids may reduce immunotherapy efficacy',
536
+ clinicalEffect: 'Reduced antitumor immune response',
537
+ management: 'Use lowest effective steroid dose. Consider steroid-sparing agents for irAE management.',
538
+ documentation: 'established'
539
+ });
540
+ this.addInteraction({
541
+ drug1: 'warfarin',
542
+ drug2: 'capecitabine',
543
+ severity: 'major',
544
+ type: 'pharmacokinetic',
545
+ mechanism: 'Capecitabine inhibits CYP2C9, increasing warfarin effect',
546
+ clinicalEffect: 'Increased INR and bleeding risk',
547
+ management: 'Monitor INR closely. Consider LMWH alternative.',
548
+ documentation: 'established'
549
+ });
550
+ this.addInteraction({
551
+ drug1: 'osimertinib',
552
+ drug2: 'strong cyp3a4 inducers',
553
+ severity: 'major',
554
+ type: 'pharmacokinetic',
555
+ mechanism: 'CYP3A4 inducers decrease osimertinib exposure',
556
+ clinicalEffect: 'Reduced efficacy',
557
+ management: 'Avoid concomitant use with strong CYP3A4 inducers',
558
+ documentation: 'established'
559
+ });
560
+ // Initialize QT-prolonging drugs
561
+ const qtDrugs = [
562
+ 'ondansetron', 'granisetron', 'haloperidol', 'droperidol',
563
+ 'methadone', 'sotalol', 'amiodarone', 'dofetilide',
564
+ 'ibutilide', 'quinidine', 'procainamide', 'disopyramide',
565
+ 'arsenic trioxide', 'crizotinib', 'lapatinib', 'nilotinib',
566
+ 'pazopanib', 'sunitinib', 'vandetanib', 'vemurafenib'
567
+ ];
568
+ qtDrugs.forEach(d => this.qtProlongingDrugs.add(d.toLowerCase()));
569
+ // Initialize black box warnings
570
+ this.blackBoxWarnings.set('pembrolizumab', [
571
+ 'Immune-mediated adverse reactions can be severe and fatal',
572
+ 'Monitor for immune-mediated pneumonitis, colitis, hepatitis, endocrinopathies, nephritis, and dermatologic reactions'
573
+ ]);
574
+ this.blackBoxWarnings.set('trastuzumab', [
575
+ 'Cardiomyopathy: Evaluate LVEF prior to and during treatment',
576
+ 'Infusion reactions including fatal cases'
577
+ ]);
578
+ this.blackBoxWarnings.set('bevacizumab', [
579
+ 'Gastrointestinal perforation',
580
+ 'Surgery and wound healing complications',
581
+ 'Hemorrhage'
582
+ ]);
583
+ // Initialize allergy cross-reactivity
584
+ this.allergenCrossReactivity.set('penicillin', ['amoxicillin', 'ampicillin', 'piperacillin', 'cephalosporins']);
585
+ this.allergenCrossReactivity.set('sulfa', ['sulfamethoxazole', 'sulfasalazine', 'celecoxib', 'furosemide']);
586
+ this.allergenCrossReactivity.set('platinum', ['cisplatin', 'carboplatin', 'oxaliplatin']);
587
+ // Initialize dosing guidelines
588
+ this.dosingGuidelines.set('carboplatin', [{
589
+ drug: 'carboplatin',
590
+ indication: 'solid tumors',
591
+ standardDose: 'AUC 5-6 (Calvert formula)',
592
+ renalAdjustment: [
593
+ { gfrThreshold: 60, adjustment: 'Use Calvert formula with measured or estimated GFR' },
594
+ { gfrThreshold: 30, adjustment: 'Reduce target AUC. Consider nephrology consult' },
595
+ { gfrThreshold: 15, adjustment: 'Avoid or significant dose reduction' }
596
+ ],
597
+ weightBasedDosing: {
598
+ formula: 'Dose (mg) = Target AUC × (GFR + 25)',
599
+ maxDose: 'Cap GFR at 125 mL/min'
600
+ }
601
+ }]);
602
+ this.dosingGuidelines.set('cisplatin', [{
603
+ drug: 'cisplatin',
604
+ indication: 'solid tumors',
605
+ standardDose: '75-100 mg/m²',
606
+ renalAdjustment: [
607
+ { gfrThreshold: 60, adjustment: 'Standard dose with aggressive hydration' },
608
+ { gfrThreshold: 45, adjustment: 'Reduce dose 25-50%' },
609
+ { gfrThreshold: 30, adjustment: 'Avoid - use carboplatin alternative' }
610
+ ]
611
+ }]);
612
+ }
613
+ addInteraction(interaction) {
614
+ const key1 = interaction.drug1.toLowerCase();
615
+ const key2 = interaction.drug2.toLowerCase();
616
+ if (!this.interactionDatabase.has(key1)) {
617
+ this.interactionDatabase.set(key1, []);
618
+ }
619
+ if (!this.interactionDatabase.has(key2)) {
620
+ this.interactionDatabase.set(key2, []);
621
+ }
622
+ this.interactionDatabase.get(key1).push(interaction);
623
+ this.interactionDatabase.get(key2).push(interaction);
624
+ }
625
+ findInteraction(drug1, drug2) {
626
+ const interactions = this.interactionDatabase.get(drug1.toLowerCase());
627
+ if (!interactions)
628
+ return null;
629
+ return interactions.find(i => i.drug2.toLowerCase() === drug2.toLowerCase() ||
630
+ i.drug1.toLowerCase() === drug2.toLowerCase()) || null;
631
+ }
632
+ mapInteractionSeverity(severity) {
633
+ switch (severity) {
634
+ case 'contraindicated': return 'critical';
635
+ case 'major': return 'high';
636
+ case 'moderate': return 'moderate';
637
+ case 'minor': return 'low';
638
+ }
639
+ }
640
+ checkCrossReactivity(allergen, drug) {
641
+ const relatedAllergens = this.allergenCrossReactivity.get(allergen.toLowerCase()) || [];
642
+ const crossReacts = relatedAllergens.some(a => drug.toLowerCase().includes(a));
643
+ let riskLevel = 'none';
644
+ if (crossReacts) {
645
+ // Platinum cross-reactivity is high
646
+ if (allergen.toLowerCase().includes('platinum')) {
647
+ riskLevel = 'high';
648
+ }
649
+ // Penicillin-cephalosporin is lower risk
650
+ else if (allergen.toLowerCase().includes('penicillin') && drug.toLowerCase().includes('cephalosporin')) {
651
+ riskLevel = 'low'; // ~2% cross-reactivity
652
+ }
653
+ else {
654
+ riskLevel = 'moderate';
655
+ }
656
+ }
657
+ return {
658
+ reportedAllergy: allergen,
659
+ drugToCheck: drug,
660
+ crossReactivity: crossReacts,
661
+ riskLevel,
662
+ relatedAllergens,
663
+ recommendation: crossReacts
664
+ ? `Consider alternative. If essential, administer with caution and monitor.`
665
+ : `No known cross-reactivity. Standard precautions.`
666
+ };
667
+ }
668
+ /**
669
+ * Generate a medication reconciliation report
670
+ */
671
+ async generateMedicationReconciliation(patient) {
672
+ const currentMeds = patient.currentMedications.map(m => m.drug);
673
+ const interactionAlerts = await this.checkDrugInteractions(currentMeds);
674
+ const interactions = [];
675
+ for (let i = 0; i < currentMeds.length; i++) {
676
+ for (let j = i + 1; j < currentMeds.length; j++) {
677
+ const int = this.findInteraction(currentMeds[i], currentMeds[j]);
678
+ if (int)
679
+ interactions.push(int);
680
+ }
681
+ }
682
+ const recommendations = [];
683
+ for (const int of interactions.filter(i => i.severity === 'major' || i.severity === 'contraindicated')) {
684
+ recommendations.push(int.management);
685
+ }
686
+ return {
687
+ currentMedications: currentMeds,
688
+ interactions,
689
+ recommendations,
690
+ summary: interactions.length > 0
691
+ ? `Found ${interactions.length} drug interaction(s), including ${interactions.filter(i => i.severity === 'major' || i.severity === 'contraindicated').length} major interaction(s).`
692
+ : 'No significant drug interactions identified.'
693
+ };
694
+ }
695
+ }
696
+ export default DrugSafetyService;
697
+ //# sourceMappingURL=drugInteractions.js.map