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.
- package/README.md +265 -2
- package/dist/body-site-grammar.d.ts +39 -0
- package/dist/body-site-lookup.d.ts +84 -0
- package/dist/body-site-resolution.d.ts +9 -0
- package/dist/body-site-spatial.d.ts +6 -0
- package/dist/clause-tail-grammar.d.ts +18 -0
- package/dist/fhir-translations.d.ts +4 -1
- package/dist/fhir.d.ts +9 -1
- package/dist/hpsg/chart.d.ts +14 -0
- package/dist/hpsg/clause-parser.d.ts +3 -0
- package/dist/hpsg/defaults.d.ts +9 -0
- package/dist/hpsg/lexical-classes.d.ts +89 -0
- package/dist/hpsg/method-lexicon.d.ts +13 -0
- package/dist/hpsg/projection.d.ts +12 -0
- package/dist/hpsg/rule-context.d.ts +32 -0
- package/dist/hpsg/rules/core-rules.d.ts +8 -0
- package/dist/hpsg/rules/instruction-rules.d.ts +4 -0
- package/dist/hpsg/rules/prn-rules.d.ts +3 -0
- package/dist/hpsg/rules/product-route.d.ts +2 -0
- package/dist/hpsg/rules/site-rules.d.ts +4 -0
- package/dist/hpsg/rules/timing-rules.d.ts +12 -0
- package/dist/hpsg/segmenter.d.ts +6 -0
- package/dist/hpsg/signature.d.ts +116 -0
- package/dist/hpsg/timing-lexicon.d.ts +31 -0
- package/dist/hpsg/unification.d.ts +8 -0
- package/dist/index.cjs +14338 -12128
- package/dist/index.d.ts +5 -0
- package/dist/index.js +14299 -12128
- package/dist/maps.d.ts +4 -2
- package/dist/parser-state.d.ts +4 -1
- package/dist/parser.d.ts +3 -13
- package/dist/prn-reason-coding.d.ts +8 -0
- package/dist/site-coding.d.ts +5 -0
- package/dist/snomed-postcoordination.d.ts +25 -0
- package/dist/snomed.d.ts +13 -0
- package/dist/types.d.ts +61 -16
- package/dist/unit-lexicon.d.ts +4 -0
- package/package.json +1 -1
- 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
|
|
372
|
-
`null` to explicitly disable
|
|
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
|
|
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,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;
|