ezmedicationinput 0.1.45 → 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 (39) 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 +14338 -12128
  27. package/dist/index.d.ts +5 -0
  28. package/dist/index.js +14299 -12128
  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 +1 -1
  39. package/dist/segment.d.ts +0 -6
package/README.md CHANGED
@@ -17,6 +17,12 @@
17
17
  - Surfaces warnings when discouraged tokens (`QD`, `QOD`, `BLD`) are used and optionally rejects them.
18
18
  - Generates upcoming administration timestamps from FHIR dosage data via `nextDueDoses` using configurable clinic clocks.
19
19
  - Auto-codes common body-site phrases (e.g. "left arm", "right eye") with SNOMED CT anatomy concepts and supports interactive lookup flows for ambiguous sites.
20
+ - Represents spatial body-site phrases such as `below ear`, `right side of abdomen`, `between fingers`, and Thai forms like `ระหว่างนิ้วมือ` through structured site metadata.
21
+ - Exposes body-site lookup/suggestion/listing helpers and SNOMED postcoordination helpers for UI search and terminology workflows.
22
+
23
+ ## Parser architecture
24
+
25
+ The parser is built around an HPSG-style lexical/sign grammar: tokens become typed signs, signs unify into clause-level structures, and the final projection emits FHIR `Dosage`. It is **not** a pure academic HPSG implementation; deterministic projection is still required for FHIR shape, terminology lookup, formatting, and compatibility behavior.
20
26
 
21
27
  ## Installation
22
28
 
@@ -255,10 +261,175 @@ result.fhir.site?.coding?.[0];
255
261
  // → { system: "http://snomed.info/sct", code: "368208006", display: "Left upper arm structure" }
