ezmedicationinput 0.1.44 → 0.1.46

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 (75) hide show
  1. package/README.md +265 -2
  2. package/dist/body-site-grammar.d.ts +39 -0
  3. package/dist/body-site-lookup.d.ts +84 -0
  4. package/dist/body-site-resolution.d.ts +9 -0
  5. package/dist/body-site-spatial.d.ts +6 -0
  6. package/dist/clause-tail-grammar.d.ts +18 -0
  7. package/dist/fhir-translations.d.ts +4 -1
  8. package/dist/fhir.d.ts +9 -1
  9. package/dist/hpsg/chart.d.ts +14 -0
  10. package/dist/hpsg/clause-parser.d.ts +3 -0
  11. package/dist/hpsg/defaults.d.ts +9 -0
  12. package/dist/hpsg/lexical-classes.d.ts +89 -0
  13. package/dist/hpsg/method-lexicon.d.ts +13 -0
  14. package/dist/hpsg/projection.d.ts +12 -0
  15. package/dist/hpsg/rule-context.d.ts +32 -0
  16. package/dist/hpsg/rules/core-rules.d.ts +8 -0
  17. package/dist/hpsg/rules/instruction-rules.d.ts +4 -0
  18. package/dist/hpsg/rules/prn-rules.d.ts +3 -0
  19. package/dist/hpsg/rules/product-route.d.ts +2 -0
  20. package/dist/hpsg/rules/site-rules.d.ts +4 -0
  21. package/dist/hpsg/rules/timing-rules.d.ts +12 -0
  22. package/dist/hpsg/segmenter.d.ts +6 -0
  23. package/dist/hpsg/signature.d.ts +116 -0
  24. package/dist/hpsg/timing-lexicon.d.ts +31 -0
  25. package/dist/hpsg/unification.d.ts +8 -0
  26. package/dist/index.cjs +21052 -0
  27. package/dist/index.d.ts +5 -0
  28. package/dist/index.js +20865 -680
  29. package/dist/maps.d.ts +4 -2
  30. package/dist/parser-state.d.ts +4 -1
  31. package/dist/parser.d.ts +3 -13
  32. package/dist/prn-reason-coding.d.ts +8 -0
  33. package/dist/site-coding.d.ts +5 -0
  34. package/dist/snomed-postcoordination.d.ts +25 -0
  35. package/dist/snomed.d.ts +13 -0
  36. package/dist/types.d.ts +61 -16
  37. package/dist/unit-lexicon.d.ts +4 -0
  38. package/package.json +17 -6
  39. package/dist/advice-rules.json +0 -772
  40. package/dist/advice-terminology.json +0 -104
  41. package/dist/advice.js +0 -1375
  42. package/dist/context.js +0 -50
  43. package/dist/event-trigger.d.ts +0 -14
  44. package/dist/event-trigger.js +0 -501
  45. package/dist/fhir-translations.js +0 -117
  46. package/dist/fhir.js +0 -693
  47. package/dist/format.js +0 -1034
  48. package/dist/i18n.js +0 -1341
  49. package/dist/internal-types.d.ts +0 -60
  50. package/dist/internal-types.js +0 -2
  51. package/dist/ir.js +0 -178
  52. package/dist/lexer/lex.js +0 -401
  53. package/dist/lexer/meaning.js +0 -619
  54. package/dist/lexer/surface.js +0 -62
  55. package/dist/lexer/token-types.js +0 -19
  56. package/dist/maps.js +0 -2226
  57. package/dist/package.json +0 -3
  58. package/dist/parser-state.js +0 -441
  59. package/dist/parser.js +0 -5631
  60. package/dist/prn.js +0 -59
  61. package/dist/safety.js +0 -15
  62. package/dist/schedule.js +0 -1636
  63. package/dist/segment.d.ts +0 -6
  64. package/dist/segment.js +0 -203
  65. package/dist/site-phrases.js +0 -344
  66. package/dist/suggest.js +0 -907
  67. package/dist/timing-summary.js +0 -138
  68. package/dist/types.js +0 -276
  69. package/dist/utils/array.js +0 -11
  70. package/dist/utils/enum.d.ts +0 -2
  71. package/dist/utils/enum.js +0 -7
  72. package/dist/utils/object.js +0 -34
  73. package/dist/utils/strength.js +0 -149
  74. package/dist/utils/text.js +0 -48
  75. package/dist/utils/units.js +0 -82
