ezmedicationinput 0.1.43 → 0.1.44

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 (46) hide show
  1. package/README.md +4 -1
  2. package/dist/advice-rules.json +772 -0
  3. package/dist/advice-terminology.json +104 -0
  4. package/dist/advice.d.ts +16 -0
  5. package/dist/advice.js +1375 -0
  6. package/dist/event-trigger.d.ts +14 -0
  7. package/dist/event-trigger.js +501 -0
  8. package/dist/fhir-translations.d.ts +5 -0
  9. package/dist/fhir-translations.js +117 -0
  10. package/dist/fhir.d.ts +6 -4
  11. package/dist/fhir.js +566 -134
  12. package/dist/format.d.ts +4 -2
  13. package/dist/format.js +515 -218
  14. package/dist/i18n.d.ts +2 -2
  15. package/dist/i18n.js +641 -199
  16. package/dist/index.d.ts +0 -1
  17. package/dist/index.js +219 -168
  18. package/dist/internal-types.d.ts +5 -5
  19. package/dist/ir.d.ts +4 -0
  20. package/dist/ir.js +178 -0
  21. package/dist/lexer/lex.d.ts +2 -0
  22. package/dist/lexer/lex.js +401 -0
  23. package/dist/lexer/meaning.d.ts +71 -0
  24. package/dist/lexer/meaning.js +619 -0
  25. package/dist/lexer/surface.d.ts +2 -0
  26. package/dist/lexer/surface.js +62 -0
  27. package/dist/lexer/token-types.d.ts +36 -0
  28. package/dist/lexer/token-types.js +19 -0
  29. package/dist/maps.d.ts +6 -12
  30. package/dist/maps.js +793 -247
  31. package/dist/parser-state.d.ts +101 -0
  32. package/dist/parser-state.js +441 -0
  33. package/dist/parser.d.ts +7 -7
  34. package/dist/parser.js +3598 -1974
  35. package/dist/prn.d.ts +4 -0
  36. package/dist/prn.js +59 -0
  37. package/dist/schedule.js +230 -32
  38. package/dist/site-phrases.d.ts +35 -0
  39. package/dist/site-phrases.js +344 -0
  40. package/dist/timing-summary.d.ts +13 -3
  41. package/dist/timing-summary.js +7 -7
  42. package/dist/types.d.ts +237 -32
  43. package/dist/types.js +49 -1
  44. package/dist/utils/text.d.ts +3 -0
  45. package/dist/utils/text.js +48 -0
  46. package/package.json +1 -1
package/dist/types.d.ts CHANGED
@@ -3,14 +3,28 @@ export interface FhirCoding {
3
3
  system?: string;
4
4
  code?: string;
5
5
  display?: string;
6
+ _display?: FhirPrimitiveElement;
7
+ i18n?: Record<string, string>;
6
8
  }
7
9
  export interface FhirCodeableConcept {
8
10
  coding?: FhirCoding[];
9
11
  text?: string;
12
+ _text?: FhirPrimitiveElement;
13
+ }
14
+ export interface FhirExtension {
15
+ url: string;
16
+ extension?: FhirExtension[];
17
+ valueCode?: string;
18
+ valueString?: string;
19
+ }
20
+ export interface FhirPrimitiveElement {
21
+ extension?: FhirExtension[];
10
22
  }
11
23
  export interface FhirQuantity {
12
24
  value?: number;
13
25
  unit?: string;
26
+ system?: string;
27
+ code?: string;
14
28
  }
