ezmedicationinput 0.1.25 → 0.1.27

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/maps.js CHANGED
@@ -663,6 +663,9 @@ exports.EVENT_TIMING_TOKENS = {
663
663
  pcv: types_1.EventTiming["After Dinner"],
664
664
  wm: types_1.EventTiming.Meal,
665
665
  "with meals": types_1.EventTiming.Meal,
666
+ "with meal": types_1.EventTiming.Meal,
667
+ "with food": types_1.EventTiming.Meal,
668
+ cc: types_1.EventTiming.Meal,
666
669
  "@m": types_1.EventTiming.Meal,
667
670
  "@meal": types_1.EventTiming.Meal,
668
671
  "@meals": types_1.EventTiming.Meal,
package/dist/parser.js CHANGED
@@ -1657,7 +1657,7 @@ function applyCountLimit(internal, value) {
1657
1657
  return true;
1658
1658
  }
1659
1659
  function parseInternal(input, options) {
1660
- var _a, _b, _c, _d, _e, _f, _g;
1660
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1661
1661
  const tokens = tokenize(input);
1662
1662
  const internal = {
1663
1663
  input,
@@ -1695,15 +1695,20 @@ function parseInternal(input, options) {
1695
1695
  if (token.lower === "prn") {
1696
1696
  internal.asNeeded = true;
1697
1697
  mark(internal.consumed, token);
1698
- prnReasonStart = i + 1;
1698
+ let reasonIndex = i + 1;
1699
+ if (((_b = tokens[reasonIndex]) === null || _b === void 0 ? void 0 : _b.lower) === "for") {
1700
+ mark(internal.consumed, tokens[reasonIndex]);
1701
+ reasonIndex += 1;
1702
+ }
1703
+ prnReasonStart = reasonIndex;
1699
1704
  break;
1700
1705
  }
1701
- if (token.lower === "as" && ((_b = tokens[i + 1]) === null || _b === void 0 ? void 0 : _b.lower) === "needed") {
1706
+ if (token.lower === "as" && ((_c = tokens[i + 1]) === null || _c === void 0 ? void 0 : _c.lower) === "needed") {
1702
1707
  internal.asNeeded = true;
1703
1708
  mark(internal.consumed, token);
1704
1709
  mark(internal.consumed, tokens[i + 1]);
1705
1710
  let reasonIndex = i + 2;
1706
- if (((_c = tokens[reasonIndex]) === null || _c === void 0 ? void 0 : _c.lower) === "for") {
1711
+ if (((_d = tokens[reasonIndex]) === null || _d === void 0 ? void 0 : _d.lower) === "for") {
1707
1712
  mark(internal.consumed, tokens[reasonIndex]);
1708
1713
  reasonIndex += 1;
1709
1714
  }
@@ -1898,7 +1903,7 @@ function parseInternal(input, options) {
1898
1903
  // Frequency abbreviation map
1899
1904
  const freqDescriptor = normalizedLower === "od"
1900
1905
  ? undefined
1901
- : (_d = maps_1.TIMING_ABBREVIATIONS[token.lower]) !== null && _d !== void 0 ? _d : maps_1.TIMING_ABBREVIATIONS[normalizedLower];
1906
+ : (_e = maps_1.TIMING_ABBREVIATIONS[token.lower]) !== null && _e !== void 0 ? _e : maps_1.TIMING_ABBREVIATIONS[normalizedLower];
1902
1907
  if (freqDescriptor) {
1903
1908
  applyFrequencyDescriptor(internal, token, freqDescriptor, options);
1904
1909
  continue;
@@ -1925,15 +1930,22 @@ function parseInternal(input, options) {
1925
1930
  }
1926
1931
  const nextToken = tokens[i + 1];
1927
1932
  if (nextToken && !internal.consumed.has(nextToken.index)) {
1928
- const combo = `${token.lower} ${nextToken.lower}`;
1929
- const comboWhen = (_e = COMBO_EVENT_TIMINGS[combo]) !== null && _e !== void 0 ? _e : maps_1.EVENT_TIMING_TOKENS[combo];
1933
+ const lowerNext = nextToken.lower;
1934
+ const combo = `${token.lower} ${lowerNext}`;
1935
+ const comboWhen = (_f = COMBO_EVENT_TIMINGS[combo]) !== null && _f !== void 0 ? _f : maps_1.EVENT_TIMING_TOKENS[combo];
1930
1936
  if (comboWhen) {
1931
1937
  applyWhenToken(internal, token, comboWhen);
1932
1938
  mark(internal.consumed, nextToken);
1933
1939
  continue;
1934
1940
  }
1941
+ // Issue 2: Support "with meal" and "with food" combos explicitly if needed
1942
+ if (token.lower === "with" && (lowerNext === "meal" || lowerNext === "food")) {
1943
+ applyWhenToken(internal, token, types_1.EventTiming.Meal);
1944
+ mark(internal.consumed, nextToken);
1945
+ continue;
1946
+ }
1935
1947
  }
1936
- const customWhen = (_f = options === null || options === void 0 ? void 0 : options.whenMap) === null || _f === void 0 ? void 0 : _f[token.lower];
1948
+ const customWhen = (_g = options === null || options === void 0 ? void 0 : options.whenMap) === null || _g === void 0 ? void 0 : _g[token.lower];
1937
1949
  if (customWhen) {
1938
1950
  applyWhenToken(internal, token, customWhen);
1939
1951
  continue;
@@ -2216,10 +2228,36 @@ function parseInternal(input, options) {
2216
2228
  const reasonTokens = [];
2217
2229
  const reasonIndices = [];
2218
2230
  const reasonObjects = [];
2231
+ const PRN_RECLAIMABLE_CONNECTORS = new Set(["at", "to", "in", "into", "on", "onto"]);
2219
2232
  for (let i = prnReasonStart; i < tokens.length; i++) {
2220
2233
  const token = tokens[i];
2221
2234
  if (internal.consumed.has(token.index)) {
2222
- internal.consumed.delete(token.index);
2235
+ // We only allow reclaiming certain generic connectors if they were used
2236
+ // as standalone markers (like 'at' or 'to') and not if they were clearly
2237
+ // part of a frequency/period instruction (which would be skipped here
2238
+ // if they were consumed by those specific logic paths).
2239
+ if (!PRN_RECLAIMABLE_CONNECTORS.has(token.lower)) {
2240
+ continue;
2241
+ }
2242
+ // If it is a reclaimable connector, we can pull it back into the reason
2243
+ // if it helps form a coherent phrase like 'irritation at rectum'.
2244
+ }
2245
+ // If we haven't started collecting the reason yet, we should skip introductory
2246
+ // connectors to avoid phrases like "as needed for if pain".
2247
+ const PRN_INTRODUCTIONS = new Set(["for", "if", "when", "upon", "due", "to"]);
2248
+ if (reasonTokens.length === 0 && PRN_INTRODUCTIONS.has(token.lower)) {
2249
+ // Special handling for "due to" - if we skipped "due", we should also skip "to"
2250
+ if (token.lower === "due") {
2251
+ const next = tokens[i + 1];
2252
+ if (next && next.lower === "to") {
2253
+ mark(internal.consumed, token);
2254
+ mark(internal.consumed, next);
2255
+ i++; // skip next token in loop
2256
+ continue;
2257
+ }
2258
+ }
2259
+ mark(internal.consumed, token);
2260
+ continue;
2223
2261
  }
2224
2262
  reasonTokens.push(token.original);
2225
2263
  reasonIndices.push(token.index);
@@ -2269,7 +2307,7 @@ function parseInternal(input, options) {
2269
2307
  let canonicalPrefix;
2270
2308
  if (reasonTokens.length > 0) {
2271
2309
  const suffixInfo = findTrailingPrnSiteSuffix(reasonObjects, internal, options);
2272
- if ((_g = suffixInfo === null || suffixInfo === void 0 ? void 0 : suffixInfo.tokens) === null || _g === void 0 ? void 0 : _g.length) {
2310
+ if ((_h = suffixInfo === null || suffixInfo === void 0 ? void 0 : suffixInfo.tokens) === null || _h === void 0 ? void 0 : _h.length) {
2273
2311
  for (const token of suffixInfo.tokens) {
2274
2312
  prnSiteSuffixIndices.add(token.index);
2275
2313
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ezmedicationinput",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "Parse concise medication sigs into FHIR R5 Dosage JSON",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",