package/dist/maps.d.ts CHANGED
@@ -25,10 +25,11 @@ export declare const DEFAULT_ROUTE_SYNONYMS: Record<string, RouteSynonym>;
25
25
  * same logic to ensure consistent lookups.
26
26
  */
27
27
  export declare function normalizeBodySiteKey(value: string): string;
28
- export declare const DEFAULT_BODY_SITE_SNOMED_SOURCE: Array<{
28
+ type BodySiteSnomedSourceEntry = {
29
29
  names: string[];
30
30
  definition: BodySiteDefinition;
31
- }>;
31
+ };
32
+ export declare const DEFAULT_BODY_SITE_SNOMED_SOURCE: BodySiteSnomedSourceEntry[];
32
33
  export declare const DEFAULT_BODY_SITE_SNOMED: Record<string, BodySiteDefinition>;
33
34
  export declare const DEFAULT_BODY_SITE_HINTS: Set<string>;
34
35
  export declare const HOUSEHOLD_VOLUME_UNITS: readonly ["tsp", "tbsp"];
@@ -80,3 +81,4 @@ export declare const DEFAULT_PRN_REASON_DEFINITIONS: Record<string, PrnReasonDef
80
81
  * Finds a default PRN reason definition by its SNOMED coding.
81
82
  */
82
83
  export declare function findPrnReasonDefinitionByCoding(system: string, code: string): PrnReasonDefinition | undefined;
84
+ export {};
@@ -1,5 +1,5 @@
1
1
  import { AnnotatedLexToken } from "./lexer/meaning";