256
262
  ```
257
263
 
264
+ Spatial site phrases are preserved as structured metadata on `Dosage.site.extension`
265
+ and in `ParseResult.meta.normalized.site.spatialRelation`.
266
+
267
+ ```ts
268
+ const result = parseSig("apply to area between fingers");
269
+
270
+ result.fhir.site?.text;
271
+ // → "area between fingers"
272
+
273
+ result.meta.normalized.site?.spatialRelation;
274
+ // → {
275
+ // relationText: "between",
276
+ // targetText: "fingers",
277
+ // targetCoding: {
278
+ // system: "http://snomed.info/sct",
279
+ // code: "7569003",
280
+ // display: "Finger structure"
281
+ // }
282
+ // }
283
+ ```
284
+
285
+ Only relations that exist in the FHIR BodyStructure relative-location ValueSet
286
+ receive `spatialRelation.relationCoding` (for example `Above`, `Beneath`,
287
+ `Posterior`, `Upper`, `Lower`, and `Lateral`). Other useful spatial language,
288
+ such as `between`, `around`, `near`, and `inside`, is preserved as
289
+ `relationText` without pretending there is an official code for it.
290
+
291
+ Thai and mixed-language site phrases resolve through the same site grammar:
292
+
293
+ ```ts
294
+ parseSig("apply ระหว่างนิ้วมือ", { locale: "th" }).longText;
295
+ // → "ทา บริเวณระหว่างนิ้วมือ."
296
+
297
+ parseSig("apply ระหว่างนิ้วเท้า", { locale: "th" }).longText;
298
+ // → "ทา บริเวณระหว่างนิ้วเท้า."
299
+
300
+ parseSig("apply ระหว่างนิ้ว", {
301
+ locale: "th",
302
+ context: { bodySiteContext: "feet" }
303
+ }).longText;
304
+ // → "ทา บริเวณระหว่างนิ้วเท้า."
305
+ ```
306
+
258
307
  When the parser encounters an unfamiliar site, it leaves the text untouched and records nothing in `meta.siteLookups`. Wrapping the phrase in braces (e.g. `apply to {mole on scalp}`) preserves the same parsing behavior but flags the entry as a **probe** so `meta.siteLookups` always contains the request. This allows UIs to display lookup widgets even before a matching code exists. Braces are optional when the site is already recognized—they simply make the clinician's intent explicit.
259
308
 
260
309
  Unknown body sites still populate `Dosage.site.text` and `ParseResult.meta.normalized.site.text`, allowing UIs to echo the verbatim phrase while terminology lookups run asynchronously.
261
310
 
311
+ For typeahead/search UI, use the exported body-site helpers directly:
312
+
313
+ ```ts
314
+ import {
315
+ getBodySiteCode,
316
+ getBodySiteCodeAsync,
317
+ getBodySiteText,
318
+ getBodySiteTextAsync,
319
+ listSupportedBodySiteGrammar,
320
+ listSupportedBodySiteText,
321
+ lookupBodySite,
322
+ suggestBodySiteText,
323
+ suggestBodySites
324
+ } from "ezmedicationinput";
325
+
326
+ getBodySiteCode("left ass");
327
+ // → { system: "http://snomed.info/sct", code: "723979003", display: "Structure of left buttock" }
328
+
329
+ getBodySiteText("723979003");
330
+ // → "left buttock"
331
+
332
+ getBodySiteText("22253000:363698007=723979003");
333
+ // → "left buttock"
334
+
335
+ getBodySiteCode("top of head");
336
+ // → { system: "http://snomed.info/sct", code: "69536005:106233006=261183002", display: "top of head" }
337
+
338
+ getBodySiteCode("top of head", { postcoordination: false });
339
+ // → undefined
340
+
341
+ getBodySiteText("69536005:106233006=261183002");
342
+ // → "top of head"
343
+
344
+ getBodySiteCode("right big toe");
345
+ // → { system: "http://snomed.info/sct", code: "78883009:272741003=24028007", display: "right great toe" }
346
+
347
+ getBodySiteText("78883009:272741003=24028007");
348
+ // → "right great toe"
349
+
350
+ getBodySiteText("22253000:363698007=723979003", {
351
+ parsePostcoordination: false
352
+ });
353
+ // → undefined
354
+
355
+ lookupBodySite("ระหว่างนิ้ว", { bodySiteContext: "feet" });
356
+ // → { text: "between toes", spatialRelation: { relationText: "between", ... }, ... }
357
+
358
+ suggestBodySites("หนัง", { limit: 5 });
359
+ // → [{ text: "scalp", coding: { code: "41695006", ... }, ... }]
360
+
361
+ suggestBodySiteText("นิ้วโป้ง", { limit: 5 });
362
+ // → ["thumb", "great toe", ...]
363
+
364
+ listSupportedBodySiteText({ limit: 10 });
365
+ // → ["abdomen", "affected area", ...]
366
+
367
+ listSupportedBodySiteGrammar().siteAnchors;
368
+ // → ["above", "around", "at", "beneath", "below", "between", ...]
369
+ ```
370
+
371
+ `getBodySiteCode` and `getBodySiteText` are convenience wrappers for the common
372
+ phrase-to-code and code-to-label cases. `getBodySiteCode` returns direct
373
+ pre-coordinated body-site codings when available; otherwise it can build a
374
+ SNOMED topographical-modifier expression for coded spatial phrases such as
375
+ `top of head` or `below ear`, and SNOMED laterality expressions for digit sites
376
+ such as `right big toe`. Parsed medication orders use the same behavior for
377
+ `Dosage.site.coding` by default and still preserve the structured spatial
378
+ extension; pass `bodySitePostcoordination: false` to `parseSig` when a consumer
379
+ only accepts literal body-site codes. `getBodySiteText` resolves finding-site,
380
+ topographical-modifier, and laterality postcoordination by default. Pass
381
+ `postcoordination: false` or `parsePostcoordination: false` to require literal
382
+ body-site codes only.
383
+
384
+ `lookupBodySite` returns the full resolved metadata, including spatial relation
385
+ details. `suggestBodySites` returns ranked bundled/custom candidates for
386
+ autocomplete, while `suggestBodySiteText` returns only display labels.
387
+ `listSupportedBodySiteText` exposes the bundled/custom label inventory for UI
388
+ preloading, and `listSupportedBodySiteGrammar` exposes the supported site
389
+ anchors/prepositions, locative relations, partitive heads/modifiers, and
390
+ SNOMED-coded spatial relation metadata. Lookup helpers accept `siteCodeMap`;
391
+ phrase-based helpers also accept `bodySiteContext`, used only for genuinely
392
+ ambiguous shorthand such as Thai `ระหว่างนิ้ว`.
393
+
394
+ Standalone lookup helpers can also call sync or async terminology hooks:
395
+
396
+ ```ts
397
+ getBodySiteCode("clinic site", {
398
+ siteCodeMap: {
399
+ "clinic site": {
400
+ coding: {
401
+ system: "http://example.org/sites",
402
+ code: "CLINIC-SITE",
403
+ display: "Clinic site"
404
+ },
405
+ text: "clinic site"
406
+ }
407
+ }
408
+ });
409
+
410
+ await getBodySiteCodeAsync("remote site", {
411
+ siteCodeResolvers: async (request) => {
412
+ if (request.canonical !== "remote site") return undefined;
413
+ return {
414
+ coding: {
415
+ system: "http://example.org/sites",
416
+ code: "REMOTE-SITE",
417
+ display: "Remote site"
418
+ },
419
+ text: "remote site"
420
+ };
421
+ }
422
+ });
423
+
424
+ await getBodySiteTextAsync(
425
+ { system: "http://example.org/sites", code: "REMOTE-SITE" },
426
+ {
427
+ siteTextResolvers: async (request) =>
428
+ request.originalCoding.code === "REMOTE-SITE" ? "remote site" : undefined
429
+ }
430
+ );
431
+ ```
432
+
262
433
  You can extend or replace the built-in codings via `ParseOptions`:
263
434
 
264
435
  ```ts
