ezmedicationinput 0.1.40 → 0.1.42

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/dist/context.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- import { MedicationContext } from "./types";
1
+ import { MedicationContext, RouteCode } from "./types";
2
2
  export declare function normalizeDosageForm(form: string | undefined): string | undefined;
3
3
  export declare function inferUnitFromContext(ctx: MedicationContext | undefined): string | undefined;
4
+ export declare function inferRouteFromContext(ctx: MedicationContext | undefined): RouteCode | undefined;
package/dist/context.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizeDosageForm = normalizeDosageForm;
4
4
  exports.inferUnitFromContext = inferUnitFromContext;
5
+ exports.inferRouteFromContext = inferRouteFromContext;
5
6
  const maps_1 = require("./maps");
6
7
  function normalizeDosageForm(form) {
7
8
  var _a;
@@ -32,3 +33,18 @@ function inferUnitFromContext(ctx) {
32
33
  }
33
34
  return undefined;
34
35
  }
36
+ function inferRouteFromContext(ctx) {
37
+ var _a;
38
+ if (!(ctx === null || ctx === void 0 ? void 0 : ctx.dosageForm)) {
39
+ return undefined;
40
+ }
41
+ const normalized = normalizeDosageForm(ctx.dosageForm);
42
+ if (!normalized) {
43
+ return undefined;
44
+ }
45
+ const snomed = maps_1.KNOWN_TMT_DOSAGE_FORM_TO_SNOMED_ROUTE[normalized];
46
+ if (!snomed) {
47
+ return (_a = maps_1.DEFAULT_ROUTE_SYNONYMS[normalized]) === null || _a === void 0 ? void 0 : _a.code;
48
+ }
49
+ return maps_1.ROUTE_BY_SNOMED[snomed];
50
+ }
package/dist/i18n.js CHANGED
@@ -231,7 +231,6 @@ const THAI_ROUTE_GRAMMAR = {
231
231
  [types_1.RouteCode["Buccal route"]]: { verb: "อมกระพุ้งแก้ม", routePhrase: "ที่กระพุ้งแก้ม" },
232
232
  [types_1.RouteCode["Respiratory tract route (qualifier value)"]]: {
233
233
  verb: "สูด",
234
- routePhrase: ({ hasSite }) => (hasSite ? undefined : "โดยการสูดดม"),
235
234
  sitePreposition: "ที่"
236
235
  },
237
236
  [types_1.RouteCode["Nasal route"]]: {
@@ -291,12 +290,18 @@ const THAI_ROUTE_GRAMMAR = {
291
290
  }
292
291
  };
293
292
  function resolveRouteGrammarThai(internal) {
294
- var _a;
293
+ var _a, _b, _c;
295
294
  if (internal.routeCode && THAI_ROUTE_GRAMMAR[internal.routeCode]) {
296
295
  return (_a = THAI_ROUTE_GRAMMAR[internal.routeCode]) !== null && _a !== void 0 ? _a : DEFAULT_THAI_ROUTE_GRAMMAR;
297
296
  }
298
297
  const grammar = grammarFromRouteTextThai(internal.routeText);
299
- return grammar !== null && grammar !== void 0 ? grammar : DEFAULT_THAI_ROUTE_GRAMMAR;
298
+ if (grammar) {
299
+ return grammar;
300
+ }
301
+ if (((_b = internal.unit) === null || _b === void 0 ? void 0 : _b.trim().toLowerCase()) === "puff") {
302
+ return (_c = THAI_ROUTE_GRAMMAR[types_1.RouteCode["Respiratory tract route (qualifier value)"]]) !== null && _c !== void 0 ? _c : DEFAULT_THAI_ROUTE_GRAMMAR;
303
+ }
304
+ return DEFAULT_THAI_ROUTE_GRAMMAR;
300
305
  }
301
306
  function grammarFromRouteTextThai(text) {
302
307
  if (!text)
@@ -606,7 +611,7 @@ function buildRoutePhraseThai(internal, grammar, hasSite) {
606
611
  return "ทางจมูก";
607
612
  }
608
613
  if (normalized.includes("inhal")) {
609
- return "โดยการสูดดม";
614
+ return undefined;
610
615
  }
611
616
  return text;
612
617
  }
package/dist/maps.js CHANGED
@@ -548,6 +548,13 @@ function addMetricUnitSynonyms(map) {
548
548
  }
549
549
  exports.HOUSEHOLD_VOLUME_UNITS = ["tsp", "tbsp"];
550
550
  const STATIC_UNIT_SYNONYMS = {
551
+ u: "U",
552
+ unit: "U",
553
+ units: "U",
554
+ iu: "IU",
555
+ "i.u": "IU",
556
+ "i.u.": "IU",
557
+ ius: "IU",
551
558
  tab: "tab",
552
559
  tabs: "tab",
553
560
  tablet: "tab",
@@ -745,18 +752,43 @@ exports.DISCOURAGED_TOKENS = {
745
752
  exports.DAY_OF_WEEK_TOKENS = {
746
753
  monday: types_1.FhirDayOfWeek.Monday,
747
754
  mon: types_1.FhirDayOfWeek.Monday,
755
+ mond: types_1.FhirDayOfWeek.Monday,
748
756
  tuesday: types_1.FhirDayOfWeek.Tuesday,
749
757
  tue: types_1.FhirDayOfWeek.Tuesday,
758
+ tues: types_1.FhirDayOfWeek.Tuesday,
750
759
  wednesday: types_1.FhirDayOfWeek.Wednesday,
751
760
  wed: types_1.FhirDayOfWeek.Wednesday,
761
+ weds: types_1.FhirDayOfWeek.Wednesday,
752
762
  thursday: types_1.FhirDayOfWeek.Thursday,
753
763
  thu: types_1.FhirDayOfWeek.Thursday,
764
+ thur: types_1.FhirDayOfWeek.Thursday,
765
+ thurs: types_1.FhirDayOfWeek.Thursday,
754
766
  friday: types_1.FhirDayOfWeek.Friday,
755
767
  fri: types_1.FhirDayOfWeek.Friday,
756
768
  saturday: types_1.FhirDayOfWeek.Saturday,
757
769
  sat: types_1.FhirDayOfWeek.Saturday,
758
770
  sunday: types_1.FhirDayOfWeek.Sunday,
759
- sun: types_1.FhirDayOfWeek.Sunday
771
+ sun: types_1.FhirDayOfWeek.Sunday,
772
+ จ: types_1.FhirDayOfWeek.Monday,
773
+ จัน: types_1.FhirDayOfWeek.Monday,
774
+ จันทร์: types_1.FhirDayOfWeek.Monday,
775
+ อ: types_1.FhirDayOfWeek.Tuesday,
776
+ อัง: types_1.FhirDayOfWeek.Tuesday,
777
+ อังคาร: types_1.FhirDayOfWeek.Tuesday,
778
+ พ: types_1.FhirDayOfWeek.Wednesday,
779
+ พุธ: types_1.FhirDayOfWeek.Wednesday,
780
+ พฤ: types_1.FhirDayOfWeek.Thursday,
781
+ พฤหัส: types_1.FhirDayOfWeek.Thursday,
782
+ พฤหัสบดี: types_1.FhirDayOfWeek.Thursday,
783
+ ศ: types_1.FhirDayOfWeek.Friday,
784
+ ศุก: types_1.FhirDayOfWeek.Friday,
785
+ ศุกร์: types_1.FhirDayOfWeek.Friday,
786
+ ส: types_1.FhirDayOfWeek.Saturday,
787
+ เสา: types_1.FhirDayOfWeek.Saturday,
788
+ เสาร์: types_1.FhirDayOfWeek.Saturday,
789
+ อา: types_1.FhirDayOfWeek.Sunday,
790
+ อาท: types_1.FhirDayOfWeek.Sunday,
791
+ อาทิตย์: types_1.FhirDayOfWeek.Sunday
760
792
  };
761
793
  exports.WORD_FREQUENCIES = {
762
794
  daily: { frequency: 1, periodUnit: types_1.FhirPeriodUnit.Day },
package/dist/parser.js CHANGED
@@ -195,6 +195,11 @@ const COMBO_EVENT_TIMINGS = {
195
195
  "before sleep": types_1.EventTiming["Before Sleep"],
196
196
  "upon waking": types_1.EventTiming.Wake
197
197
  };
198
+ const DAY_RANGE_PART_PATTERN = Object.keys(maps_1.DAY_OF_WEEK_TOKENS)
199
+ .sort((a, b) => b.length - a.length)
200
+ .map((token) => token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
201
+ .join("|");
202
+ const DAY_RANGE_SPACED_HYPHEN_REGEX = new RegExp(`(^|\\s)(${DAY_RANGE_PART_PATTERN})\\s*-\\s*(${DAY_RANGE_PART_PATTERN})(?=\\s|$)`, "giu");
198
203
  const MEAL_CONTEXT_CONNECTORS = new Set(["and", "or", "&", "+", "plus"]);
199
204
  const COUNT_KEYWORDS = new Set([
200
205
  "time",
@@ -331,6 +336,7 @@ const EYE_SITE_TOKENS = {
331
336
  };
332
337
  const OPHTHALMIC_ROUTE_CODES = new Set([
333
338
  types_1.RouteCode["Ophthalmic route"],
339
+ types_1.RouteCode["Ocular route (qualifier value)"],
334
340
  types_1.RouteCode["Intravitreal route (qualifier value)"]
335
341
  ]);
336
342
  const OPHTHALMIC_CONTEXT_TOKENS = new Set([
@@ -533,9 +539,13 @@ function shouldTreatEyeTokenAsSite(internal, tokens, index, context) {
533
539
  const currentToken = tokens[index];
534
540
  const normalizedSelf = normalizeTokenLower(currentToken);
535
541
  const eyeMeta = EYE_SITE_TOKENS[normalizedSelf];
542
+ const contextRoute = (0, context_1.inferRouteFromContext)(context !== null && context !== void 0 ? context : undefined);
536
543
  if (internal.routeCode && !OPHTHALMIC_ROUTE_CODES.has(internal.routeCode)) {
537
544
  return false;
538
545
  }
546
+ if (contextRoute && !OPHTHALMIC_ROUTE_CODES.has(contextRoute)) {
547
+ return false;
548
+ }
539
549
  if (internal.siteText) {
540
550
  return false;
541
551
  }
@@ -543,7 +553,9 @@ function shouldTreatEyeTokenAsSite(internal, tokens, index, context) {
543
553
  return false;
544
554
  }
545
555
  const dosageForm = (_a = context === null || context === void 0 ? void 0 : context.dosageForm) === null || _a === void 0 ? void 0 : _a.toLowerCase();
546
- const contextImpliesOphthalmic = Boolean(dosageForm && /(eye|ophth|ocular|intravit)/i.test(dosageForm));
556
+ const contextImpliesOphthalmic = contextRoute
557
+ ? OPHTHALMIC_ROUTE_CODES.has(contextRoute)
558
+ : Boolean(dosageForm && /(eye|ophth|ocular|intravit)/i.test(dosageForm));
547
559
  const eyeRouteImpliesOphthalmic = (eyeMeta === null || eyeMeta === void 0 ? void 0 : eyeMeta.route) === types_1.RouteCode["Intravitreal route (qualifier value)"];
548
560
  const ophthalmicContext = hasOphthalmicContextHint(tokens, index) ||
549
561
  (internal.routeCode !== undefined && OPHTHALMIC_ROUTE_CODES.has(internal.routeCode)) ||
@@ -965,6 +977,7 @@ const SITE_UNIT_ROUTE_HINTS = [
965
977
  function tokenize(input) {
966
978
  const separators = /[(),;]/g;
967
979
  let normalized = input.trim().replace(separators, " ");
980
+ normalized = normalized.replace(DAY_RANGE_SPACED_HYPHEN_REGEX, (_match, prefix, start, end) => `${prefix}${start}-${end}`);
968
981
  normalized = normalized.replace(/\s-\s/g, " ; ");
969
982
  normalized = normalized.replace(/(\d+(?:\.\d+)?)\s*\/\s*(d|day|days|wk|w|week|weeks|mo|month|months|hr|hrs|hour|hours|h|min|mins|minute|minutes)\b/gi, (_match, value, unit) => `${value} per ${unit}`);
970
983
  normalized = normalized.replace(/(\d+)\s*\/\s*(\d+)/g, (match, num, den) => {
@@ -1585,6 +1598,154 @@ function isTimingAnchorOrPrefix(tokens, index, prnReasonStart) {
1585
1598
  (isAtPrefixToken(lower) || lower === "on" || lower === "with") ||
1586
1599
  /^\d/.test(lower));
1587
1600
  }
1601
+ const DAY_SEQUENCE = [
1602
+ types_1.FhirDayOfWeek.Monday,
1603
+ types_1.FhirDayOfWeek.Tuesday,
1604
+ types_1.FhirDayOfWeek.Wednesday,
1605
+ types_1.FhirDayOfWeek.Thursday,
1606
+ types_1.FhirDayOfWeek.Friday,
1607
+ types_1.FhirDayOfWeek.Saturday,
1608
+ types_1.FhirDayOfWeek.Sunday
1609
+ ];
1610
+ const DAY_GROUP_TOKENS = {
1611
+ weekend: [types_1.FhirDayOfWeek.Saturday, types_1.FhirDayOfWeek.Sunday],
1612
+ weekends: [types_1.FhirDayOfWeek.Saturday, types_1.FhirDayOfWeek.Sunday],
1613
+ wknd: [types_1.FhirDayOfWeek.Saturday, types_1.FhirDayOfWeek.Sunday],
1614
+ weekdays: [
1615
+ types_1.FhirDayOfWeek.Monday,
1616
+ types_1.FhirDayOfWeek.Tuesday,
1617
+ types_1.FhirDayOfWeek.Wednesday,
1618
+ types_1.FhirDayOfWeek.Thursday,
1619
+ types_1.FhirDayOfWeek.Friday
1620
+ ],
1621
+ weekday: [
1622
+ types_1.FhirDayOfWeek.Monday,
1623
+ types_1.FhirDayOfWeek.Tuesday,
1624
+ types_1.FhirDayOfWeek.Wednesday,
1625
+ types_1.FhirDayOfWeek.Thursday,
1626
+ types_1.FhirDayOfWeek.Friday
1627
+ ],
1628
+ workday: [
1629
+ types_1.FhirDayOfWeek.Monday,
1630
+ types_1.FhirDayOfWeek.Tuesday,
1631
+ types_1.FhirDayOfWeek.Wednesday,
1632
+ types_1.FhirDayOfWeek.Thursday,
1633
+ types_1.FhirDayOfWeek.Friday
1634
+ ],
1635
+ workdays: [
1636
+ types_1.FhirDayOfWeek.Monday,
1637
+ types_1.FhirDayOfWeek.Tuesday,
1638
+ types_1.FhirDayOfWeek.Wednesday,
1639
+ types_1.FhirDayOfWeek.Thursday,
1640
+ types_1.FhirDayOfWeek.Friday
1641
+ ],
1642
+ วันธรรมดา: [
1643
+ types_1.FhirDayOfWeek.Monday,
1644
+ types_1.FhirDayOfWeek.Tuesday,
1645
+ types_1.FhirDayOfWeek.Wednesday,
1646
+ types_1.FhirDayOfWeek.Thursday,
1647
+ types_1.FhirDayOfWeek.Friday
1648
+ ],
1649
+ วันทำงาน: [
1650
+ types_1.FhirDayOfWeek.Monday,
1651
+ types_1.FhirDayOfWeek.Tuesday,
1652
+ types_1.FhirDayOfWeek.Wednesday,
1653
+ types_1.FhirDayOfWeek.Thursday,
1654
+ types_1.FhirDayOfWeek.Friday
1655
+ ],
1656
+ วันหยุด: [types_1.FhirDayOfWeek.Saturday, types_1.FhirDayOfWeek.Sunday],
1657
+ สุดสัปดาห์: [types_1.FhirDayOfWeek.Saturday, types_1.FhirDayOfWeek.Sunday],
1658
+ เสาร์อาทิตย์: [types_1.FhirDayOfWeek.Saturday, types_1.FhirDayOfWeek.Sunday],
1659
+ จันทร์ถึงศุกร์: [
1660
+ types_1.FhirDayOfWeek.Monday,
1661
+ types_1.FhirDayOfWeek.Tuesday,
1662
+ types_1.FhirDayOfWeek.Wednesday,
1663
+ types_1.FhirDayOfWeek.Thursday,
1664
+ types_1.FhirDayOfWeek.Friday
1665
+ ]
1666
+ };
1667
+ const DAY_RANGE_CONNECTOR_TOKENS = new Set(["-", "to", "through", "thru", "ถึง", "จนถึง"]);
1668
+ function addDayOfWeek(internal, day) {
1669
+ if (!(0, array_1.arrayIncludes)(internal.dayOfWeek, day)) {
1670
+ internal.dayOfWeek.push(day);
1671
+ }
1672
+ }
1673
+ function addDayOfWeekList(internal, days) {
1674
+ for (const day of days) {
1675
+ addDayOfWeek(internal, day);
1676
+ }
1677
+ }
1678
+ function expandDayRange(start, end) {
1679
+ const startIndex = DAY_SEQUENCE.indexOf(start);
1680
+ const endIndex = DAY_SEQUENCE.indexOf(end);
1681
+ if (startIndex < 0 || endIndex < 0) {
1682
+ return [start, end];
1683
+ }
1684
+ if (startIndex <= endIndex) {
1685
+ return DAY_SEQUENCE.slice(startIndex, endIndex + 1);
1686
+ }
1687
+ return [...DAY_SEQUENCE.slice(startIndex), ...DAY_SEQUENCE.slice(0, endIndex + 1)];
1688
+ }
1689
+ function resolveDayTokenDays(tokenLower) {
1690
+ const normalized = tokenLower.replace(/[.,;:]/g, "");
1691
+ const direct = maps_1.DAY_OF_WEEK_TOKENS[normalized];
1692
+ if (direct) {
1693
+ return [direct];
1694
+ }
1695
+ const grouped = DAY_GROUP_TOKENS[normalized];
1696
+ if (grouped) {
1697
+ return grouped.slice();
1698
+ }
1699
+ const rangeMatch = normalized.match(/^([^-–—~]+)[-–—~]([^-–—~]+)$/);
1700
+ if (rangeMatch) {
1701
+ const start = maps_1.DAY_OF_WEEK_TOKENS[rangeMatch[1]];
1702
+ const end = maps_1.DAY_OF_WEEK_TOKENS[rangeMatch[2]];
1703
+ if (start && end) {
1704
+ return expandDayRange(start, end);
1705
+ }
1706
+ }
1707
+ const compactConnectorRange = normalized.match(/^(.+?)(ถึง|จนถึง|to|through|thru)(.+)$/u);
1708
+ if (compactConnectorRange) {
1709
+ const start = maps_1.DAY_OF_WEEK_TOKENS[compactConnectorRange[1]];
1710
+ const end = maps_1.DAY_OF_WEEK_TOKENS[compactConnectorRange[3]];
1711
+ if (start && end) {
1712
+ return expandDayRange(start, end);
1713
+ }
1714
+ }
1715
+ return undefined;
1716
+ }
1717
+ function tryConsumeDayRangeTokens(internal, tokens, index) {
1718
+ const startToken = tokens[index];
1719
+ if (!startToken || internal.consumed.has(startToken.index)) {
1720
+ return 0;
1721
+ }
1722
+ const startDays = resolveDayTokenDays(normalizeTokenLower(startToken));
1723
+ if (!startDays || startDays.length !== 1) {
1724
+ return 0;
1725
+ }
1726
+ const connectorToken = tokens[index + 1];
1727
+ const endToken = tokens[index + 2];
1728
+ if (!connectorToken ||
1729
+ !endToken ||
1730
+ internal.consumed.has(connectorToken.index) ||
1731
+ internal.consumed.has(endToken.index)) {
1732
+ return 0;
1733
+ }
1734
+ const connector = normalizeTokenLower(connectorToken);
1735
+ if (!DAY_RANGE_CONNECTOR_TOKENS.has(connector)) {
1736
+ return 0;
1737
+ }
1738
+ const endDays = resolveDayTokenDays(normalizeTokenLower(endToken));
1739
+ if (!endDays || endDays.length !== 1) {
1740
+ return 0;
1741
+ }
1742
+ const expanded = expandDayRange(startDays[0], endDays[0]);
1743
+ addDayOfWeekList(internal, expanded);
1744
+ mark(internal.consumed, startToken);
1745
+ mark(internal.consumed, connectorToken);
1746
+ mark(internal.consumed, endToken);
1747
+ return 3;
1748
+ }
1588
1749
  function parseAnchorSequence(internal, tokens, index, prefixCode) {
1589
1750
  var _a;
1590
1751
  const token = tokens[index];
@@ -1594,16 +1755,20 @@ function parseAnchorSequence(internal, tokens, index, prefixCode) {
1594
1755
  if (internal.consumed.has(nextToken.index)) {
1595
1756
  continue;
1596
1757
  }
1597
- const lower = nextToken.lower;
1758
+ const lower = normalizeTokenLower(nextToken);
1598
1759
  if (MEAL_CONTEXT_CONNECTORS.has(lower) || lower === ",") {
1599
1760
  mark(internal.consumed, nextToken);
1600
1761
  continue;
1601
1762
  }
1602
- const day = maps_1.DAY_OF_WEEK_TOKENS[lower];
1603
- if (day) {
1604
- if (!(0, array_1.arrayIncludes)(internal.dayOfWeek, day)) {
1605
- internal.dayOfWeek.push(day);
1606
- }
1763
+ const rangeConsumed = tryConsumeDayRangeTokens(internal, tokens, lookahead);
1764
+ if (rangeConsumed > 0) {
1765
+ converted++;
1766
+ lookahead += rangeConsumed - 1;
1767
+ continue;
1768
+ }
1769
+ const days = resolveDayTokenDays(lower);
1770
+ if (days) {
1771
+ addDayOfWeekList(internal, days);
1607
1772
  mark(internal.consumed, nextToken);
1608
1773
  converted++;
1609
1774
  continue;
@@ -1748,6 +1913,70 @@ function applyCountLimit(internal, value) {
1748
1913
  internal.count = rounded;
1749
1914
  return true;
1750
1915
  }
1916
+ const DOSE_SCALE_MULTIPLIERS = {
1917
+ k: 1000,
1918
+ thousand: 1000,
1919
+ m: 1000000,
1920
+ mn: 1000000,
1921
+ mio: 1000000,
1922
+ million: 1000000,
1923
+ b: 1000000000,
1924
+ bn: 1000000000,
1925
+ billion: 1000000000
1926
+ };
1927
+ function resolveUnitTokenAt(tokens, index, consumed, options) {
1928
+ const token = tokens[index];
1929
+ if (!token || consumed.has(token.index)) {
1930
+ return undefined;
1931
+ }
1932
+ const normalized = normalizeTokenLower(token);
1933
+ const direct = normalizeUnit(normalized, options);
1934
+ if (direct) {
1935
+ return { unit: direct, consumedIndices: [index] };
1936
+ }
1937
+ if (normalized === "international") {
1938
+ const nextToken = tokens[index + 1];
1939
+ if (!nextToken || consumed.has(nextToken.index)) {
1940
+ return undefined;
1941
+ }
1942
+ const nextNormalized = normalizeTokenLower(nextToken);
1943
+ if (nextNormalized === "unit" ||
1944
+ nextNormalized === "units" ||
1945
+ nextNormalized === "u" ||
1946
+ nextNormalized === "iu" ||
1947
+ nextNormalized === "ius") {
1948
+ return { unit: "IU", consumedIndices: [index, index + 1] };
1949
+ }
1950
+ }
1951
+ return undefined;
1952
+ }
1953
+ function resolveNumericDoseUnit(tokens, numberIndex, value, consumed, options) {
1954
+ const directUnit = resolveUnitTokenAt(tokens, numberIndex + 1, consumed, options);
1955
+ if (directUnit) {
1956
+ return {
1957
+ doseValue: value,
1958
+ unit: directUnit.unit,
1959
+ consumedIndices: directUnit.consumedIndices
1960
+ };
1961
+ }
1962
+ const scaleToken = tokens[numberIndex + 1];
1963
+ if (!scaleToken || consumed.has(scaleToken.index)) {
1964
+ return { doseValue: value, consumedIndices: [] };
1965
+ }
1966
+ const multiplier = DOSE_SCALE_MULTIPLIERS[normalizeTokenLower(scaleToken)];
1967
+ if (!multiplier) {
1968
+ return { doseValue: value, consumedIndices: [] };
1969
+ }
1970
+ const scaledUnit = resolveUnitTokenAt(tokens, numberIndex + 2, consumed, options);
1971
+ if (!scaledUnit) {
1972
+ return { doseValue: value, consumedIndices: [] };
1973
+ }
1974
+ return {
1975
+ doseValue: value * multiplier,
1976
+ unit: scaledUnit.unit,
1977
+ consumedIndices: [numberIndex + 1, ...scaledUnit.consumedIndices]
1978
+ };
1979
+ }
1751
1980
  function parseInternal(input, options) {
1752
1981
  var _a, _b, _c, _d, _e, _f, _g, _h;
1753
1982
  const tokens = tokenize(input);
@@ -2063,11 +2292,13 @@ function parseInternal(input, options) {
2063
2292
  }
2064
2293
  }
2065
2294
  // Day of week
2066
- const day = maps_1.DAY_OF_WEEK_TOKENS[token.lower];
2067
- if (day) {
2068
- if (!(0, array_1.arrayIncludes)(internal.dayOfWeek, day)) {
2069
- internal.dayOfWeek.push(day);
2070
- }
2295
+ const rangeConsumed = tryConsumeDayRangeTokens(internal, tokens, i);
2296
+ if (rangeConsumed > 0) {
2297
+ continue;
2298
+ }
2299
+ const days = resolveDayTokenDays(normalizeTokenLower(token));
2300
+ if (days) {
2301
+ addDayOfWeekList(internal, days);
2071
2302
  mark(internal.consumed, token);
2072
2303
  continue;
2073
2304
  }
@@ -2210,29 +2441,27 @@ function parseInternal(input, options) {
2210
2441
  internal.doseRange = rangeValue;
2211
2442
  }
2212
2443
  mark(internal.consumed, token);
2213
- const unitToken = tokens[i + 1];
2214
- if (unitToken && !internal.consumed.has(unitToken.index)) {
2215
- const unit = normalizeUnit(unitToken.lower, options);
2216
- if (unit) {
2217
- internal.unit = unit;
2218
- mark(internal.consumed, unitToken);
2444
+ const resolvedUnit = resolveUnitTokenAt(tokens, i + 1, internal.consumed, options);
2445
+ if (resolvedUnit) {
2446
+ internal.unit = resolvedUnit.unit;
2447
+ for (const consumedIndex of resolvedUnit.consumedIndices) {
2448
+ mark(internal.consumed, tokens[consumedIndex]);
2219
2449
  }
2220
2450
  }
2221
2451
  continue;
2222
2452
  }
2223
2453
  if (/^[0-9]+(?:\.[0-9]+)?$/.test(token.lower)) {
2224
2454
  const value = parseFloat(token.original);
2455
+ const resolvedDose = resolveNumericDoseUnit(tokens, i, value, internal.consumed, options);
2225
2456
  if (internal.dose === undefined) {
2226
- internal.dose = value;
2457
+ internal.dose = resolvedDose.doseValue;
2227
2458
  }
2228
2459
  mark(internal.consumed, token);
2229
- const unitToken = tokens[i + 1];
2230
- if (unitToken && !internal.consumed.has(unitToken.index)) {
2231
- const unit = normalizeUnit(unitToken.lower, options);
2232
- if (unit) {
2233
- internal.unit = unit;
2234
- mark(internal.consumed, unitToken);
2235
- }
2460
+ if (resolvedDose.unit) {
2461
+ internal.unit = resolvedDose.unit;
2462
+ }
2463
+ for (const consumedIndex of resolvedDose.consumedIndices) {
2464
+ mark(internal.consumed, tokens[consumedIndex]);
2236
2465
  }
2237
2466
  continue;
2238
2467
  }
@@ -0,0 +1,2 @@
1
+ export declare function enumEntries<T extends Record<string, string | number>>(enumeration: T): Array<[keyof T, T[keyof T]]>;
2
+ export declare function enumValues<T extends Record<string, string | number>>(enumeration: T): Array<T[keyof T]>;
@@ -0,0 +1,7 @@
1
+ import { objectEntries, objectValues } from "./object";
2
+ export function enumEntries(enumeration) {
3
+ return objectEntries(enumeration);
4
+ }
5
+ export function enumValues(enumeration) {
6
+ return objectValues(enumeration);
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ezmedicationinput",
3
- "version": "0.1.40",
3
+ "version": "0.1.42",
4
4
  "description": "Parse concise medication sigs into FHIR R5 Dosage JSON",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",