2
- import { CanonicalAdditionalInstructionExpr, CanonicalDoseRange, CanonicalPrnReasonExpr, CanonicalSigClause, EventTiming, FhirCoding, FhirDayOfWeek, FhirPrimitiveElement, FhirPeriodUnit, PrnReasonLookupRequest, PrnReasonSuggestion, RouteCode, SiteCodeLookupRequest, SiteCodeSuggestion } from "./types";
2
+ import { CanonicalAdditionalInstructionExpr, BodySiteSpatialRelation, CanonicalDoseRange, CanonicalPrnReasonExpr, CanonicalSigClause, EventTiming, FhirCoding, FhirDayOfWeek, FhirPrimitiveElement, FhirPeriodUnit, PrnReasonLookupRequest, PrnReasonSuggestion, RouteCode, SiteCodeLookupRequest, SiteCodeSuggestion } from "./types";
3
3
  export interface SiteLookupDetail {
4
4
  request: SiteCodeLookupRequest;
5
5
  suggestions: SiteCodeSuggestion[];
@@ -23,6 +23,7 @@ export declare class ParserState {
23
23
  siteLookups: SiteLookupDetail[];
24
24
  customSiteHints?: Set<string>;
25
25
  prnReasonLookupRequest?: PrnReasonLookupRequest;
26
+ prnReasonLookupRequests?: PrnReasonLookupRequest[];
26
27
  prnReasonLookups: PrnReasonLookupDetail[];
27
28
  methodVerb?: string;
28
29
  productFormKey?: string;
@@ -84,6 +85,8 @@ export declare class ParserState {
84
85
  set siteSource(value: "abbreviation" | "text" | "selection" | "resolver" | undefined);
85
86
  get siteCoding(): LocalizedCoding | undefined;
86
87
  set siteCoding(value: LocalizedCoding | undefined);
88
+ get siteSpatialRelation(): BodySiteSpatialRelation | undefined;
89
+ set siteSpatialRelation(value: BodySiteSpatialRelation | undefined);
87
90
  get additionalInstructions(): CanonicalAdditionalInstructionExpr[];
88
91
  set additionalInstructions(value: CanonicalAdditionalInstructionExpr[]);
89
92
  get patientInstruction(): string | undefined;
package/dist/parser.d.ts CHANGED
@@ -1,20 +1,10 @@
1
1
  import { ParserState, Token } from "./parser-state";
2
+ export { applyPrnReasonCoding, applyPrnReasonCodingAsync } from "./prn-reason-coding";
3
+ export { applySiteCoding, applySiteCodingAsync } from "./site-coding";
2
4
  import { ParseOptions, TextRange } from "./types";
3
5
  export declare function tokenize(input: string): Token[];
4
- export declare function findUnparsedTokenGroups(internal: ParserState): Array<{
6
+ export declare function findUnparsedTokenGroups(state: ParserState): Array<{
5
7
  tokens: Token[];
6
8
  range?: TextRange;
7
9
  }>;
8
10
  export declare function parseClauseState(input: string, options?: ParseOptions): ParserState;
9
- /**
10
- * Resolves parsed site text against SNOMED dictionaries and synchronous
11
- * callbacks, applying the best match to the in-progress parse result.
12
- */
13
- export declare function applyPrnReasonCoding(internal: ParserState, options?: ParseOptions): void;
14
- export declare function applyPrnReasonCodingAsync(internal: ParserState, options?: ParseOptions): Promise<void>;
15
- export declare function applySiteCoding(internal: ParserState, options?: ParseOptions): void;
16
- /**
17
- * Asynchronous counterpart to {@link applySiteCoding} that awaits resolver and
18
- * suggestion callbacks so remote terminology services can be used.
19
- */
20
- export declare function applySiteCodingAsync(internal: ParserState, options?: ParseOptions): Promise<void>;
@@ -0,0 +1,8 @@
1
+ import { ParserState } from "./parser-state";
2
+ import { ParseOptions } from "./types";
3
+ /**
4
+ * Resolves parsed PRN reason text against SNOMED dictionaries and synchronous
5
+ * callbacks, applying the best match to the in-progress parse result.
6
+ */
7
+ export declare function applyPrnReasonCoding(internal: ParserState, options?: ParseOptions): void;
8
+ export declare function applyPrnReasonCodingAsync(internal: ParserState, options?: ParseOptions): Promise<void>;
@@ -0,0 +1,5 @@
1
+ import { ParserState } from "./parser-state";
2
+ import { BodySiteDefinition, ParseOptions } from "./types";
3
+ export declare function applySiteCoding(internal: ParserState, options?: ParseOptions): void;
4
+ export declare function applySiteCodingAsync(internal: ParserState, options?: ParseOptions): Promise<void>;
5
+ export declare function lookupBodySiteDefinition(map: Record<string, BodySiteDefinition> | undefined, canonical: string): BodySiteDefinition | undefined;
@@ -0,0 +1,25 @@
1
+ import { BodySiteSpatialRelation, FhirCoding } from "./types";
2
+ export declare function hasSnomedFindingSitePostcoordination(code: string | undefined): boolean;
3
+ export declare function buildSnomedFindingSitePostcoordinationCode(focusCode: string, siteCode: string): string;
4
+ export declare function hasSnomedTopographicalModifierPostcoordination(code: string | undefined): boolean;
5
+ export declare function buildSnomedBodySiteTopographicalModifierPostcoordinationCode(siteCode: string, modifierCode: string): string;
6
+ export declare function hasSnomedBodySiteLateralityPostcoordination(code: string | undefined): boolean;
7
+ export declare function buildSnomedBodySiteLateralityPostcoordinationCode(siteCode: string, lateralityCode: string): string;
8
+ export declare function parseSnomedBodySiteTopographicalModifierPostcoordinationCode(code: string | undefined): {
9
+ siteCode: string;
10
+ modifierCode: string;
11
+ } | undefined;
12
+ export declare function parseSnomedBodySiteLateralityPostcoordinationCode(code: string | undefined): {
13
+ siteCode: string;
14
+ lateralityCode: string;
15
+ } | undefined;
16
+ export declare function parseSnomedFindingSitePostcoordinationCode(code: string | undefined): {
17
+ focusCode: string;
18
+ siteCode: string;
19
+ } | undefined;
20
+ export declare function buildSnomedFindingSiteCoding(params: {
21
+ focusCoding: FhirCoding | undefined;
22
+ siteCoding: FhirCoding | undefined;
23
+ display?: string;
24
+ spatialRelation?: BodySiteSpatialRelation;
25
+ }): FhirCoding | undefined;
@@ -0,0 +1,13 @@
1
+ export declare const SNOMED_SYSTEM = "http://snomed.info/sct";
2
+ export declare const SNOMED_CT_FINDING_SITE_ATTRIBUTE_CODE = "363698007";
3
+ export declare const SNOMED_CT_FINDING_SITE_ATTRIBUTE_DISPLAY = "Finding site";
4
+ export declare const SNOMED_CT_TOPOGRAPHICAL_MODIFIER_CODE = "106233006";
5
+ export declare const SNOMED_CT_TOPOGRAPHICAL_MODIFIER_DISPLAY = "Topographical modifier";
6
+ export declare const SNOMED_CT_LATERALITY_ATTRIBUTE_CODE = "272741003";
7
+ export declare const SNOMED_CT_LATERALITY_ATTRIBUTE_DISPLAY = "Laterality";
8
+ export declare const SNOMED_CT_LEFT_QUALIFIER_CODE = "7771000";
9
+ export declare const SNOMED_CT_LEFT_QUALIFIER_DISPLAY = "Left";
10
+ export declare const SNOMED_CT_RIGHT_QUALIFIER_CODE = "24028007";
11
+ export declare const SNOMED_CT_RIGHT_QUALIFIER_DISPLAY = "Right";
12
+ export declare const SNOMED_CT_BILATERAL_QUALIFIER_CODE = "51440002";
13
+ export declare const SNOMED_CT_BILATERAL_QUALIFIER_DISPLAY = "Right and left";
package/dist/types.d.ts CHANGED
@@ -3,12 +3,14 @@ export interface FhirCoding {
3
3
  system?: string;
4
4
  code?: string;
5
5
  display?: string;
6
+ extension?: FhirExtension[];
6
7
  _display?: FhirPrimitiveElement;
7
8
  i18n?: Record<string, string>;
8
9
  }
9
10
  export interface FhirCodeableConcept {
10
11
  coding?: FhirCoding[];
11
12
  text?: string;
13
+ extension?: FhirExtension[];
12
14
  _text?: FhirPrimitiveElement;
13
15
  }
14
16
  export interface FhirExtension {
@@ -16,6 +18,8 @@ export interface FhirExtension {
16
18
  extension?: FhirExtension[];
17
19
  valueCode?: string;
18
20
  valueString?: string;
21
+ valueCoding?: FhirCoding;
22
+ valueCodeableConcept?: FhirCodeableConcept;
19
23
  }
20
24
  export interface FhirPrimitiveElement {
21
25
  extension?: FhirExtension[];
@@ -297,6 +301,12 @@ export type RouteCode = SNOMEDCTRouteCodes;
297
301
  export declare const RouteCode: typeof SNOMEDCTRouteCodes;
298
302
  export interface MedicationContext {
299
303
  dosageForm?: string;
304
+ /**
305
+ * Optional anatomical context used to disambiguate shorthand body-site
306
+ * phrases, e.g. Thai "ระหว่างนิ้ว" can mean fingers by default but toes
307
+ * when the active context is foot/feet/toes.
308
+ */
309
+ bodySiteContext?: string;
300
310
  /** "Simple" strength string; might be the only way strength is provided
301
311
  * for discrete units this is the amount of medication for unit e.g. "500 mg" (1 tablet), or for mixed tablets might be like "400 mg + 80 mg"
302
312
  * for things like creams or fluids or syrupsit might be "2%", 5 g/100g, 100mg/ 100 g, 262 mg/15 mL, 200 mg/2 mL, 1 mg/dL, or "400 mg/5mL + 80 mg/5mL"
@@ -339,9 +349,17 @@ export interface BodySiteCode {
339
349
  system?: string;
340
350
  i18n?: Record<string, string>;
341
351
  }
352
+ export interface BodySiteSpatialRelation {
353
+ relationText: string;
354
+ relationCoding?: FhirCoding;
355
+ targetText?: string;
356
+ targetCoding?: BodySiteCode;
357
+ sourceText?: string;
358
+ }
342
359
  export interface BodySiteDefinition {
343
360
  coding?: BodySiteCode;
344
361
  text?: string;
362
+ spatialRelation?: BodySiteSpatialRelation;
345
363
  routeHint?: RouteCode;
346
364
  /**
347
365
  * Optional phrases that should resolve to the same coding as this entry.
@@ -455,6 +473,12 @@ export interface SiteCodeLookupRequest {
455
473
  sourceText?: string;
456
474
  /** Location of {@link sourceText} relative to the original input. */
457
475
  range?: TextRange;
476
+ /**
477
+ * Parsed spatial relation when the site phrase is relation + body site
478
+ * (for example, "below ear" or "top of hand"). Terminology callbacks can
479
+ * use this to code either the full site phrase or the relation target.
480
+ */
481
+ spatialRelation?: BodySiteSpatialRelation;
458
482
  }
459
483
  export interface SiteCodeResolution extends BodySiteDefinition {
460
484
  }
@@ -465,11 +489,22 @@ export interface SiteCodeSuggestion {
465
489
  export interface SiteCodeSuggestionsResult {
466
490
  suggestions: SiteCodeSuggestion[];
467
491
  }
492
+ /**
493
+ * PRN reason lookup context. For located reasons such as "pain at hand",
494
+ * `headCanonical` is the symptom head ("pain"), `locativeSiteCanonical` is the
495
+ * parsed site key when known ("hand"), `locativeSiteCoding` is preferred for
496
+ * coded SNOMED/FHIR output when present, and `locativeSiteSpatialRelation`
497
+ * carries modifiers such as "below ear" that refine the locative site.
498
+ */
468
499
  export interface PrnReasonLookupRequest {
469
500
  originalText: string;
470
501
  text: string;
471
502
  normalized: string;
472
503
  canonical: string;
504
+ headCanonical?: string;
505
+ locativeSiteCanonical?: string;
506
+ locativeSiteCoding?: FhirCoding;
507
+ locativeSiteSpatialRelation?: BodySiteSpatialRelation;
473
508
  isProbe: boolean;
474
509
  inputText: string;
475
510
  sourceText?: string;
@@ -606,6 +641,13 @@ export interface ParseOptions extends FormatOptions {
606
641
  * the default site dictionary (trimmed, lower-cased, collapsing whitespace).
607
642
  */
608
643
  siteCodeMap?: Record<string, BodySiteDefinition>;
644
+ /**
645
+ * Defaults to true. When true, parsed spatial body-site phrases without a
646
+ * direct pre-coordinated site code may emit SNOMED topographical modifier
647
+ * postcoordination in FHIR Dosage.site.coding while preserving the structured
648
+ * spatial-relation extension.
649
+ */
650
+ bodySitePostcoordination?: boolean;
609
651
  /**
610
652
  * Explicit selections that override automatic site resolution for matching
611
653
  * phrases. Useful when custom dictionaries provide multiple options but a UI
@@ -660,6 +702,7 @@ export interface CanonicalRouteExpr {
660
702
  export interface CanonicalSiteExpr {
661
703
  text?: string;
662
704
  coding?: BodySiteCode;
705
+ spatialRelation?: BodySiteSpatialRelation;
663
706
  source?: "abbreviation" | "text" | "selection" | "resolver";
664
707
  inferred?: boolean;
665
708
  evidence?: CanonicalEvidence[];
@@ -689,6 +732,7 @@ export interface CanonicalScheduleExpr {
689
732
  export interface CanonicalPrnReasonExpr {
690
733
  text?: string;
691
734
  coding?: FhirCoding;
735
+ spatialRelation?: BodySiteSpatialRelation;
692
736
  }
693
737
  export interface CanonicalPrnExpr {
694
738
  enabled: boolean;
@@ -755,28 +799,29 @@ export interface ParseResult {
755
799
  export interface ParseNormalizedMeta {
756
800
  route?: RouteCode;
757
801
  unit?: string;
758
- site?: {
759
- text?: string;
760
- coding?: BodySiteCode;
761
- };
802
+ site?: BodySiteDetail;
762
803
  method?: {
763
804
  text?: string;
764
805
  coding?: FhirCoding;
765
806
  };
766
807
  patientInstruction?: string;
767
- prnReason?: {
768
- text?: string;
769
- coding?: FhirCoding;
770
- };
771
- prnReasons?: Array<{
772
- text?: string;
773
- coding?: FhirCoding;
774
- }>;
808
+ prnReason?: ConceptSiteDetail;
809
+ prnReasons?: ConceptSiteDetail[];
775
810
  additionalInstructions?: Array<{
776
811
  text?: string;
777
812
  coding?: FhirCoding;
778
813
  }>;
779
814
  }
815
+ export interface BodySiteDetail {
816
+ text?: string;
817
+ coding?: BodySiteCode;
818
+ spatialRelation?: BodySiteSpatialRelation;
819
+ }
820
+ export interface ConceptSiteDetail {
821
+ text?: string;
822
+ coding?: FhirCoding;
823
+ spatialRelation?: BodySiteSpatialRelation;
824
+ }
780
825
  export interface ParseBatchSegmentMeta {
781
826
  index: number;
782
827
  text: string;
@@ -787,17 +832,17 @@ export interface ParseBatchResult {
787
832
  count: number;
788
833
  items: ParseResult[];
789
834
  /**
790
- * Legacy compatibility field mirroring the first parsed item so existing
835
+ * Top-level compatibility field mirroring the first parsed item so existing
791
836
  * single-sig integrations can migrate incrementally.
792
837
  */
793
838
  fhir: FhirDosage;
794
839
  /**
795
- * Legacy compatibility field mirroring the first parsed item so existing
840
+ * Top-level compatibility field mirroring the first parsed item so existing
796
841
  * single-sig integrations can migrate incrementally.
797
842
  */
798
843
  shortText: string;
799
844
  /**
800
- * Legacy compatibility field mirroring the first parsed item so existing
845
+ * Top-level compatibility field mirroring the first parsed item so existing
801
846
  * single-sig integrations can migrate incrementally.
802
847
  */
803
848
  longText: string;
@@ -841,7 +886,7 @@ export interface LintBatchResult {
841
886
  count: number;
842
887
  items: LintResult[];
843
888
  /**
844
- * Legacy compatibility fields mirroring the first parsed item so existing
889
+ * Top-level compatibility fields mirroring the first parsed item so existing
845
890
  * consumers of `lintSig` can migrate incrementally.
846
891
  */
847
892
  result: ParseResult;
@@ -0,0 +1,4 @@
1
+ import { ParseOptions } from "./types";
2
+ export declare function normalizeUnit(token: string, options?: ParseOptions): string | undefined;
3
+ export declare function enforceHouseholdUnitPolicy(unit: string | undefined, options?: ParseOptions): string | undefined;
4
+ export declare function isDiscreteUnit(unit: string): boolean;
package/package.json CHANGED
@@ -1,13 +1,23 @@
1
1
  {
2
2
  "name": "ezmedicationinput",
3
- "version": "0.1.44",
3
+ "version": "0.1.46",
4
4
  "description": "Parse concise medication sigs into FHIR R5 Dosage JSON",
5
5
  "type": "module",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
8
17
  "scripts": {
9
- "build": "tsc -p tsconfig.json && node scripts/postbuild.cjs",
10
- "test": "vitest run"
18
+ "test:dist": "npm run build && vitest run test-dist",
19
+ "build": "tsup && tsc -p tsconfig.types.json",
20
+ "test": "vitest run --dir test"
11
21
  },
12
22
  "files": [
13
23
  "dist"
@@ -26,7 +36,8 @@
26
36
  },
27
37
  "bugs": "https://github.com/swittk/ezmedicationinput/issues",
28
38
  "devDependencies": {
39
+ "tsup": "^8.5.1",
29
40
  "typescript": "^5.4.0",
30
41
  "vitest": "^1.5.0"
31
42
  }
32
- }
43
+ }