ezmedicationinput 0.1.6 → 0.1.8
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 +2 -0
- package/dist/fhir.js +17 -12
- package/dist/format.js +9 -0
- package/dist/internal-types.d.ts +1 -0
- package/dist/parser.js +248 -5
- package/dist/schedule.js +30 -16
- package/dist/suggest.js +83 -70
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -110,6 +110,8 @@ When `when` is populated, `timeOfDay` is intentionally omitted to stay within HL
|
|
|
110
110
|
|
|
111
111
|
Routes always include SNOMED CT codings. Every code from the SNOMED Route of Administration value set is represented so you can confidently pass parsed results into downstream FHIR services that expect coded routes.
|
|
112
112
|
|
|
113
|
+
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}`
|
|
114
|
+
|
|
113
115
|
### Advanced parsing options
|
|
114
116
|
|
|
115
117
|
`parseSig` accepts a `ParseOptions` object. Highlights:
|
package/dist/fhir.js
CHANGED
|
@@ -17,6 +17,10 @@ function toFhir(internal) {
|
|
|
17
17
|
repeat.frequency = internal.frequency;
|
|
18
18
|
hasRepeat = true;
|
|
19
19
|
}
|
|
20
|
+
if (internal.count !== undefined) {
|
|
21
|
+
repeat.count = internal.count;
|
|
22
|
+
hasRepeat = true;
|
|
23
|
+
}
|
|
20
24
|
if (internal.frequencyMax !== undefined) {
|
|
21
25
|
repeat.frequencyMax = internal.frequencyMax;
|
|
22
26
|
hasRepeat = true;
|
|
@@ -112,7 +116,7 @@ function toFhir(internal) {
|
|
|
112
116
|
return dosage;
|
|
113
117
|
}
|
|
114
118
|
function internalFromFhir(dosage) {
|
|
115
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
|
|
119
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5;
|
|
116
120
|
const internal = {
|
|
117
121
|
input: (_a = dosage.text) !== null && _a !== void 0 ? _a : "",
|
|
118
122
|
tokens: [],
|
|
@@ -125,18 +129,19 @@ function internalFromFhir(dosage) {
|
|
|
125
129
|
: [],
|
|
126
130
|
warnings: [],
|
|
127
131
|
timingCode: (_j = (_h = (_g = (_f = dosage.timing) === null || _f === void 0 ? void 0 : _f.code) === null || _g === void 0 ? void 0 : _g.coding) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.code,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
count: (_l = (_k = dosage.timing) === null || _k === void 0 ? void 0 : _k.repeat) === null || _l === void 0 ? void 0 : _l.count,
|
|
133
|
+
frequency: (_o = (_m = dosage.timing) === null || _m === void 0 ? void 0 : _m.repeat) === null || _o === void 0 ? void 0 : _o.frequency,
|
|
134
|
+
frequencyMax: (_q = (_p = dosage.timing) === null || _p === void 0 ? void 0 : _p.repeat) === null || _q === void 0 ? void 0 : _q.frequencyMax,
|
|
135
|
+
period: (_s = (_r = dosage.timing) === null || _r === void 0 ? void 0 : _r.repeat) === null || _s === void 0 ? void 0 : _s.period,
|
|
136
|
+
periodMax: (_u = (_t = dosage.timing) === null || _t === void 0 ? void 0 : _t.repeat) === null || _u === void 0 ? void 0 : _u.periodMax,
|
|
137
|
+
periodUnit: (_w = (_v = dosage.timing) === null || _v === void 0 ? void 0 : _v.repeat) === null || _w === void 0 ? void 0 : _w.periodUnit,
|
|
138
|
+
routeText: (_x = dosage.route) === null || _x === void 0 ? void 0 : _x.text,
|
|
139
|
+
siteText: (_y = dosage.site) === null || _y === void 0 ? void 0 : _y.text,
|
|
135
140
|
asNeeded: dosage.asNeededBoolean,
|
|
136
|
-
asNeededReason: (
|
|
141
|
+
asNeededReason: (_0 = (_z = dosage.asNeededFor) === null || _z === void 0 ? void 0 : _z[0]) === null || _0 === void 0 ? void 0 : _0.text,
|
|
137
142
|
siteTokenIndices: new Set()
|
|
138
143
|
};
|
|
139
|
-
const routeCoding = (
|
|
144
|
+
const routeCoding = (_2 = (_1 = dosage.route) === null || _1 === void 0 ? void 0 : _1.coding) === null || _2 === void 0 ? void 0 : _2.find((code) => code.system === SNOMED_SYSTEM);
|
|
140
145
|
if (routeCoding === null || routeCoding === void 0 ? void 0 : routeCoding.code) {
|
|
141
146
|
// Translate SNOMED codings back into the simplified enum for round-trip fidelity.
|
|
142
147
|
const mapped = maps_1.ROUTE_BY_SNOMED[routeCoding.code];
|
|
@@ -145,13 +150,13 @@ function internalFromFhir(dosage) {
|
|
|
145
150
|
internal.routeText = maps_1.ROUTE_TEXT[mapped];
|
|
146
151
|
}
|
|
147
152
|
}
|
|
148
|
-
const doseAndRate = (
|
|
153
|
+
const doseAndRate = (_3 = dosage.doseAndRate) === null || _3 === void 0 ? void 0 : _3[0];
|
|
149
154
|
if (doseAndRate === null || doseAndRate === void 0 ? void 0 : doseAndRate.doseRange) {
|
|
150
155
|
const { low, high } = doseAndRate.doseRange;
|
|
151
156
|
if ((low === null || low === void 0 ? void 0 : low.value) !== undefined && (high === null || high === void 0 ? void 0 : high.value) !== undefined) {
|
|
152
157
|
internal.doseRange = { low: low.value, high: high.value };
|
|
153
158
|
}
|
|
154
|
-
internal.unit = (
|
|
159
|
+
internal.unit = (_5 = (_4 = low === null || low === void 0 ? void 0 : low.unit) !== null && _4 !== void 0 ? _4 : high === null || high === void 0 ? void 0 : high.unit) !== null && _5 !== void 0 ? _5 : internal.unit;
|
|
155
160
|
}
|
|
156
161
|
else if (doseAndRate === null || doseAndRate === void 0 ? void 0 : doseAndRate.doseQuantity) {
|
|
157
162
|
const dose = doseAndRate.doseQuantity;
|
package/dist/format.js
CHANGED
|
@@ -548,6 +548,9 @@ function formatShort(internal) {
|
|
|
548
548
|
.map((d) => d.charAt(0).toUpperCase() + d.slice(1, 3))
|
|
549
549
|
.join(","));
|
|
550
550
|
}
|
|
551
|
+
if (internal.count !== undefined) {
|
|
552
|
+
parts.push(`x${stripTrailingZero(internal.count)}`);
|
|
553
|
+
}
|
|
551
554
|
if (internal.asNeeded) {
|
|
552
555
|
if (internal.asNeededReason) {
|
|
553
556
|
parts.push(`PRN ${internal.asNeededReason}`);
|
|
@@ -568,6 +571,9 @@ function formatLong(internal) {
|
|
|
568
571
|
const eventParts = collectWhenPhrases(internal);
|
|
569
572
|
const timing = combineFrequencyAndEvents(frequencyPart, eventParts);
|
|
570
573
|
const dayPart = describeDayOfWeek(internal);
|
|
574
|
+
const countPart = internal.count
|
|
575
|
+
? `for ${stripTrailingZero(internal.count)} ${internal.count === 1 ? "dose" : "doses"}`
|
|
576
|
+
: undefined;
|
|
571
577
|
const asNeededPart = internal.asNeeded
|
|
572
578
|
? internal.asNeededReason
|
|
573
579
|
? `as needed for ${internal.asNeededReason}`
|
|
@@ -586,6 +592,9 @@ function formatLong(internal) {
|
|
|
586
592
|
if (dayPart) {
|
|
587
593
|
segments.push(dayPart);
|
|
588
594
|
}
|
|
595
|
+
if (countPart) {
|
|
596
|
+
segments.push(countPart);
|
|
597
|
+
}
|
|
589
598
|
if (asNeededPart) {
|
|
590
599
|
segments.push(asNeededPart);
|
|
591
600
|
}
|
package/dist/internal-types.d.ts
CHANGED
package/dist/parser.js
CHANGED
|
@@ -111,6 +111,58 @@ const COMBO_EVENT_TIMINGS = {
|
|
|
111
111
|
"upon waking": types_1.EventTiming.Wake
|
|
112
112
|
};
|
|
113
113
|
const MEAL_CONTEXT_CONNECTORS = new Set(["and", "or", "&", "+", "plus"]);
|
|
114
|
+
const COUNT_KEYWORDS = new Set([
|
|
115
|
+
"time",
|
|
116
|
+
"times",
|
|
117
|
+
"dose",
|
|
118
|
+
"doses",
|
|
119
|
+
"application",
|
|
120
|
+
"applications",
|
|
121
|
+
"use",
|
|
122
|
+
"uses"
|
|
123
|
+
]);
|
|
124
|
+
const COUNT_CONNECTOR_WORDS = new Set([
|
|
125
|
+
"a",
|
|
126
|
+
"an",
|
|
127
|
+
"the",
|
|
128
|
+
"total",
|
|
129
|
+
"of",
|
|
130
|
+
"up",
|
|
131
|
+
"to",
|
|
132
|
+
"no",
|
|
133
|
+
"more",
|
|
134
|
+
"than",
|
|
135
|
+
"max",
|
|
136
|
+
"maximum",
|
|
137
|
+
"additional",
|
|
138
|
+
"extra"
|
|
139
|
+
]);
|
|
140
|
+
const ROUTE_DESCRIPTOR_FILLER_WORDS = new Set([
|
|
141
|
+
"per",
|
|
142
|
+
"by",
|
|
143
|
+
"via",
|
|
144
|
+
"the",
|
|
145
|
+
"a",
|
|
146
|
+
"an"
|
|
147
|
+
]);
|
|
148
|
+
function normalizeRouteDescriptorPhrase(phrase) {
|
|
149
|
+
return phrase
|
|
150
|
+
.trim()
|
|
151
|
+
.toLowerCase()
|
|
152
|
+
.split(/\s+/)
|
|
153
|
+
.filter((word) => word.length > 0 && !ROUTE_DESCRIPTOR_FILLER_WORDS.has(word))
|
|
154
|
+
.join(" ");
|
|
155
|
+
}
|
|
156
|
+
const DEFAULT_ROUTE_DESCRIPTOR_SYNONYMS = (() => {
|
|
157
|
+
const map = new Map();
|
|
158
|
+
for (const [phrase, synonym] of (0, object_1.objectEntries)(maps_1.DEFAULT_ROUTE_SYNONYMS)) {
|
|
159
|
+
const normalized = normalizeRouteDescriptorPhrase(phrase);
|
|
160
|
+
if (normalized && !map.has(normalized)) {
|
|
161
|
+
map.set(normalized, synonym);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return map;
|
|
165
|
+
})();
|
|
114
166
|
// Tracking explicit breakfast/lunch/dinner markers lets the meal-expansion
|
|
115
167
|
// logic bail early when the clinician already specified precise events.
|
|
116
168
|
const SPECIFIC_MEAL_TIMINGS = new Set([
|
|
@@ -1093,6 +1145,20 @@ function parseNumericRange(token) {
|
|
|
1093
1145
|
}
|
|
1094
1146
|
return { low, high };
|
|
1095
1147
|
}
|
|
1148
|
+
function applyCountLimit(internal, value) {
|
|
1149
|
+
if (value === undefined || !Number.isFinite(value) || value <= 0) {
|
|
1150
|
+
return false;
|
|
1151
|
+
}
|
|
1152
|
+
if (internal.count !== undefined) {
|
|
1153
|
+
return false;
|
|
1154
|
+
}
|
|
1155
|
+
const rounded = Math.round(value);
|
|
1156
|
+
if (rounded <= 0) {
|
|
1157
|
+
return false;
|
|
1158
|
+
}
|
|
1159
|
+
internal.count = rounded;
|
|
1160
|
+
return true;
|
|
1161
|
+
}
|
|
1096
1162
|
function parseInternal(input, options) {
|
|
1097
1163
|
var _a, _b, _c, _d, _e, _f;
|
|
1098
1164
|
const tokens = tokenize(input);
|
|
@@ -1112,6 +1178,11 @@ function parseInternal(input, options) {
|
|
|
1112
1178
|
value
|
|
1113
1179
|
]))
|
|
1114
1180
|
: undefined;
|
|
1181
|
+
const customRouteDescriptorMap = customRouteMap
|
|
1182
|
+
? new Map(Array.from(customRouteMap.entries())
|
|
1183
|
+
.map(([key, value]) => [normalizeRouteDescriptorPhrase(key), value])
|
|
1184
|
+
.filter(([normalized]) => normalized.length > 0))
|
|
1185
|
+
: undefined;
|
|
1115
1186
|
if (tokens.length === 0) {
|
|
1116
1187
|
return internal;
|
|
1117
1188
|
}
|
|
@@ -1155,6 +1226,50 @@ function parseInternal(input, options) {
|
|
|
1155
1226
|
mark(internal.consumed, token);
|
|
1156
1227
|
}
|
|
1157
1228
|
}
|
|
1229
|
+
const applyRouteDescriptor = (code, text) => {
|
|
1230
|
+
if (internal.routeCode && internal.routeCode !== code) {
|
|
1231
|
+
return false;
|
|
1232
|
+
}
|
|
1233
|
+
setRoute(internal, code, text);
|
|
1234
|
+
return true;
|
|
1235
|
+
};
|
|
1236
|
+
const maybeApplyRouteDescriptor = (phrase) => {
|
|
1237
|
+
if (!phrase) {
|
|
1238
|
+
return false;
|
|
1239
|
+
}
|
|
1240
|
+
const normalized = phrase.trim().toLowerCase();
|
|
1241
|
+
if (!normalized) {
|
|
1242
|
+
return false;
|
|
1243
|
+
}
|
|
1244
|
+
const customCode = customRouteMap === null || customRouteMap === void 0 ? void 0 : customRouteMap.get(normalized);
|
|
1245
|
+
if (customCode) {
|
|
1246
|
+
if (applyRouteDescriptor(customCode)) {
|
|
1247
|
+
return true;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
const synonym = maps_1.DEFAULT_ROUTE_SYNONYMS[normalized];
|
|
1251
|
+
if (synonym) {
|
|
1252
|
+
if (applyRouteDescriptor(synonym.code, synonym.text)) {
|
|
1253
|
+
return true;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
const normalizedDescriptor = normalizeRouteDescriptorPhrase(normalized);
|
|
1257
|
+
if (normalizedDescriptor && normalizedDescriptor !== normalized) {
|
|
1258
|
+
const customDescriptorCode = customRouteDescriptorMap === null || customRouteDescriptorMap === void 0 ? void 0 : customRouteDescriptorMap.get(normalizedDescriptor);
|
|
1259
|
+
if (customDescriptorCode) {
|
|
1260
|
+
if (applyRouteDescriptor(customDescriptorCode)) {
|
|
1261
|
+
return true;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
const fallbackSynonym = DEFAULT_ROUTE_DESCRIPTOR_SYNONYMS.get(normalizedDescriptor);
|
|
1265
|
+
if (fallbackSynonym) {
|
|
1266
|
+
if (applyRouteDescriptor(fallbackSynonym.code, fallbackSynonym.text)) {
|
|
1267
|
+
return true;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
return false;
|
|
1272
|
+
};
|
|
1158
1273
|
// Process tokens sequentially
|
|
1159
1274
|
const tryRouteSynonym = (startIndex) => {
|
|
1160
1275
|
const maxSpan = Math.min(24, tokens.length - startIndex);
|
|
@@ -1275,6 +1390,122 @@ function parseInternal(input, options) {
|
|
|
1275
1390
|
mark(internal.consumed, token);
|
|
1276
1391
|
continue;
|
|
1277
1392
|
}
|
|
1393
|
+
if (internal.count === undefined) {
|
|
1394
|
+
const countMatch = token.lower.match(/^[x*]([0-9]+(?:\.[0-9]+)?)$/);
|
|
1395
|
+
if (countMatch) {
|
|
1396
|
+
if (applyCountLimit(internal, parseFloat(countMatch[1]))) {
|
|
1397
|
+
mark(internal.consumed, token);
|
|
1398
|
+
const nextToken = tokens[i + 1];
|
|
1399
|
+
if (nextToken && COUNT_KEYWORDS.has(nextToken.lower)) {
|
|
1400
|
+
mark(internal.consumed, nextToken);
|
|
1401
|
+
}
|
|
1402
|
+
continue;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
if (token.lower === "x" || token.lower === "*") {
|
|
1406
|
+
const numericToken = tokens[i + 1];
|
|
1407
|
+
if (numericToken &&
|
|
1408
|
+
!internal.consumed.has(numericToken.index) &&
|
|
1409
|
+
/^[0-9]+(?:\.[0-9]+)?$/.test(numericToken.lower) &&
|
|
1410
|
+
applyCountLimit(internal, parseFloat(numericToken.original))) {
|
|
1411
|
+
mark(internal.consumed, token);
|
|
1412
|
+
mark(internal.consumed, numericToken);
|
|
1413
|
+
const afterToken = tokens[i + 2];
|
|
1414
|
+
if (afterToken && COUNT_KEYWORDS.has(afterToken.lower)) {
|
|
1415
|
+
mark(internal.consumed, afterToken);
|
|
1416
|
+
}
|
|
1417
|
+
continue;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
if (token.lower === "for") {
|
|
1421
|
+
const skipConnectors = (startIndex, bucket) => {
|
|
1422
|
+
let cursor = startIndex;
|
|
1423
|
+
while (cursor < tokens.length) {
|
|
1424
|
+
const candidate = tokens[cursor];
|
|
1425
|
+
if (!candidate) {
|
|
1426
|
+
break;
|
|
1427
|
+
}
|
|
1428
|
+
if (internal.consumed.has(candidate.index)) {
|
|
1429
|
+
cursor += 1;
|
|
1430
|
+
continue;
|
|
1431
|
+
}
|
|
1432
|
+
if (!COUNT_CONNECTOR_WORDS.has(candidate.lower)) {
|
|
1433
|
+
break;
|
|
1434
|
+
}
|
|
1435
|
+
bucket.push(candidate);
|
|
1436
|
+
cursor += 1;
|
|
1437
|
+
}
|
|
1438
|
+
return cursor;
|
|
1439
|
+
};
|
|
1440
|
+
const preConnectors = [];
|
|
1441
|
+
let lookaheadIndex = skipConnectors(i + 1, preConnectors);
|
|
1442
|
+
const numericToken = tokens[lookaheadIndex];
|
|
1443
|
+
if (numericToken &&
|
|
1444
|
+
!internal.consumed.has(numericToken.index) &&
|
|
1445
|
+
/^[0-9]+(?:\.[0-9]+)?$/.test(numericToken.lower)) {
|
|
1446
|
+
const postConnectors = [];
|
|
1447
|
+
lookaheadIndex = skipConnectors(lookaheadIndex + 1, postConnectors);
|
|
1448
|
+
const keywordToken = tokens[lookaheadIndex];
|
|
1449
|
+
if (keywordToken &&
|
|
1450
|
+
!internal.consumed.has(keywordToken.index) &&
|
|
1451
|
+
COUNT_KEYWORDS.has(keywordToken.lower) &&
|
|
1452
|
+
applyCountLimit(internal, parseFloat(numericToken.original))) {
|
|
1453
|
+
mark(internal.consumed, token);
|
|
1454
|
+
for (const connector of preConnectors) {
|
|
1455
|
+
mark(internal.consumed, connector);
|
|
1456
|
+
}
|
|
1457
|
+
mark(internal.consumed, numericToken);
|
|
1458
|
+
for (const connector of postConnectors) {
|
|
1459
|
+
mark(internal.consumed, connector);
|
|
1460
|
+
}
|
|
1461
|
+
mark(internal.consumed, keywordToken);
|
|
1462
|
+
continue;
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
if (COUNT_KEYWORDS.has(token.lower)) {
|
|
1467
|
+
const partsToMark = [token];
|
|
1468
|
+
let value;
|
|
1469
|
+
const prevToken = tokens[i - 1];
|
|
1470
|
+
if (prevToken && !internal.consumed.has(prevToken.index)) {
|
|
1471
|
+
const prevLower = prevToken.lower;
|
|
1472
|
+
const suffixMatch = prevLower.match(/^([0-9]+(?:\.[0-9]+)?)[x*]$/);
|
|
1473
|
+
const prefixMatch = prevLower.match(/^[x*]([0-9]+(?:\.[0-9]+)?)$/);
|
|
1474
|
+
if (suffixMatch) {
|
|
1475
|
+
value = parseFloat(suffixMatch[1]);
|
|
1476
|
+
partsToMark.push(prevToken);
|
|
1477
|
+
}
|
|
1478
|
+
else if (prefixMatch) {
|
|
1479
|
+
value = parseFloat(prefixMatch[1]);
|
|
1480
|
+
partsToMark.push(prevToken);
|
|
1481
|
+
}
|
|
1482
|
+
else if (/^[0-9]+(?:\.[0-9]+)?$/.test(prevLower)) {
|
|
1483
|
+
const maybeX = tokens[i - 2];
|
|
1484
|
+
if (maybeX &&
|
|
1485
|
+
!internal.consumed.has(maybeX.index) &&
|
|
1486
|
+
(maybeX.lower === "x" || maybeX.lower === "*")) {
|
|
1487
|
+
value = parseFloat(prevToken.original);
|
|
1488
|
+
partsToMark.push(maybeX, prevToken);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
if (value === undefined) {
|
|
1493
|
+
const nextToken = tokens[i + 1];
|
|
1494
|
+
if (nextToken &&
|
|
1495
|
+
!internal.consumed.has(nextToken.index) &&
|
|
1496
|
+
/^[0-9]+(?:\.[0-9]+)?$/.test(nextToken.lower)) {
|
|
1497
|
+
value = parseFloat(nextToken.original);
|
|
1498
|
+
partsToMark.push(nextToken);
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
if (applyCountLimit(internal, value)) {
|
|
1502
|
+
for (const part of partsToMark) {
|
|
1503
|
+
mark(internal.consumed, part);
|
|
1504
|
+
}
|
|
1505
|
+
continue;
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1278
1509
|
// Numeric dose
|
|
1279
1510
|
const rangeValue = parseNumericRange(token.lower);
|
|
1280
1511
|
if (rangeValue) {
|
|
@@ -1416,7 +1647,9 @@ function parseInternal(input, options) {
|
|
|
1416
1647
|
break;
|
|
1417
1648
|
}
|
|
1418
1649
|
const lower = token.lower;
|
|
1419
|
-
if (SITE_CONNECTORS.has(lower) ||
|
|
1650
|
+
if (SITE_CONNECTORS.has(lower) ||
|
|
1651
|
+
BODY_SITE_HINTS.has(lower) ||
|
|
1652
|
+
ROUTE_DESCRIPTOR_FILLER_WORDS.has(lower)) {
|
|
1420
1653
|
indicesToInclude.add(token.index);
|
|
1421
1654
|
prev -= 1;
|
|
1422
1655
|
continue;
|
|
@@ -1430,7 +1663,9 @@ function parseInternal(input, options) {
|
|
|
1430
1663
|
break;
|
|
1431
1664
|
}
|
|
1432
1665
|
const lower = token.lower;
|
|
1433
|
-
if (SITE_CONNECTORS.has(lower) ||
|
|
1666
|
+
if (SITE_CONNECTORS.has(lower) ||
|
|
1667
|
+
BODY_SITE_HINTS.has(lower) ||
|
|
1668
|
+
ROUTE_DESCRIPTOR_FILLER_WORDS.has(lower)) {
|
|
1434
1669
|
indicesToInclude.add(token.index);
|
|
1435
1670
|
next += 1;
|
|
1436
1671
|
continue;
|
|
@@ -1456,9 +1691,17 @@ function parseInternal(input, options) {
|
|
|
1456
1691
|
.join(" ")
|
|
1457
1692
|
.trim();
|
|
1458
1693
|
if (normalizedSite) {
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1694
|
+
const normalizedLower = normalizedSite.toLowerCase();
|
|
1695
|
+
const strippedDescriptor = normalizeRouteDescriptorPhrase(normalizedLower);
|
|
1696
|
+
const siteWords = normalizedLower.split(/\s+/).filter((word) => word.length > 0);
|
|
1697
|
+
const hasNonSiteWords = siteWords.some((word) => !BODY_SITE_HINTS.has(word));
|
|
1698
|
+
const shouldAttemptRouteDescriptor = strippedDescriptor !== normalizedLower || hasNonSiteWords || strippedDescriptor === "mouth";
|
|
1699
|
+
const appliedRouteDescriptor = shouldAttemptRouteDescriptor && maybeApplyRouteDescriptor(normalizedSite);
|
|
1700
|
+
if (!appliedRouteDescriptor) {
|
|
1701
|
+
internal.siteText = normalizedSite;
|
|
1702
|
+
if (!internal.siteSource) {
|
|
1703
|
+
internal.siteSource = "text";
|
|
1704
|
+
}
|
|
1462
1705
|
}
|
|
1463
1706
|
}
|
|
1464
1707
|
}
|
package/dist/schedule.js
CHANGED
|
@@ -495,6 +495,12 @@ function nextDueDoses(dosage, options) {
|
|
|
495
495
|
if (!timing || !repeat) {
|
|
496
496
|
return [];
|
|
497
497
|
}
|
|
498
|
+
const rawCount = repeat.count;
|
|
499
|
+
const normalizedCount = rawCount === undefined ? undefined : Math.max(0, Math.floor(rawCount));
|
|
500
|
+
if (normalizedCount === 0) {
|
|
501
|
+
return [];
|
|
502
|
+
}
|
|
503
|
+
const effectiveLimit = normalizedCount !== undefined ? Math.min(limit, normalizedCount) : limit;
|
|
498
504
|
const results = [];
|
|
499
505
|
const seen = new Set();
|
|
500
506
|
const dayFilter = new Set(((_g = repeat.dayOfWeek) !== null && _g !== void 0 ? _g : []).map((day) => day.toLowerCase()));
|
|
@@ -519,17 +525,22 @@ function nextDueDoses(dosage, options) {
|
|
|
519
525
|
const immediateSource = orderedAt !== null && orderedAt !== void 0 ? orderedAt : from;
|
|
520
526
|
if (!orderedAt || orderedAt >= from) {
|
|
521
527
|
const instantIso = formatZonedIso(immediateSource, timeZone);
|
|
522
|
-
|
|
523
|
-
|
|
528
|
+
if (!seen.has(instantIso)) {
|
|
529
|
+
seen.add(instantIso);
|
|
530
|
+
results.push(instantIso);
|
|
531
|
+
}
|
|
524
532
|
}
|
|
525
533
|
}
|
|
534
|
+
if (results.length >= effectiveLimit) {
|
|
535
|
+
return results.slice(0, effectiveLimit);
|
|
536
|
+
}
|
|
526
537
|
if (expanded.length === 0) {
|
|
527
|
-
return results.slice(0,
|
|
538
|
+
return results.slice(0, effectiveLimit);
|
|
528
539
|
}
|
|
529
540
|
let currentDay = startOfLocalDay(from, timeZone);
|
|
530
541
|
let iterations = 0;
|
|
531
|
-
const maxIterations =
|
|
532
|
-
while (results.length <
|
|
542
|
+
const maxIterations = effectiveLimit * 31;
|
|
543
|
+
while (results.length < effectiveLimit && iterations < maxIterations) {
|
|
533
544
|
const weekday = getLocalWeekday(currentDay, timeZone);
|
|
534
545
|
if (!enforceDayFilter || dayFilter.has(weekday)) {
|
|
535
546
|
for (const entry of expanded) {
|
|
@@ -550,16 +561,19 @@ function nextDueDoses(dosage, options) {
|
|
|
550
561
|
if (!seen.has(iso)) {
|
|
551
562
|
seen.add(iso);
|
|
552
563
|
results.push(iso);
|
|
553
|
-
if (results.length ===
|
|
564
|
+
if (results.length === effectiveLimit) {
|
|
554
565
|
break;
|
|
555
566
|
}
|
|
556
567
|
}
|
|
557
568
|
}
|
|
558
569
|
}
|
|
570
|
+
if (results.length >= effectiveLimit) {
|
|
571
|
+
break;
|
|
572
|
+
}
|
|
559
573
|
currentDay = addLocalDays(currentDay, 1, timeZone);
|
|
560
574
|
iterations += 1;
|
|
561
575
|
}
|
|
562
|
-
return results.slice(0,
|
|
576
|
+
return results.slice(0, effectiveLimit);
|
|
563
577
|
}
|
|
564
578
|
const treatAsInterval = !!repeat.period &&
|
|
565
579
|
!!repeat.periodUnit &&
|
|
@@ -569,7 +583,7 @@ function nextDueDoses(dosage, options) {
|
|
|
569
583
|
if (treatAsInterval) {
|
|
570
584
|
// True interval schedules advance from the order start in fixed units. The
|
|
571
585
|
// timing.code remains advisory so we only rely on the period/unit fields.
|
|
572
|
-
const candidates = generateIntervalSeries(baseTime, from,
|
|
586
|
+
const candidates = generateIntervalSeries(baseTime, from, effectiveLimit, repeat, timeZone, dayFilter, enforceDayFilter, orderedAt);
|
|
573
587
|
return candidates;
|
|
574
588
|
}
|
|
575
589
|
if (repeat.frequency && repeat.period && repeat.periodUnit) {
|
|
@@ -582,8 +596,8 @@ function nextDueDoses(dosage, options) {
|
|
|
582
596
|
}
|
|
583
597
|
let currentDay = startOfLocalDay(from, timeZone);
|
|
584
598
|
let iterations = 0;
|
|
585
|
-
const maxIterations =
|
|
586
|
-
while (results.length <
|
|
599
|
+
const maxIterations = effectiveLimit * 31;
|
|
600
|
+
while (results.length < effectiveLimit && iterations < maxIterations) {
|
|
587
601
|
const weekday = getLocalWeekday(currentDay, timeZone);
|
|
588
602
|
if (!enforceDayFilter || dayFilter.has(weekday)) {
|
|
589
603
|
for (const clock of clocks) {
|
|
@@ -601,7 +615,7 @@ function nextDueDoses(dosage, options) {
|
|
|
601
615
|
if (!seen.has(iso)) {
|
|
602
616
|
seen.add(iso);
|
|
603
617
|
results.push(iso);
|
|
604
|
-
if (results.length ===
|
|
618
|
+
if (results.length === effectiveLimit) {
|
|
605
619
|
break;
|
|
606
620
|
}
|
|
607
621
|
}
|
|
@@ -610,7 +624,7 @@ function nextDueDoses(dosage, options) {
|
|
|
610
624
|
currentDay = addLocalDays(currentDay, 1, timeZone);
|
|
611
625
|
iterations += 1;
|
|
612
626
|
}
|
|
613
|
-
return results.slice(0,
|
|
627
|
+
return results.slice(0, effectiveLimit);
|
|
614
628
|
}
|
|
615
629
|
return [];
|
|
616
630
|
}
|
|
@@ -618,7 +632,7 @@ function nextDueDoses(dosage, options) {
|
|
|
618
632
|
* Generates an interval-based series by stepping forward from the base time
|
|
619
633
|
* until the requested number of timestamps have been produced.
|
|
620
634
|
*/
|
|
621
|
-
function generateIntervalSeries(baseTime, from,
|
|
635
|
+
function generateIntervalSeries(baseTime, from, effectiveLimit, repeat, timeZone, dayFilter, enforceDayFilter, orderedAt) {
|
|
622
636
|
const increment = createIntervalStepper(repeat, timeZone);
|
|
623
637
|
if (!increment) {
|
|
624
638
|
return [];
|
|
@@ -627,7 +641,7 @@ function generateIntervalSeries(baseTime, from, limit, repeat, timeZone, dayFilt
|
|
|
627
641
|
const seen = new Set();
|
|
628
642
|
let current = baseTime;
|
|
629
643
|
let guard = 0;
|
|
630
|
-
const maxIterations =
|
|
644
|
+
const maxIterations = effectiveLimit * 1000;
|
|
631
645
|
while (current < from && guard < maxIterations) {
|
|
632
646
|
const next = increment(current);
|
|
633
647
|
if (!next || next.getTime() === current.getTime()) {
|
|
@@ -636,7 +650,7 @@ function generateIntervalSeries(baseTime, from, limit, repeat, timeZone, dayFilt
|
|
|
636
650
|
current = next;
|
|
637
651
|
guard += 1;
|
|
638
652
|
}
|
|
639
|
-
while (results.length <
|
|
653
|
+
while (results.length < effectiveLimit && guard < maxIterations) {
|
|
640
654
|
const weekday = getLocalWeekday(current, timeZone);
|
|
641
655
|
if (!enforceDayFilter || dayFilter.has(weekday)) {
|
|
642
656
|
if (current < from) {
|
|
@@ -671,7 +685,7 @@ function generateIntervalSeries(baseTime, from, limit, repeat, timeZone, dayFilt
|
|
|
671
685
|
current = next;
|
|
672
686
|
guard += 1;
|
|
673
687
|
}
|
|
674
|
-
return results.slice(0,
|
|
688
|
+
return results.slice(0, effectiveLimit);
|
|
675
689
|
}
|
|
676
690
|
/**
|
|
677
691
|
* Builds a function that advances a Date according to repeat.period/unit.
|
package/dist/suggest.js
CHANGED
|
@@ -105,6 +105,7 @@ const WHEN_COMBINATIONS = [
|
|
|
105
105
|
].filter((token) => maps_1.EVENT_TIMING_TOKENS[token] !== undefined);
|
|
106
106
|
const CORE_WHEN_TOKENS = ["pc", "ac", "hs"].filter((token) => maps_1.EVENT_TIMING_TOKENS[token] !== undefined);
|
|
107
107
|
const FREQUENCY_CODES = ["qd", "od", "bid", "tid", "qid"].filter((token) => maps_1.TIMING_ABBREVIATIONS[token] !== undefined);
|
|
108
|
+
const FREQUENCY_CODE_SUFFIXES = FREQUENCY_CODES.map((code) => ` ${code}`);
|
|
108
109
|
const FREQ_TOKEN_BY_NUMBER = {};
|
|
109
110
|
for (const [frequency, token] of [
|
|
110
111
|
[1, "qd"],
|
|
@@ -235,10 +236,15 @@ function removeDashes(value) {
|
|
|
235
236
|
}
|
|
236
237
|
return result.join("");
|
|
237
238
|
}
|
|
239
|
+
const UNIT_VARIANT_CACHE = new Map();
|
|
238
240
|
function getUnitVariants(unit) {
|
|
239
241
|
var _a;
|
|
240
242
|
const canonical = (_a = resolveCanonicalUnit(unit)) !== null && _a !== void 0 ? _a : normalizeSpacing(unit);
|
|
241
243
|
const normalizedCanonical = normalizeKey(canonical);
|
|
244
|
+
const cached = UNIT_VARIANT_CACHE.get(normalizedCanonical);
|
|
245
|
+
if (cached) {
|
|
246
|
+
return cached;
|
|
247
|
+
}
|
|
242
248
|
const variants = new Map();
|
|
243
249
|
const push = (candidate) => {
|
|
244
250
|
if (!candidate) {
|
|
@@ -262,7 +268,9 @@ function getUnitVariants(unit) {
|
|
|
262
268
|
push(candidate);
|
|
263
269
|
}
|
|
264
270
|
}
|
|
265
|
-
|
|
271
|
+
const result = [...variants.values()];
|
|
272
|
+
UNIT_VARIANT_CACHE.set(normalizedCanonical, result);
|
|
273
|
+
return result;
|
|
266
274
|
}
|
|
267
275
|
function buildIntervalTokens(input) {
|
|
268
276
|
const intervals = new Set();
|
|
@@ -322,6 +330,7 @@ function buildWhenSequences() {
|
|
|
322
330
|
return sequences;
|
|
323
331
|
}
|
|
324
332
|
const PRECOMPUTED_WHEN_SEQUENCES = buildWhenSequences();
|
|
333
|
+
const PRECOMPUTED_WHEN_SEQUENCE_SUFFIXES = PRECOMPUTED_WHEN_SEQUENCES.map((sequence) => ` ${sequence.join(" ")}`);
|
|
325
334
|
function tokenizeLowercaseForMatching(value) {
|
|
326
335
|
return value
|
|
327
336
|
.split(/\s+/)
|
|
@@ -481,117 +490,121 @@ function generateCandidateDirections(pairs, doseValues, prnReasons, intervalToke
|
|
|
481
490
|
suggestions.push(value);
|
|
482
491
|
return suggestions.length >= limit;
|
|
483
492
|
};
|
|
484
|
-
|
|
493
|
+
const codeSuffixes = FREQUENCY_CODE_SUFFIXES;
|
|
494
|
+
const prnSuffixes = new Array(prnReasons.length);
|
|
495
|
+
for (let i = 0; i < prnReasons.length; i += 1) {
|
|
496
|
+
prnSuffixes[i] = ` prn ${prnReasons[i]}`;
|
|
497
|
+
}
|
|
498
|
+
const intervalSuffixes = new Array(intervalTokens.length);
|
|
499
|
+
for (let i = 0; i < intervalTokens.length; i += 1) {
|
|
500
|
+
intervalSuffixes[i] = ` ${intervalTokens[i]}`;
|
|
501
|
+
}
|
|
502
|
+
const whenSuffixes = whenSequences === PRECOMPUTED_WHEN_SEQUENCES
|
|
503
|
+
? PRECOMPUTED_WHEN_SEQUENCE_SUFFIXES
|
|
504
|
+
: whenSequences.map((sequence) => ` ${sequence.join(" ")}`);
|
|
505
|
+
for (let pairIndex = 0; pairIndex < pairs.length; pairIndex += 1) {
|
|
506
|
+
const pair = pairs[pairIndex];
|
|
485
507
|
const unitVariants = getUnitVariants(pair.unit);
|
|
486
508
|
const route = pair.route;
|
|
487
509
|
const routeLower = pair.routeLower;
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
510
|
+
const unitDoseVariants = new Array(unitVariants.length);
|
|
511
|
+
for (let unitIndex = 0; unitIndex < unitVariants.length; unitIndex += 1) {
|
|
512
|
+
const unitVariant = unitVariants[unitIndex];
|
|
513
|
+
const unitRouteValue = `${unitVariant.value} ${route}`;
|
|
514
|
+
const unitRouteLower = `${unitVariant.lower} ${routeLower}`;
|
|
515
|
+
const doseBases = new Array(doseVariants.length);
|
|
516
|
+
for (let doseIndex = 0; doseIndex < doseVariants.length; doseIndex += 1) {
|
|
517
|
+
const doseVariant = doseVariants[doseIndex];
|
|
518
|
+
doseBases[doseIndex] = {
|
|
519
|
+
value: `${doseVariant.value} ${unitRouteValue}`,
|
|
520
|
+
lower: `${doseVariant.lower} ${unitRouteLower}`,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
unitDoseVariants[unitIndex] = doseBases;
|
|
524
|
+
}
|
|
525
|
+
for (let codeIndex = 0; codeIndex < codeSuffixes.length; codeIndex += 1) {
|
|
526
|
+
const codeSuffix = codeSuffixes[codeIndex];
|
|
527
|
+
for (let unitIndex = 0; unitIndex < unitDoseVariants.length; unitIndex += 1) {
|
|
528
|
+
const doseBases = unitDoseVariants[unitIndex];
|
|
529
|
+
for (let doseIndex = 0; doseIndex < doseBases.length; doseIndex += 1) {
|
|
530
|
+
const base = doseBases[doseIndex];
|
|
531
|
+
if (push(base.value + codeSuffix, base.lower + codeSuffix)) {
|
|
497
532
|
return suggestions;
|
|
498
533
|
}
|
|
499
534
|
}
|
|
500
535
|
}
|
|
501
|
-
|
|
502
|
-
const candidateLower = `${routeLower}${codeSuffix}`;
|
|
503
|
-
if (push(candidate, candidateLower)) {
|
|
536
|
+
if (push(route + codeSuffix, routeLower + codeSuffix)) {
|
|
504
537
|
return suggestions;
|
|
505
538
|
}
|
|
506
539
|
}
|
|
507
|
-
for (
|
|
508
|
-
const intervalSuffix =
|
|
509
|
-
for (
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
const
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
const intervalCandidateLower = `${baseLower}${intervalSuffix}`;
|
|
517
|
-
if (push(intervalCandidate, intervalCandidateLower)) {
|
|
540
|
+
for (let intervalIndex = 0; intervalIndex < intervalSuffixes.length; intervalIndex += 1) {
|
|
541
|
+
const intervalSuffix = intervalSuffixes[intervalIndex];
|
|
542
|
+
for (let unitIndex = 0; unitIndex < unitDoseVariants.length; unitIndex += 1) {
|
|
543
|
+
const doseBases = unitDoseVariants[unitIndex];
|
|
544
|
+
for (let doseIndex = 0; doseIndex < doseBases.length; doseIndex += 1) {
|
|
545
|
+
const base = doseBases[doseIndex];
|
|
546
|
+
const baseIntervalValue = base.value + intervalSuffix;
|
|
547
|
+
const baseIntervalLower = base.lower + intervalSuffix;
|
|
548
|
+
if (push(baseIntervalValue, baseIntervalLower)) {
|
|
518
549
|
return suggestions;
|
|
519
550
|
}
|
|
520
|
-
for (
|
|
521
|
-
const reasonSuffix =
|
|
522
|
-
|
|
523
|
-
const reasonCandidateLower = `${baseLower}${reasonSuffix}`;
|
|
524
|
-
if (push(reasonCandidate, reasonCandidateLower)) {
|
|
551
|
+
for (let reasonIndex = 0; reasonIndex < prnSuffixes.length; reasonIndex += 1) {
|
|
552
|
+
const reasonSuffix = prnSuffixes[reasonIndex];
|
|
553
|
+
if (push(baseIntervalValue + reasonSuffix, baseIntervalLower + reasonSuffix)) {
|
|
525
554
|
return suggestions;
|
|
526
555
|
}
|
|
527
556
|
}
|
|
528
557
|
}
|
|
529
558
|
}
|
|
530
|
-
|
|
531
|
-
const candidateLower = `${routeLower}${intervalSuffix}`;
|
|
532
|
-
if (push(candidate, candidateLower)) {
|
|
559
|
+
if (push(route + intervalSuffix, routeLower + intervalSuffix)) {
|
|
533
560
|
return suggestions;
|
|
534
561
|
}
|
|
535
562
|
}
|
|
536
|
-
for (
|
|
563
|
+
for (let freqIndex = 0; freqIndex < FREQUENCY_NUMBERS.length; freqIndex += 1) {
|
|
564
|
+
const freq = FREQUENCY_NUMBERS[freqIndex];
|
|
537
565
|
const freqToken = FREQ_TOKEN_BY_NUMBER[freq];
|
|
538
566
|
if (!freqToken) {
|
|
539
567
|
continue;
|
|
540
568
|
}
|
|
541
|
-
const
|
|
569
|
+
const baseValue = `1x${freq} ${route}`;
|
|
542
570
|
const baseLower = `1x${freq} ${routeLower}`;
|
|
543
|
-
|
|
544
|
-
const freqCandidateLower = `${baseLower} ${freqToken}`;
|
|
545
|
-
if (push(freqCandidate, freqCandidateLower)) {
|
|
571
|
+
if (push(`${baseValue} ${freqToken}`, `${baseLower} ${freqToken}`)) {
|
|
546
572
|
return suggestions;
|
|
547
573
|
}
|
|
548
|
-
for (
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
if (push(whenCandidate, whenCandidateLower)) {
|
|
574
|
+
for (let whenIndex = 0; whenIndex < CORE_WHEN_TOKENS.length; whenIndex += 1) {
|
|
575
|
+
const whenToken = CORE_WHEN_TOKENS[whenIndex];
|
|
576
|
+
if (push(`${baseValue} ${whenToken}`, `${baseLower} ${whenToken}`)) {
|
|
552
577
|
return suggestions;
|
|
553
578
|
}
|
|
554
579
|
}
|
|
555
580
|
}
|
|
556
|
-
for (
|
|
557
|
-
const
|
|
558
|
-
for (
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
const baseLower = `${doseVariant.lower} ${unitRouteLower}`;
|
|
564
|
-
const candidate = `${base}${suffix}`;
|
|
565
|
-
const candidateLower = `${baseLower}${suffix}`;
|
|
566
|
-
if (push(candidate, candidateLower)) {
|
|
581
|
+
for (let whenIndex = 0; whenIndex < whenSuffixes.length; whenIndex += 1) {
|
|
582
|
+
const whenSuffix = whenSuffixes[whenIndex];
|
|
583
|
+
for (let unitIndex = 0; unitIndex < unitDoseVariants.length; unitIndex += 1) {
|
|
584
|
+
const doseBases = unitDoseVariants[unitIndex];
|
|
585
|
+
for (let doseIndex = 0; doseIndex < doseBases.length; doseIndex += 1) {
|
|
586
|
+
const base = doseBases[doseIndex];
|
|
587
|
+
if (push(base.value + whenSuffix, base.lower + whenSuffix)) {
|
|
567
588
|
return suggestions;
|
|
568
589
|
}
|
|
569
590
|
}
|
|
570
591
|
}
|
|
571
|
-
|
|
572
|
-
const candidateLower = `${routeLower}${suffix}`;
|
|
573
|
-
if (push(candidate, candidateLower)) {
|
|
592
|
+
if (push(route + whenSuffix, routeLower + whenSuffix)) {
|
|
574
593
|
return suggestions;
|
|
575
594
|
}
|
|
576
595
|
}
|
|
577
|
-
for (
|
|
578
|
-
const reasonSuffix =
|
|
579
|
-
for (
|
|
580
|
-
const
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
const baseLower = `${doseVariant.lower} ${unitRouteLower}`;
|
|
585
|
-
const candidate = `${base}${reasonSuffix}`;
|
|
586
|
-
const candidateLower = `${baseLower}${reasonSuffix}`;
|
|
587
|
-
if (push(candidate, candidateLower)) {
|
|
596
|
+
for (let reasonIndex = 0; reasonIndex < prnSuffixes.length; reasonIndex += 1) {
|
|
597
|
+
const reasonSuffix = prnSuffixes[reasonIndex];
|
|
598
|
+
for (let unitIndex = 0; unitIndex < unitDoseVariants.length; unitIndex += 1) {
|
|
599
|
+
const doseBases = unitDoseVariants[unitIndex];
|
|
600
|
+
for (let doseIndex = 0; doseIndex < doseBases.length; doseIndex += 1) {
|
|
601
|
+
const base = doseBases[doseIndex];
|
|
602
|
+
if (push(base.value + reasonSuffix, base.lower + reasonSuffix)) {
|
|
588
603
|
return suggestions;
|
|
589
604
|
}
|
|
590
605
|
}
|
|
591
606
|
}
|
|
592
|
-
|
|
593
|
-
const candidateLower = `${routeLower}${reasonSuffix}`;
|
|
594
|
-
if (push(candidate, candidateLower)) {
|
|
607
|
+
if (push(route + reasonSuffix, routeLower + reasonSuffix)) {
|
|
595
608
|
return suggestions;
|
|
596
609
|
}
|
|
597
610
|
}
|
package/dist/types.d.ts
CHANGED