15
29
  export interface FhirRange {
16
30
  low?: FhirQuantity;
@@ -242,6 +256,8 @@ export declare enum FhirDayOfWeek {
242
256
  }
243
257
  export interface FhirTimingRepeat {
244
258
  count?: number;
259
+ boundsDuration?: FhirQuantity;
260
+ boundsRange?: FhirRange;
245
261
  frequency?: number;
246
262
  frequencyMax?: number;
247
263
  period?: number;
@@ -267,9 +283,11 @@ export interface FhirDoseAndRate {
267
283
  }
268
284
  export interface FhirDosage {
269
285
  text?: string;
286
+ patientInstruction?: string;
270
287
  timing?: FhirTiming;
271
288
  route?: FhirCodeableConcept;
272
289
  site?: FhirCodeableConcept;
290
+ method?: FhirCodeableConcept;
273
291
  additionalInstruction?: FhirCodeableConcept[];
274
292
  asNeededBoolean?: boolean;
275
293
  asNeededFor?: FhirCodeableConcept[];
@@ -319,21 +337,23 @@ export interface BodySiteCode {
319
337
  code: string;
320
338
  display?: string;
321
339
  system?: string;
340
+ i18n?: Record<string, string>;
322
341
  }
323
342
  export interface BodySiteDefinition {
324
343
  coding?: BodySiteCode;
325
344
  text?: string;
345
+ routeHint?: RouteCode;
326
346
  /**
327
347
  * Optional phrases that should resolve to the same coding as this entry.
328
348
  * Aliases are normalized with the same logic as map keys so callers can
329
349
  * provide punctuation-heavy variants such as "first bicuspid, left".
330
350
  */
331
- aliases?: string[];
351
+ aliases?: readonly string[];
332
352
  }
333
353
  export interface CodeableConceptDefinition {
334
354
  coding?: FhirCoding;
335
355
  text?: string;
336
- aliases?: string[];
356
+ aliases?: readonly string[];
337
357
  /** Optional translations for different locales (e.g., { "th": "ปวด" }) */
338
358
  i18n?: Record<string, string>;
339
359
  }
@@ -341,6 +361,71 @@ export interface PrnReasonDefinition extends CodeableConceptDefinition {
341
361
  }
342
362
  export interface AdditionalInstructionDefinition extends CodeableConceptDefinition {
343
363
  }
364
+ export declare enum AdvicePolarity {
365
+ Affirm = "affirm",
366
+ Negate = "negate"
367
+ }
368
+ export declare enum AdviceForce {
369
+ Instruction = "instruction",
370
+ Warning = "warning",
371
+ Caution = "caution",
372
+ Sequence = "sequence"
373
+ }
374
+ export declare enum AdviceModality {
375
+ May = "may",
376
+ Can = "can",
377
+ Might = "might",
378
+ Could = "could",
379
+ Should = "should",
380
+ Must = "must"
381
+ }
382
+ export declare enum AdviceRelation {
383
+ With = "with",
384
+ Without = "without",
385
+ Before = "before",
386
+ After = "after",
387
+ During = "during",
388
+ Then = "then",
389
+ Until = "until",
390
+ For = "for",
391
+ In = "in",
392
+ On = "on"
393
+ }
394
+ export declare enum AdviceArgumentRole {
395
+ Theme = "theme",
396
+ Object = "object",
397
+ Substance = "substance",
398
+ MealState = "meal_state",
399
+ Activity = "activity",
400
+ Material = "material",
401
+ Site = "site",
402
+ Amount = "amount",
403
+ Duration = "duration",
404
+ Time = "time",
405
+ Free = "free"
406
+ }
407
+ export interface AdviceArgument {
408
+ role: AdviceArgumentRole;
409
+ text: string;
410
+ normalized?: string;
411
+ conceptId?: string;
412
+ span?: TextRange;
413
+ }
414
+ export interface AdviceFrame {
415
+ force: AdviceForce;
416
+ polarity?: AdvicePolarity;
417
+ modality?: AdviceModality;
418
+ predicate: {
419
+ lemma: string;
420
+ semanticClass?: string;
421
+ };
422
+ relation?: AdviceRelation;
423
+ args: AdviceArgument[];
424
+ span: TextRange;
425
+ sourceText: string;
426
+ sequenceIndex?: number;
427
+ coding?: FhirCoding;
428
+ }
344
429
  export interface TextRange {
345
430
  /** Inclusive start index of the matched substring within the original input. */
346
431
  start: number;
@@ -433,6 +518,30 @@ export type SiteCodeResolver = (request: SiteCodeLookupRequest) => SiteCodeResol
433
518
  * caller's full input and the character range of the detected site phrase.
434
519
  */
435
520
  export type SiteCodeSuggestionResolver = (request: SiteCodeLookupRequest) => SiteCodeSuggestionsResult | SiteCodeSuggestion[] | SiteCodeSuggestion | null | undefined | Promise<SiteCodeSuggestionsResult | SiteCodeSuggestion[] | SiteCodeSuggestion | null | undefined>;
521
+ export interface SmartMealExpansionScope {
522
+ /**
523
+ * Optional allowlist of routes that may use smart meal expansion. When
524
+ * provided, non-matching routes are excluded unless a dosage form matches
525
+ * `includeDosageForms`.
526
+ */
527
+ includeRoutes?: RouteCode[];
528
+ /**
529
+ * Optional denylist of routes that must not use smart meal expansion.
530
+ * Exclusions take precedence over includes.
531
+ */
532
+ excludeRoutes?: RouteCode[];
533
+ /**
534
+ * Optional allowlist of dosage forms that may use smart meal expansion.
535
+ * Values are matched case-insensitively after dosage-form normalization.
536
+ */
537
+ includeDosageForms?: string[];
538
+ /**
539
+ * Optional denylist of dosage forms that must not use smart meal expansion.
540
+ * Values are matched case-insensitively after dosage-form normalization.
541
+ * Exclusions take precedence over includes.
542
+ */
543
+ excludeDosageForms?: string[];
544
+ }
436
545
  export interface ParseOptions extends FormatOptions {
437
546
  /**
438
547
  * Optional medication context that assists with default unit inference.
@@ -468,6 +577,12 @@ export interface ParseOptions extends FormatOptions {
468
577
  * `context.mealRelation` when provided.
469
578
  */
470
579
  smartMealExpansion?: boolean;
580
+ /**
581
+ * Optional route/dosage-form policy overrides for smart meal expansion.
582
+ * When omitted, the parser uses its built-in default heuristic.
583
+ * Exclusions take precedence over includes.
584
+ */
585
+ smartMealExpansionScope?: SmartMealExpansionScope;
471
586
  /**
472
587
  * Enables parsing meal dash shorthand like `1-0-1` / `1-0-0-1` into
473
588
  * multiple dosage clauses aligned to breakfast/lunch/dinner/(bedtime).
@@ -526,6 +641,95 @@ export interface ParseOptions extends FormatOptions {
526
641
  */
527
642
  prnReasonSuggestionResolvers?: PrnReasonSuggestionResolver | PrnReasonSuggestionResolver[];
528
643
  }
644
+ export interface CanonicalDoseRange {
645
+ low?: number;
646
+ high?: number;
647
+ }
648
+ export interface CanonicalDoseExpr {
649
+ value?: number;
650
+ range?: CanonicalDoseRange;
651
+ unit?: string;
652
+ evidence?: CanonicalEvidence[];
653
+ }
654
+ export interface CanonicalRouteExpr {
655
+ code?: RouteCode;
656
+ text?: string;
657
+ inferred?: boolean;
658
+ evidence?: CanonicalEvidence[];
659
+ }
660
+ export interface CanonicalSiteExpr {
661
+ text?: string;
662
+ coding?: BodySiteCode;
663
+ source?: "abbreviation" | "text" | "selection" | "resolver";
664
+ inferred?: boolean;
665
+ evidence?: CanonicalEvidence[];
666
+ }
667
+ export interface CanonicalMethodExpr {
668
+ text?: string;
669
+ _text?: FhirPrimitiveElement;
670
+ coding?: FhirCoding;
671
+ evidence?: CanonicalEvidence[];
672
+ }
673
+ export interface CanonicalScheduleExpr {
674
+ timingCode?: string;
675
+ count?: number;
676
+ duration?: number;
677
+ durationMax?: number;
678
+ durationUnit?: FhirPeriodUnit;
679
+ frequency?: number;
680
+ frequencyMax?: number;
681
+ period?: number;
682
+ periodMax?: number;
683
+ periodUnit?: FhirPeriodUnit;
684
+ dayOfWeek?: FhirDayOfWeek[];
685
+ when?: EventTiming[];
686
+ timeOfDay?: string[];
687
+ evidence?: CanonicalEvidence[];
688
+ }
689
+ export interface CanonicalPrnReasonExpr {
690
+ text?: string;
691
+ coding?: FhirCoding;
692
+ }
693
+ export interface CanonicalPrnExpr {
694
+ enabled: boolean;
695
+ reason?: CanonicalPrnReasonExpr;
696
+ reasons?: CanonicalPrnReasonExpr[];
697
+ evidence?: CanonicalEvidence[];
698
+ }
699
+ export interface CanonicalAdditionalInstructionExpr {
700
+ text?: string;
701
+ coding?: FhirCoding;
702
+ frames?: AdviceFrame[];
703
+ evidence?: CanonicalEvidence[];
704
+ }
705
+ export interface CanonicalSourceSpan extends TextRange {
706
+ text: string;
707
+ tokenIndices?: number[];
708
+ }
709
+ export interface CanonicalEvidence {
710
+ rule: string;
711
+ spans: CanonicalSourceSpan[];
712
+ score?: number;
713
+ note?: string;
714
+ }
715
+ export interface CanonicalSigClause {
716
+ kind: "administration";
717
+ rawText: string;
718
+ span?: TextRange;
719
+ raw: CanonicalSourceSpan;
720
+ dose?: CanonicalDoseExpr;
721
+ route?: CanonicalRouteExpr;
722
+ site?: CanonicalSiteExpr;
723
+ method?: CanonicalMethodExpr;
724
+ schedule?: CanonicalScheduleExpr;
725
+ prn?: CanonicalPrnExpr;
726
+ patientInstruction?: string;
727
+ additionalInstructions?: CanonicalAdditionalInstructionExpr[];
728
+ leftovers: CanonicalSourceSpan[];
729
+ evidence: CanonicalEvidence[];
730
+ confidence: number;
731
+ warnings?: string[];
732
+ }
529
733
  export interface ParseResult {
530
734
  fhir: FhirDosage;
531
735
  shortText: string;
@@ -534,21 +738,9 @@ export interface ParseResult {
534
738
  meta: {
535
739
  consumedTokens: string[];
536
740
  leftoverText?: string;
537
- normalized: {
538
- route?: RouteCode;
539
- unit?: string;
540
- site?: {
541
- text?: string;
542
- coding?: BodySiteCode;
543
- };
544
- prnReason?: {
545
- text?: string;
546
- coding?: FhirCoding;
547
- };
548
- additionalInstructions?: Array<{
549
- text?: string;
550
- coding?: FhirCoding;
551
- }>;
741
+ normalized: ParseNormalizedMeta;
742
+ canonical: {
743
+ clauses: CanonicalSigClause[];
552
744
  };
553
745
  siteLookups?: Array<{
554
746
  request: SiteCodeLookupRequest;
@@ -560,6 +752,31 @@ export interface ParseResult {
560
752
  }>;
561
753
  };
562
754
  }
755
+ export interface ParseNormalizedMeta {
756
+ route?: RouteCode;
757
+ unit?: string;
758
+ site?: {
759
+ text?: string;
760
+ coding?: BodySiteCode;
761
+ };
762
+ method?: {
763
+ text?: string;
764
+ coding?: FhirCoding;
765
+ };
766
+ patientInstruction?: string;
767
+ prnReason?: {
768
+ text?: string;
769
+ coding?: FhirCoding;
770
+ };
771
+ prnReasons?: Array<{
772
+ text?: string;
773
+ coding?: FhirCoding;
774
+ }>;
775
+ additionalInstructions?: Array<{
776
+ text?: string;
777
+ coding?: FhirCoding;
778
+ }>;
779
+ }
563
780
  export interface ParseBatchSegmentMeta {
564
781
  index: number;
565
782
  text: string;
@@ -588,21 +805,9 @@ export interface ParseBatchResult {
588
805
  meta: {
589
806
  consumedTokens: string[];
590
807
  leftoverText?: string;
591
- normalized: {
592
- route?: RouteCode;
593
- unit?: string;
594
- site?: {
595
- text?: string;
596
- coding?: BodySiteCode;
597
- };
598
- prnReason?: {
599
- text?: string;
600
- coding?: FhirCoding;
601
- };
602
- additionalInstructions?: Array<{
603
- text?: string;
604
- coding?: FhirCoding;
605
- }>;
808
+ normalized: ParseNormalizedMeta;
809
+ canonical: {
810
+ clauses: CanonicalSigClause[];
606
811
  };
607
812
  siteLookups?: Array<{
608
813
  request: SiteCodeLookupRequest;
package/dist/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RouteCode = exports.FhirDayOfWeek = exports.FhirPeriodUnit = exports.SNOMEDCTRouteCodes = exports.EventTiming = void 0;
3
+ exports.AdviceArgumentRole = exports.AdviceRelation = exports.AdviceModality = exports.AdviceForce = exports.AdvicePolarity = exports.RouteCode = exports.FhirDayOfWeek = exports.FhirPeriodUnit = exports.SNOMEDCTRouteCodes = exports.EventTiming = void 0;
4
4
  /**
5
5
  * Follows https://build.fhir.org/valueset-event-timing.html
6
6
  * Real-world event relating to the schedule.
@@ -226,3 +226,51 @@ var FhirDayOfWeek;
226
226
  FhirDayOfWeek["Sunday"] = "sun";
227
227
  })(FhirDayOfWeek || (exports.FhirDayOfWeek = FhirDayOfWeek = {}));
228
228
  exports.RouteCode = SNOMEDCTRouteCodes;
229
+ var AdvicePolarity;
230
+ (function (AdvicePolarity) {
231
+ AdvicePolarity["Affirm"] = "affirm";
232
+ AdvicePolarity["Negate"] = "negate";
233
+ })(AdvicePolarity || (exports.AdvicePolarity = AdvicePolarity = {}));
234
+ var AdviceForce;
235
+ (function (AdviceForce) {
236
+ AdviceForce["Instruction"] = "instruction";
237
+ AdviceForce["Warning"] = "warning";
238
+ AdviceForce["Caution"] = "caution";
239
+ AdviceForce["Sequence"] = "sequence";
240
+ })(AdviceForce || (exports.AdviceForce = AdviceForce = {}));
241
+ var AdviceModality;
242
+ (function (AdviceModality) {
243
+ AdviceModality["May"] = "may";
244
+ AdviceModality["Can"] = "can";
245
+ AdviceModality["Might"] = "might";
246
+ AdviceModality["Could"] = "could";
247
+ AdviceModality["Should"] = "should";
248
+ AdviceModality["Must"] = "must";
249
+ })(AdviceModality || (exports.AdviceModality = AdviceModality = {}));
250
+ var AdviceRelation;
251
+ (function (AdviceRelation) {
252
+ AdviceRelation["With"] = "with";
253
+ AdviceRelation["Without"] = "without";
254
+ AdviceRelation["Before"] = "before";
255
+ AdviceRelation["After"] = "after";
256
+ AdviceRelation["During"] = "during";
257
+ AdviceRelation["Then"] = "then";
258
+ AdviceRelation["Until"] = "until";
259
+ AdviceRelation["For"] = "for";
260
+ AdviceRelation["In"] = "in";
261
+ AdviceRelation["On"] = "on";
262
+ })(AdviceRelation || (exports.AdviceRelation = AdviceRelation = {}));
263
+ var AdviceArgumentRole;
264
+ (function (AdviceArgumentRole) {
265
+ AdviceArgumentRole["Theme"] = "theme";
266
+ AdviceArgumentRole["Object"] = "object";
267
+ AdviceArgumentRole["Substance"] = "substance";
268
+ AdviceArgumentRole["MealState"] = "meal_state";
269
+ AdviceArgumentRole["Activity"] = "activity";
270
+ AdviceArgumentRole["Material"] = "material";
271
+ AdviceArgumentRole["Site"] = "site";
272
+ AdviceArgumentRole["Amount"] = "amount";
273
+ AdviceArgumentRole["Duration"] = "duration";
274
+ AdviceArgumentRole["Time"] = "time";
275
+ AdviceArgumentRole["Free"] = "free";
276
+ })(AdviceArgumentRole || (exports.AdviceArgumentRole = AdviceArgumentRole = {}));
@@ -0,0 +1,3 @@
1
+ export declare function isWhitespaceChar(char: string): boolean;
2
+ export declare function isLoosePhraseSeparatorChar(char: string): boolean;
3
+ export declare function normalizeLoosePhraseKey(value: string): string;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isWhitespaceChar = isWhitespaceChar;
4
+ exports.isLoosePhraseSeparatorChar = isLoosePhraseSeparatorChar;
5
+ exports.normalizeLoosePhraseKey = normalizeLoosePhraseKey;
6
+ function isWhitespaceChar(char) {
7
+ const code = char.charCodeAt(0);
8
+ return (code <= 0x20 ||
9
+ code === 0x00a0 ||
10
+ code === 0x1680 ||
11
+ (code >= 0x2000 && code <= 0x200a) ||
12
+ code === 0x2028 ||
13
+ code === 0x2029 ||
14
+ code === 0x202f ||
15
+ code === 0x205f ||
16
+ code === 0x3000);
17
+ }
18
+ function isAsciiPunctuationCode(code) {
19
+ return ((code >= 0x21 && code <= 0x2f) ||
20
+ (code >= 0x3a && code <= 0x40) ||
21
+ (code >= 0x5b && code <= 0x60) ||
22
+ (code >= 0x7b && code <= 0x7e));
23
+ }
24
+ function isLoosePhraseSeparatorChar(char) {
25
+ const code = char.charCodeAt(0);
26
+ return (isWhitespaceChar(char) ||
27
+ isAsciiPunctuationCode(code) ||
28
+ (code >= 0x2000 && code <= 0x206f) ||
29
+ (code >= 0x2e00 && code <= 0x2e7f) ||
30
+ (code >= 0x3000 && code <= 0x303f));
31
+ }
32
+ function normalizeLoosePhraseKey(value) {
33
+ const lowered = value.trim().toLowerCase();
34
+ let normalized = "";
35
+ let pendingSpace = false;
36
+ for (const char of lowered) {
37
+ if (isLoosePhraseSeparatorChar(char)) {
38
+ pendingSpace = normalized.length > 0;
39
+ continue;
40
+ }
41
+ if (pendingSpace) {
42
+ normalized += " ";
43
+ pendingSpace = false;
44
+ }
45
+ normalized += char;
46
+ }
47
+ return normalized.trim();
48
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ezmedicationinput",
3
- "version": "0.1.43",
3
+ "version": "0.1.44",
4
4
  "description": "Parse concise medication sigs into FHIR R5 Dosage JSON",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",