@@ -336,6 +507,7 @@ export interface SiteCodeLookupRequest {
336
507
  text: string; // Brace-free, whitespace-collapsed site text
337
508
  normalized: string; // Lower-case variant of `text`
338
509
  canonical: string; // Normalized key for dictionary lookups
510
+ spatialRelation?: BodySiteSpatialRelation; // Parsed relation + target, when present
339
511
  isProbe: boolean; // True when the sig used `{placeholder}` syntax
340
512
  inputText: string; // Full sig string the parser received
341
513
  sourceText?: string; // Substring extracted from `inputText`
@@ -361,6 +533,93 @@ export type SiteCodeSuggestionResolver = (
361
533
 
362
534
  Consumers that only need synchronous resolution can continue calling `parseSig`. If any synchronous resolver accidentally returns a Promise, an error is thrown with guidance to switch to `parseSigAsync`.
363
535
 
536
+ #### Standalone body-site helper resolver signatures
537
+
538
+ The standalone helper callbacks are intentionally smaller than parser callbacks
539
+ because they only resolve one phrase or one code at a time.
540
+
541
+ ```ts
542
+ export interface BodySiteLookupRequest {
543
+ originalText: string;
544
+ text: string;
545
+ normalized: string;
546
+ canonical: string;
547
+ bodySiteContext?: string;
548
+ spatialRelation?: BodySiteSpatialRelation;
549
+ }
550
+
551
+ export type BodySiteResolver = (
552
+ request: BodySiteLookupRequest
553
+ ) => BodySiteDefinition | null | undefined | Promise<BodySiteDefinition | null | undefined>;
554
+
555
+ export interface BodySiteTextLookupRequest {
556
+ coding: BodySiteCode; // decoded literal site when postcoordination is enabled
557
+ originalCoding: BodySiteCode; // original input coding/code
558
+ parsedPostcoordination?: {
559
+ type: "topographicalModifier" | "laterality" | "findingSite";
560
+ siteCode: string;
561
+ modifierCode?: string;
562
+ lateralityCode?: string;
563
+ focusCode?: string;
564
+ };
565
+ }
566
+
567
+ export type BodySiteTextResolver = (
568
+ request: BodySiteTextLookupRequest
569
+ ) => string | null | undefined | Promise<string | null | undefined>;
570
+ ```
571
+
572
+ #### SNOMED finding-site postcoordination helpers
573
+
574
+ When a PRN reason has a symptom plus site (for example `pain at abdomen`), the
575
+ library can represent the coded symptom with a SNOMED finding-site expression.
576
+ The helpers are exported for callers that need the same representation outside
577
+ the parser.
578
+
579
+ This is separate from body-site postcoordination. PRN findings use
580
+ `363698007 | Finding site |`; spatial body-site phrases use
581
+ `106233006 | Topographical modifier |`; laterality on body sites uses
582
+ `272741003 | Laterality |`.
583
+
584
+ ```ts
585
+ import {
586
+ buildSnomedBodySiteLateralityPostcoordinationCode,
587
+ buildSnomedFindingSiteCoding,
588
+ buildSnomedFindingSitePostcoordinationCode,
589
+ hasSnomedFindingSitePostcoordination
590
+ } from "ezmedicationinput";
591
+
592
+ buildSnomedBodySiteLateralityPostcoordinationCode("78883009", "24028007");
593
+ // → "78883009:272741003=24028007"
594
+
595
+ buildSnomedFindingSitePostcoordinationCode("22253000", "85562004");
596
+ // → "22253000:363698007=85562004"
597
+
598
+ hasSnomedFindingSitePostcoordination("22253000:363698007=85562004");
599
+ // → true
600
+
601
+ buildSnomedFindingSiteCoding({
602
+ focusCoding: {
603
+ system: "http://snomed.info/sct",
604
+ code: "22253000",
605
+ display: "Pain"
606
+ },
607
+ siteCoding: {
608
+ system: "http://snomed.info/sct",
609
+ code: "85562004",
610
+ display: "Hand"
611
+ },
612
+ display: "Pain at hand"
613
+ });
614
+ ```
615
+
616
+ The spatial site extension helpers are also exported:
617
+ `buildBodySiteSpatialRelationExtension`,
618
+ `buildBodySiteSpatialRelationExtensions`,
619
+ `parseBodySiteSpatialRelationExtension`,
620
+ `cloneBodySiteSpatialRelation`, and
621
+ `BODY_SITE_SPATIAL_RELATION_EXTENSION_URL`.
622
+
364
623
  You can specify the number of times (total count) the medication is supposed to be used by ending with `for {number} times`, `x {number} doses`, or simply `x {number}`
365
624
 
366
625
  ### Advanced parsing options
@@ -368,8 +627,12 @@ You can specify the number of times (total count) the medication is supposed to
368
627
  `parseSig` accepts a `ParseOptions` object. Highlights:
369
628
 
370
629
  - `context`: optional medication context (dosage form, strength, container
371
- metadata) used to infer default units when a sig omits explicit units. Pass
372
- `null` to explicitly disable context-based inference.
630
+ metadata, and optional `bodySiteContext`) used to infer defaults and
631
+ disambiguate shorthand body-site phrases. Pass `null` to explicitly disable
632
+ context-based inference.
633
+ - `context.bodySiteContext`: optional anatomical context for ambiguous site
634
+ shorthand. Example: Thai `ระหว่างนิ้ว` defaults to fingers, but resolves to
635
+ toes when `bodySiteContext` is `"feet"`, `"foot"`, or another foot/toe phrase.
373
636
  - `smartMealExpansion`: when `true`, generic AC/PC/C meal abbreviations and
374
637
  cadence-only instructions expand into concrete with-meal EventTiming
375
638
  combinations (e.g. `1x3` → breakfast/lunch/dinner). This also respects
@@ -0,0 +1,39 @@
1
+ import { BodySiteDefinition, BodySiteSpatialRelation, FhirCoding } from "./types";
2
+ export type BodySiteGrammarKind = "nominal" | "partitive" | "locative";
3
+ export type BodySiteLocativeRelation = "behind" | "around" | "under" | "above" | "below" | "beneath" | "near" | "outside" | "inside" | "between";
4
+ export interface BodySiteNominalFeatures {
5
+ kind: "nominal";
6
+ text: string;
7
+ canonical: string;
8
+ coding?: FhirCoding;
9
+ article: "definite" | "bare";
10
+ }
11
+ export interface BodySitePartitiveFeatures {
12
+ kind: "partitive";
13
+ part: string;
14
+ relationKey?: string;
15
+ whole: BodySiteNominalFeatures;
16
+ }
17
+ export interface BodySiteLocativeFeatures {
18
+ kind: "locative";
19
+ relation: BodySiteLocativeRelation;
20
+ target: BodySiteNominalFeatures | BodySitePartitiveFeatures;
21
+ }
22
+ export type BodySiteFeatureStructure = BodySiteNominalFeatures | BodySitePartitiveFeatures | BodySiteLocativeFeatures;
23
+ export interface ResolvedBodySitePhrase {
24
+ lookupCanonical: string;
25
+ resolutionCanonical: string;
26
+ canonical: string;
27
+ displayText: string;
28
+ coding?: FhirCoding;
29
+ spatialRelation?: BodySiteSpatialRelation;
30
+ definition?: BodySiteDefinition;
31
+ features: BodySiteFeatureStructure;
32
+ englishObjectText: string;
33
+ preferredPreposition?: "to" | "at" | "in" | "into";
34
+ }
35
+ export interface BodySitePhraseContext {
36
+ bodySiteContext?: string;
37
+ }
38
+ export declare function lookupBodySiteDefinition(map: Record<string, BodySiteDefinition> | undefined, canonical: string): BodySiteDefinition | undefined;
39
+ export declare function resolveBodySitePhrase(text: string, customSiteMap?: Record<string, BodySiteDefinition>, context?: BodySitePhraseContext): ResolvedBodySitePhrase | undefined;
@@ -0,0 +1,84 @@
1
+ import { BodySiteCode, BodySiteDefinition, BodySiteSpatialRelation, FhirCoding } from "./types";
2
+ export interface BodySiteLookupOptions {
3
+ siteCodeMap?: Record<string, BodySiteDefinition>;
4
+ siteCodeResolvers?: BodySiteResolver | BodySiteResolver[];
5
+ bodySiteContext?: string;
6
+ /**
7
+ * Defaults to true. When true, phrase-to-code lookup can return a
8
+ * SNOMED-coded topographical modifier expression for spatial body-site
9
+ * phrases that do not have a direct pre-coordinated body-site code.
10
+ */
11
+ postcoordination?: boolean;
12
+ limit?: number;
13
+ }
14
+ export interface BodySiteTextOptions {
15
+ siteCodeMap?: Record<string, BodySiteDefinition>;
16
+ siteTextResolvers?: BodySiteTextResolver | BodySiteTextResolver[];
17
+ system?: string;
18
+ /**
19
+ * Defaults to true. When true, SNOMED finding-site postcoordination strings
20
+ * such as "22253000:363698007=723979003" and topographical modifier
21
+ * expressions such as "69536005:106233006=261183002" are resolved.
22
+ */
23
+ postcoordination?: boolean;
24
+ parsePostcoordination?: boolean;
25
+ }
26
+ export interface BodySiteLookupResult {
27
+ text: string;
28
+ canonical: string;
29
+ lookupCanonical: string;
30
+ resolutionCanonical: string;
31
+ matchedText: string;
32
+ coding?: BodySiteCode;
33
+ spatialRelation?: BodySiteSpatialRelation;
34
+ definition?: BodySiteDefinition;
35
+ score: number;
36
+ }
37
+ export interface BodySiteLookupRequest {
38
+ originalText: string;
39
+ text: string;
40
+ normalized: string;
41
+ canonical: string;
42
+ bodySiteContext?: string;
43
+ spatialRelation?: BodySiteSpatialRelation;
44
+ }
45
+ export interface BodySiteTextLookupRequest {
46
+ coding: BodySiteCode;
47
+ originalCoding: BodySiteCode;
48
+ parsedPostcoordination?: {
49
+ type: "topographicalModifier" | "laterality" | "findingSite";
50
+ siteCode: string;
51
+ modifierCode?: string;
52
+ lateralityCode?: string;
53
+ focusCode?: string;
54
+ };
55
+ }
56
+ export type BodySiteResolver = (request: BodySiteLookupRequest) => BodySiteDefinition | null | undefined | Promise<BodySiteDefinition | null | undefined>;
57
+ export type BodySiteTextResolver = (request: BodySiteTextLookupRequest) => string | null | undefined | Promise<string | null | undefined>;
58
+ export interface BodySiteVocabularyOptions {
59
+ siteCodeMap?: Record<string, BodySiteDefinition>;
60
+ bodySiteContext?: string;
61
+ limit?: number;
62
+ }
63
+ export interface BodySiteGrammarVocabulary {
64
+ siteAnchors: string[];
65
+ siteSelfDisplayAnchors: string[];
66
+ locativeRelations: string[];
67
+ partitiveHeads: string[];
68
+ partitiveModifiers: string[];
69
+ partitiveConnectors: string[];
70
+ spatialRelationCodings: Record<string, FhirCoding>;
71
+ }
72
+ type BodySiteCodeInput = string | BodySiteCode | FhirCoding;
73
+ export declare function buildBodySiteTopographicalModifierCoding(relation: BodySiteSpatialRelation | undefined, display?: string, options?: Pick<BodySiteLookupOptions, "postcoordination">): BodySiteCode | undefined;
74
+ export declare function lookupBodySite(input: string, options?: BodySiteLookupOptions): BodySiteLookupResult | undefined;
75
+ export declare function lookupBodySiteAsync(input: string, options?: BodySiteLookupOptions): Promise<BodySiteLookupResult | undefined>;
76
+ export declare function getBodySiteCode(input: string, options?: BodySiteLookupOptions): BodySiteCode | undefined;
77
+ export declare function getBodySiteCodeAsync(input: string, options?: BodySiteLookupOptions): Promise<BodySiteCode | undefined>;
78
+ export declare function getBodySiteText(input: BodySiteCodeInput, options?: BodySiteTextOptions): string | undefined;
79
+ export declare function getBodySiteTextAsync(input: BodySiteCodeInput, options?: BodySiteTextOptions): Promise<string | undefined>;
80
+ export declare function suggestBodySites(input: string, options?: BodySiteLookupOptions): BodySiteLookupResult[];
81
+ export declare function suggestBodySiteText(input: string, options?: BodySiteLookupOptions): string[];
82
+ export declare function listSupportedBodySiteText(options?: BodySiteVocabularyOptions): string[];
83
+ export declare function listSupportedBodySiteGrammar(): BodySiteGrammarVocabulary;
84
+ export {};
@@ -0,0 +1,9 @@
1
+ import { ParserState } from "./parser-state";
2
+ import { FhirCoding } from "./types";
3
+ export interface BodySiteResolutionCandidates {
4
+ canonicals: string[];
5
+ codings: FhirCoding[];
6
+ normalizedSiteText: string;
7
+ normalizedSiteCodingDisplay: string;
8
+ }
9
+ export declare function collectParsedBodySiteCandidates(internal: ParserState): BodySiteResolutionCandidates;
@@ -0,0 +1,6 @@
1
+ import { BodySiteSpatialRelation, FhirCodeableConcept, FhirExtension } from "./types";
2
+ export declare const BODY_SITE_SPATIAL_RELATION_EXTENSION_URL = "urn:ezmedicationinput:body-site-spatial-relation";
3
+ export declare function cloneBodySiteSpatialRelation(relation: BodySiteSpatialRelation | undefined): BodySiteSpatialRelation | undefined;
4
+ export declare function buildBodySiteSpatialRelationExtension(relation: BodySiteSpatialRelation | undefined): FhirExtension | undefined;
5
+ export declare function buildBodySiteSpatialRelationExtensions(relation: BodySiteSpatialRelation | undefined): FhirExtension[] | undefined;
6
+ export declare function parseBodySiteSpatialRelationExtension(concept: FhirCodeableConcept | undefined): BodySiteSpatialRelation | undefined;
@@ -0,0 +1,18 @@
1
+ import { AdviceParseContext, ParsedAdditionalInstruction } from "./advice";
2
+ import { Token } from "./parser-state";
3
+ import { TextRange } from "./types";
4
+ export interface TailTokenSegment {
5
+ startOffset: number;
6
+ tokens: Token[];
7
+ leadingSeparatorTokens: Token[];
8
+ range: TextRange;
9
+ text: string;
10
+ }
11
+ export interface ParsedInstructionTokenSegment {
12
+ segment: TailTokenSegment;
13
+ instructions: ParsedAdditionalInstruction[];
14
+ }
15
+ export declare function splitTailTokenSegments(input: string, tokens: Token[]): TailTokenSegment[];
16
+ export declare function findStructuredInstructionTailOffset(input: string, tokens: Token[], context: AdviceParseContext): number | undefined;
17
+ export declare function hasInstructionBoundaryBeforeToken(tokens: Token[], tokenIndex: number): boolean;
18
+ export declare function parseInstructionTokenSegments(input: string, tokens: Token[], context: AdviceParseContext): ParsedInstructionTokenSegment[];
@@ -1,5 +1,8 @@
1
- import { FhirPrimitiveElement } from "./types";
1
+ import { FhirExtension, FhirPrimitiveElement } from "./types";
2
2
  export declare const FHIR_TRANSLATION_EXTENSION_URL = "http://hl7.org/fhir/StructureDefinition/translation";
3
+ export declare function cloneI18nRecord(i18n: Record<string, string> | undefined): Record<string, string> | undefined;
4
+ export declare function cloneExtension(extension: FhirExtension): FhirExtension;
5
+ export declare function cloneExtensions(extensions: FhirExtension[] | undefined): FhirExtension[] | undefined;
3
6
  export declare function clonePrimitiveElement(element: FhirPrimitiveElement | undefined): FhirPrimitiveElement | undefined;
4
7
  export declare function buildTranslationPrimitiveElement(translations: Record<string, string> | undefined, base?: FhirPrimitiveElement): FhirPrimitiveElement | undefined;
5
8
  export declare function getPrimitiveTranslation(element: FhirPrimitiveElement | undefined, locale: string | undefined): string | undefined;
package/dist/fhir.d.ts CHANGED
@@ -1,6 +1,14 @@
1
1
  import { ParserState } from "./parser-state";
2
2
  import { CanonicalSigClause, FhirDosage } from "./types";
3
- export declare function canonicalToFhir(clause: CanonicalSigClause, textOverride?: string): FhirDosage;
3
+ export interface FhirProjectionOptions {
4
+ /**
5
+ * Defaults to true. When true, structured spatial body-site phrases such as
6
+ * "top of head" can emit a SNOMED topographical modifier expression in
7
+ * Dosage.site.coding while preserving the spatial-relation extension.
8
+ */
9
+ bodySitePostcoordination?: boolean;
10
+ }
11
+ export declare function canonicalToFhir(clause: CanonicalSigClause, textOverride?: string, options?: FhirProjectionOptions): FhirDosage;
4
12
  export declare function toFhir(state: ParserState): FhirDosage;
5
13
  export declare function canonicalFromFhir(dosage: FhirDosage): CanonicalSigClause;
6
14
  export declare function parserStateFromFhir(dosage: FhirDosage): ParserState;
@@ -0,0 +1,14 @@
1
+ import { Token } from "../parser-state";
2
+ import { HpsgGrammar, HpsgSign } from "./signature";
3
+ export interface HpsgChartContext {
4
+ tokens: Token[];
5
+ }
6
+ export interface HpsgChartOptions {
7
+ limit?: number;
8
+ maxIterations?: number;
9
+ }
10
+ export interface HpsgChartParseResult {
11
+ signs: HpsgSign[];
12
+ best?: HpsgSign;
13
+ }
14
+ export declare function parseHpsgChart<TContext extends HpsgChartContext>(context: TContext, grammar: HpsgGrammar<TContext>, options?: HpsgChartOptions): HpsgChartParseResult;
@@ -0,0 +1,3 @@
1
+ import { HpsgSign } from "./signature";
2
+ import { HpsgClauseContext } from "./rule-context";
3
+ export declare function parseHpsgClause(context: HpsgClauseContext): HpsgSign | undefined;
@@ -0,0 +1,9 @@
1
+ import { ParserState } from "../parser-state";
2
+ import { ParseOptions, RouteCode } from "../types";
3
+ export interface HpsgDefaultConstraintDeps {
4
+ setRoute: (state: ParserState, code: RouteCode, text?: string) => void;
5
+ }
6
+ export declare function applyHpsgDefaultConstraints(state: ParserState, tokens: readonly {
7
+ lower: string;
8
+ index: number;
9
+ }[], options: ParseOptions | undefined, deps: HpsgDefaultConstraintDeps): void;
@@ -0,0 +1,89 @@
1
+ import { EventTiming, FhirCoding } from "../types";
2
+ type MealRelation = "before" | "after" | "with";
3
+ type MealTimingByRelation = Map<MealRelation, Map<EventTiming, EventTiming>>;
4
+ type BodySiteFeatureKind = "nominal" | "partitive" | "locative";
5
+ type CompoundDoseUnit = {
6
+ head: string;
7
+ tails: string[];
8
+ unit: string;
9
+ };
10
+ export declare const SITE_ANCHORS: Set<string>;
11
+ export declare const SITE_SELF_DISPLAY_ANCHORS: Set<string>;
12
+ export declare const SITE_FILLERS: Set<string>;
13
+ export declare const BODY_SITE_LOCATIVE_RELATIONS: Set<string>;
14
+ export declare const BODY_SITE_LOCATIVE_RENDER_PREPOSITIONS: Map<string, string>;
15
+ export declare const BODY_SITE_SPATIAL_RELATION_CODINGS: Map<string, FhirCoding>;
16
+ export declare const BODY_SITE_PARTITIVE_HEADS: Set<string>;
17
+ export declare const BODY_SITE_PARTITIVE_MODIFIERS: Set<string>;
18
+ export declare const BODY_SITE_PARTITIVE_CONNECTORS: Set<string>;
19
+ export declare const BODY_SITE_BARE_NOMINAL_PREFIXES: Set<string>;
20
+ export declare const OTIC_SITE_WORDS: Set<string>;
21
+ export declare const OPHTHALMIC_SITE_WORDS: Set<string>;
22
+ export declare const NASAL_SITE_WORDS: Set<string>;
23
+ export declare const BODY_SITE_ADJECTIVE_SUFFIXES: readonly string[];
24
+ export declare const BODY_SITE_DISPLAY_PENALTY_WORDS: Set<string>;
25
+ export declare const BODY_SITE_FEATURE_SCORE_BONUS: Map<BodySiteFeatureKind, number>;
26
+ export declare const CONNECTORS: Set<string>;
27
+ export declare const ROUTE_SITE_PREPOSITIONS: Set<string>;
28
+ export declare const SITE_DISPLAY_FILLERS: Set<string>;
29
+ export declare const NON_SITE_ANCHORED_PHRASES: Set<string>;
30
+ export declare const EXTERNAL_SITE_LOCATIVE_PREFIXES: Set<string>;
31
+ export declare const ROUTE_BLOCKED_BY_FOLLOWING_PARTITIVE_HEADS: Set<string>;
32
+ export declare const PRN_LEADS: Set<string>;
33
+ export declare const PRN_REASON_LEAD_INS: Set<string>;
34
+ export declare const PRN_STANDALONE_REASON_LEADS: Set<string>;
35
+ export declare const PRN_REASON_MULTIWORD_LEAD_INS: Set<string>;
36
+ export declare const PRN_REASON_SITE_CONNECTORS: Set<string>;
37
+ export declare const PRN_REASON_COORDINATORS: Set<string>;
38
+ export declare const PRN_CONDITIONAL_SITE_BOUNDARY_ANCHORS: Set<string>;
39
+ export declare const PRN_PREDICATE_REASON_NORMALIZATIONS: Map<string, string>;
40
+ export declare const PRN_GENERIC_LOCATED_HEADS: Map<string, string>;
41
+ export declare const PRN_DEFAULT_SITE_CONNECTOR: string;
42
+ export declare const PRN_COMPACT_REASON_SEPARATORS: Set<string>;
43
+ export declare const SITE_ROUTE_HINTS_ALLOWED_IN_GRAMMAR: Set<import("../types").SNOMEDCTRouteCodes>;
44
+ export declare const PRODUCT_METHOD_TEXT: Record<string, Partial<Record<string, string>>>;
45
+ export declare const PRODUCT_METHOD_THAI: Record<string, string>;
46
+ export declare const COMPOUND_DOSE_UNITS: CompoundDoseUnit[];
47
+ export declare const MILLION_DOSE_MULTIPLIER_TOKENS: Set<string>;
48
+ export declare const SCHEDULE_UNIT_SEPARATOR_TOKENS: Set<string>;
49
+ export declare const COMPACT_LIST_SEPARATORS: Set<string>;
50
+ export declare const EVERY_INTERVAL_TOKENS_DATA: Set<string>;
51
+ export declare const COUNT_MARKER_TOKENS_DATA: Set<string>;
52
+ export declare const COUNT_CONNECTOR_WORDS_DATA: Set<string>;
53
+ export declare const FREQUENCY_SIMPLE_WORDS_DATA: Record<string, number>;
54
+ export declare const FREQUENCY_NUMBER_WORDS_DATA: Record<string, number>;
55
+ export declare const FREQUENCY_TIMES_WORDS_DATA: Set<string>;
56
+ export declare const FREQUENCY_CONNECTOR_WORDS_DATA: Set<string>;
57
+ export declare const FREQUENCY_ADVERB_UNITS_DATA: Map<string, string>;
58
+ export declare const INTERVAL_UNIT_TOKENS_DATA: Map<string, string>;
59
+ export declare const WORKFLOW_START_WORDS: Set<string>;
60
+ export declare const WORKFLOW_NOUNS: Set<string>;
61
+ export declare const ANTE_MERIDIEM_TOKENS: Set<string>;
62
+ export declare const POST_MERIDIEM_TOKENS: Set<string>;
63
+ export declare const MERIDIEM_TOKENS: Set<string>;
64
+ export declare const LIST_SEPARATORS: Set<string>;
65
+ export declare const MEDICATION_OBJECT_FILLERS: Set<string>;
66
+ export declare const CLOCK_LEAD_TOKENS: Set<string>;
67
+ export declare const EVENT_PREPOSITIONS: Set<string>;
68
+ export declare const EVENT_ARTICLE_TOKENS: Set<string>;
69
+ export declare const FIXED_EVENT_PHRASES: Map<string, EventTiming>;
70
+ export declare const MEAL_RELATION_BY_TOKEN: Map<string, MealRelation>;
71
+ export declare const MEAL_TIMING_BY_RELATION: MealTimingByRelation;
72
+ export declare const SLEEP_EVENT_ALIASES: Set<string>;
73
+ export declare const WAKE_EVENT_ALIASES: Set<string>;
74
+ export declare const FOOD_EVENT_ALIASES: Set<string>;
75
+ export declare const DAY_RANGE_CONNECTORS: Set<string>;
76
+ export declare const RANGE_CONNECTORS: Set<string>;
77
+ export declare const DURATION_LEAD_TOKENS: Set<string>;
78
+ export declare const INSTRUCTION_LEADING_SEPARATORS: Set<string>;
79
+ export declare const INSTRUCTION_START_WORDS: Set<string>;
80
+ export declare const WORKFLOW_CONTINUATION_LICENSES: Set<string>;
81
+ export declare const AS_NEEDED_LEAD_PHRASES: Set<string>;
82
+ export declare const PRN_BREAKING_COORDINATORS: Set<string>;
83
+ export declare const EYE_SITE_ABBREVIATIONS: Set<string>;
84
+ export declare const NON_OCULAR_DOSE_UNITS: Set<string>;
85
+ export declare const OCULAR_ROUTE_CODES: Set<import("../types").SNOMEDCTRouteCodes>;
86
+ export declare const HARD_SEGMENT_BOUNDARY_TOKENS: Set<string>;
87
+ export declare const CLAUSE_LEAD_WORDS: Set<string>;
88
+ export declare const LATERAL_MODIFIER_WORDS: Set<string>;
89
+ export {};
@@ -0,0 +1,13 @@
1
+ import { FhirCoding } from "../types";
2
+ export declare enum MethodAction {
3
+ Administer = "administer",
4
+ Apply = "apply",
5
+ Insert = "insert",
6
+ Instill = "instill",
7
+ Spray = "spray",
8
+ Swallow = "swallow",
9
+ Wash = "wash"
10
+ }
11
+ export declare const METHOD_ACTION_BY_VERB: Record<string, MethodAction>;
12
+ export declare const METHOD_CODING_BY_ACTION: Record<MethodAction, FhirCoding>;
13
+ export declare function cloneMethodCoding(coding: FhirCoding | undefined): FhirCoding | undefined;
@@ -0,0 +1,12 @@
1
+ import { ParserState, Token } from "../parser-state";
2
+ import { EventTiming, FhirDayOfWeek, RouteCode } from "../types";
3
+ import { HpsgSign } from "./signature";
4
+ export interface HpsgProjectionDeps {
5
+ addDayOfWeekList: (state: ParserState, days: FhirDayOfWeek[]) => void;
6
+ addWhen: (target: EventTiming[], whenCode: EventTiming) => void;
7
+ markToken: (state: ParserState, token: Token) => void;
8
+ recordEvidence: (state: ParserState, rule: string, startIndex: number, endIndex: number) => void;
9
+ refreshMethodSurface: (state: ParserState) => void;
10
+ setRoute: (state: ParserState, code: RouteCode, text?: string) => void;
11
+ }
12
+ export declare function projectHpsgSignToState(sign: HpsgSign, state: ParserState, tokens: Token[], deps: HpsgProjectionDeps): void;