ezmedicationinput 0.1.15 → 0.1.16

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/parser.js CHANGED
@@ -11,6 +11,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.tokenize = tokenize;
13
13
  exports.parseInternal = parseInternal;
14
+ exports.applyPrnReasonCoding = applyPrnReasonCoding;
15
+ exports.applyPrnReasonCodingAsync = applyPrnReasonCodingAsync;
14
16
  exports.applySiteCoding = applySiteCoding;
15
17
  exports.applySiteCodingAsync = applySiteCodingAsync;
16
18
  const maps_1 = require("./maps");
@@ -317,7 +319,7 @@ const OPHTHALMIC_CONTEXT_TOKENS = new Set([
317
319
  "be"
318
320
  ]);
319
321
  function normalizeTokenLower(token) {
320
- return token.lower.replace(/[.{}]/g, "");
322
+ return token.lower.replace(/[.{};]/g, "");
321
323
  }
322
324
  function hasOphthalmicContextHint(tokens, index) {
323
325
  for (let offset = -3; offset <= 3; offset++) {
@@ -758,8 +760,9 @@ const SITE_UNIT_ROUTE_HINTS = [
758
760
  { pattern: /\bvaginal\b/i, route: types_1.RouteCode["Per vagina"] }
759
761
  ];
760
762
  function tokenize(input) {
761
- const separators = /[(),]/g;
763
+ const separators = /[(),;]/g;
762
764
  let normalized = input.trim().replace(separators, " ");
765
+ normalized = normalized.replace(/\s-\s/g, " ; ");
763
766
  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}`);
764
767
  normalized = normalized.replace(/(\d+)\s*\/\s*(\d+)/g, (match, num, den) => {
765
768
  const numerator = parseFloat(num);
@@ -794,7 +797,7 @@ function tokenize(input) {
794
797
  * Locates the span of the detected site tokens within the caller's original
795
798
  * input so downstream consumers can highlight or replace the exact substring.
796
799
  */
797
- function computeSiteTextRange(input, tokens, indices) {
800
+ function computeTokenRange(input, tokens, indices) {
798
801
  if (!indices.length) {
799
802
  return undefined;
800
803
  }
@@ -1421,7 +1424,9 @@ function parseInternal(input, options) {
1421
1424
  warnings: [],
1422
1425
  siteTokenIndices: new Set(),
1423
1426
  siteLookups: [],
1424
- customSiteHints: buildCustomSiteHints(options === null || options === void 0 ? void 0 : options.siteCodeMap)
1427
+ customSiteHints: buildCustomSiteHints(options === null || options === void 0 ? void 0 : options.siteCodeMap),
1428
+ prnReasonLookups: [],
1429
+ additionalInstructions: []
1425
1430
  };
1426
1431
  const context = (_a = options === null || options === void 0 ? void 0 : options.context) !== null && _a !== void 0 ? _a : undefined;
1427
1432
  const customRouteMap = (options === null || options === void 0 ? void 0 : options.routeMap)
@@ -1530,12 +1535,19 @@ function parseInternal(input, options) {
1530
1535
  if (slice.some((part) => internal.consumed.has(part.index))) {
1531
1536
  continue;
1532
1537
  }
1533
- const phrase = slice.map((part) => part.lower).join(" ");
1538
+ const normalizedParts = slice.filter((part) => !/^[;:(),]+$/.test(part.lower));
1539
+ const phrase = normalizedParts.map((part) => part.lower).join(" ");
1534
1540
  const customCode = customRouteMap === null || customRouteMap === void 0 ? void 0 : customRouteMap.get(phrase);
1535
1541
  const synonym = customCode
1536
1542
  ? { code: customCode, text: maps_1.ROUTE_TEXT[customCode] }
1537
1543
  : maps_1.DEFAULT_ROUTE_SYNONYMS[phrase];
1538
1544
  if (synonym) {
1545
+ if (phrase === "in" && slice.length === 1) {
1546
+ const prevToken = tokens[startIndex - 1];
1547
+ if (prevToken && !internal.consumed.has(prevToken.index)) {
1548
+ continue;
1549
+ }
1550
+ }
1539
1551
  setRoute(internal, synonym.code, synonym.text);
1540
1552
  for (const part of slice) {
1541
1553
  mark(internal.consumed, part);
@@ -1881,6 +1893,51 @@ function parseInternal(input, options) {
1881
1893
  // Expand generic meal markers into specific EventTiming codes when asked to.
1882
1894
  expandMealTimings(internal, options);
1883
1895
  sortWhenValues(internal, options);
1896
+ // PRN reason text
1897
+ if (internal.asNeeded && prnReasonStart !== undefined) {
1898
+ const reasonTokens = [];
1899
+ const reasonIndices = [];
1900
+ for (let i = prnReasonStart; i < tokens.length; i++) {
1901
+ const token = tokens[i];
1902
+ if (internal.consumed.has(token.index)) {
1903
+ continue;
1904
+ }
1905
+ reasonTokens.push(token.original);
1906
+ reasonIndices.push(token.index);
1907
+ mark(internal.consumed, token);
1908
+ }
1909
+ if (reasonTokens.length > 0) {
1910
+ const joined = reasonTokens.join(" ").trim();
1911
+ if (joined) {
1912
+ const sortedIndices = reasonIndices.sort((a, b) => a - b);
1913
+ const range = computeTokenRange(internal.input, tokens, sortedIndices);
1914
+ const sourceText = range ? internal.input.slice(range.start, range.end) : undefined;
1915
+ let sanitized = joined.replace(/\s+/g, " ").trim();
1916
+ let isProbe = false;
1917
+ const probeMatch = sanitized.match(/^\{(.+)}$/);
1918
+ if (probeMatch) {
1919
+ isProbe = true;
1920
+ sanitized = probeMatch[1];
1921
+ }
1922
+ sanitized = sanitized.replace(/[{}]/g, " ").replace(/\s+/g, " ").trim();
1923
+ const text = sanitized || joined;
1924
+ internal.asNeededReason = text;
1925
+ const normalized = text.toLowerCase();
1926
+ const canonical = sanitized ? (0, maps_1.normalizePrnReasonKey)(sanitized) : (0, maps_1.normalizePrnReasonKey)(text);
1927
+ internal.prnReasonLookupRequest = {
1928
+ originalText: joined,
1929
+ text,
1930
+ normalized,
1931
+ canonical: canonical !== null && canonical !== void 0 ? canonical : "",
1932
+ isProbe,
1933
+ inputText: internal.input,
1934
+ sourceText,
1935
+ range
1936
+ };
1937
+ }
1938
+ }
1939
+ }
1940
+ collectAdditionalInstructions(internal, tokens);
1884
1941
  // Determine site text from leftover tokens (excluding PRN reason tokens)
1885
1942
  const leftoverTokens = tokens.filter((t) => !internal.consumed.has(t.index));
1886
1943
  const siteCandidateIndices = new Set();
@@ -1888,6 +1945,13 @@ function parseInternal(input, options) {
1888
1945
  const normalized = normalizeTokenLower(token);
1889
1946
  if (isBodySiteHint(normalized, internal.customSiteHints)) {
1890
1947
  siteCandidateIndices.add(token.index);
1948
+ continue;
1949
+ }
1950
+ if (SITE_CONNECTORS.has(normalized)) {
1951
+ const next = tokens[token.index + 1];
1952
+ if (next && !internal.consumed.has(next.index)) {
1953
+ siteCandidateIndices.add(next.index);
1954
+ }
1891
1955
  }
1892
1956
  }
1893
1957
  for (const idx of internal.siteTokenIndices) {
@@ -1949,7 +2013,7 @@ function parseInternal(input, options) {
1949
2013
  .join(" ")
1950
2014
  .trim();
1951
2015
  if (normalizedSite) {
1952
- const tokenRange = computeSiteTextRange(internal.input, tokens, sortedIndices);
2016
+ const tokenRange = computeTokenRange(internal.input, tokens, sortedIndices);
1953
2017
  let sanitized = normalizedSite;
1954
2018
  let isProbe = false;
1955
2019
  const probeMatch = sanitized.match(/^\{(.+)}$/);
@@ -2000,21 +2064,6 @@ function parseInternal(input, options) {
2000
2064
  }
2001
2065
  }
2002
2066
  }
2003
- // PRN reason text
2004
- if (internal.asNeeded && prnReasonStart !== undefined) {
2005
- const reasonTokens = [];
2006
- for (let i = prnReasonStart; i < tokens.length; i++) {
2007
- const token = tokens[i];
2008
- if (internal.consumed.has(token.index)) {
2009
- continue;
2010
- }
2011
- reasonTokens.push(token.original);
2012
- mark(internal.consumed, token);
2013
- }
2014
- if (reasonTokens.length > 0) {
2015
- internal.asNeededReason = reasonTokens.join(" ");
2016
- }
2017
- }
2018
2067
  if (internal.routeCode === types_1.RouteCode["Intravitreal route (qualifier value)"] &&
2019
2068
  (!internal.siteText || !/eye/i.test(internal.siteText))) {
2020
2069
  internal.warnings.push("Intravitreal administrations require an eye site (e.g., OD/OS/OU).");
@@ -2025,6 +2074,14 @@ function parseInternal(input, options) {
2025
2074
  * Resolves parsed site text against SNOMED dictionaries and synchronous
2026
2075
  * callbacks, applying the best match to the in-progress parse result.
2027
2076
  */
2077
+ function applyPrnReasonCoding(internal, options) {
2078
+ runPrnReasonResolutionSync(internal, options);
2079
+ }
2080
+ function applyPrnReasonCodingAsync(internal, options) {
2081
+ return __awaiter(this, void 0, void 0, function* () {
2082
+ yield runPrnReasonResolutionAsync(internal, options);
2083
+ });
2084
+ }
2028
2085
  function applySiteCoding(internal, options) {
2029
2086
  runSiteCodingResolutionSync(internal, options);
2030
2087
  }
@@ -2240,16 +2297,21 @@ function pickSiteSelection(selections, request) {
2240
2297
  * the coding system to SNOMED CT when the definition omits one.
2241
2298
  */
2242
2299
  function applySiteDefinition(internal, definition) {
2243
- var _a;
2300
+ var _a, _b;
2244
2301
  const coding = definition.coding;
2245
- internal.siteCoding = {
2246
- code: coding.code,
2247
- display: coding.display,
2248
- system: (_a = coding.system) !== null && _a !== void 0 ? _a : SNOMED_SYSTEM
2249
- };
2302
+ internal.siteCoding = (coding === null || coding === void 0 ? void 0 : coding.code)
2303
+ ? {
2304
+ code: coding.code,
2305
+ display: coding.display,
2306
+ system: (_a = coding.system) !== null && _a !== void 0 ? _a : SNOMED_SYSTEM
2307
+ }
2308
+ : undefined;
2250
2309
  if (definition.text) {
2251
2310
  internal.siteText = definition.text;
2252
2311
  }
2312
+ else if (!internal.siteText && ((_b = internal.siteLookupRequest) === null || _b === void 0 ? void 0 : _b.text)) {
2313
+ internal.siteText = internal.siteLookupRequest.text;
2314
+ }
2253
2315
  }
2254
2316
  /**
2255
2317
  * Converts a body-site definition into a suggestion payload so all suggestion
@@ -2257,11 +2319,15 @@ function applySiteDefinition(internal, definition) {
2257
2319
  */
2258
2320
  function definitionToSuggestion(definition) {
2259
2321
  var _a;
2322
+ const coding = definition.coding;
2323
+ if (!(coding === null || coding === void 0 ? void 0 : coding.code)) {
2324
+ return undefined;
2325
+ }
2260
2326
  return {
2261
2327
  coding: {
2262
- code: definition.coding.code,
2263
- display: definition.coding.display,
2264
- system: (_a = definition.coding.system) !== null && _a !== void 0 ? _a : SNOMED_SYSTEM
2328
+ code: coding.code,
2329
+ display: coding.display,
2330
+ system: (_a = coding.system) !== null && _a !== void 0 ? _a : SNOMED_SYSTEM
2265
2331
  },
2266
2332
  text: definition.text
2267
2333
  };
@@ -2307,6 +2373,415 @@ function collectSuggestionResult(map, result) {
2307
2373
  addSuggestionToMap(map, suggestion);
2308
2374
  }
2309
2375
  }
2376
+ function findAdditionalInstructionDefinition(text, canonical) {
2377
+ if (!canonical) {
2378
+ return undefined;
2379
+ }
2380
+ for (const entry of maps_1.DEFAULT_ADDITIONAL_INSTRUCTION_ENTRIES) {
2381
+ if (!entry.canonical) {
2382
+ continue;
2383
+ }
2384
+ if (entry.canonical === canonical) {
2385
+ return entry.definition;
2386
+ }
2387
+ if (canonical.includes(entry.canonical) || entry.canonical.includes(canonical)) {
2388
+ return entry.definition;
2389
+ }
2390
+ for (const term of entry.terms) {
2391
+ const normalizedTerm = (0, maps_1.normalizeAdditionalInstructionKey)(term);
2392
+ if (!normalizedTerm) {
2393
+ continue;
2394
+ }
2395
+ if (canonical.includes(normalizedTerm) || normalizedTerm.includes(canonical)) {
2396
+ return entry.definition;
2397
+ }
2398
+ }
2399
+ }
2400
+ return undefined;
2401
+ }
2402
+ function collectAdditionalInstructions(internal, tokens) {
2403
+ var _a, _b, _c, _d, _e, _f;
2404
+ if (internal.additionalInstructions.length) {
2405
+ return;
2406
+ }
2407
+ const leftover = tokens.filter((token) => !internal.consumed.has(token.index));
2408
+ if (!leftover.length) {
2409
+ return;
2410
+ }
2411
+ const punctuationOnly = /^[;:.,-]+$/;
2412
+ const contentTokens = leftover.filter((token) => !punctuationOnly.test(token.original));
2413
+ if (!contentTokens.length) {
2414
+ return;
2415
+ }
2416
+ const leftoverIndices = leftover.map((token) => token.index).sort((a, b) => a - b);
2417
+ const contiguous = leftoverIndices.every((index, i) => i === 0 || index === leftoverIndices[i - 1] + 1);
2418
+ if (!contiguous) {
2419
+ return;
2420
+ }
2421
+ const lastIndex = leftoverIndices[leftoverIndices.length - 1];
2422
+ for (let i = lastIndex + 1; i < tokens.length; i++) {
2423
+ const trailingToken = tokens[i];
2424
+ if (!internal.consumed.has(trailingToken.index)) {
2425
+ return;
2426
+ }
2427
+ }
2428
+ const joined = contentTokens
2429
+ .map((token) => token.original)
2430
+ .join(" ")
2431
+ .replace(/\s+/g, " ")
2432
+ .trim();
2433
+ if (!joined) {
2434
+ return;
2435
+ }
2436
+ const contentIndices = contentTokens.map((token) => token.index).sort((a, b) => a - b);
2437
+ const range = computeTokenRange(internal.input, tokens, contentIndices);
2438
+ let separatorDetected = false;
2439
+ if (range) {
2440
+ for (let cursor = range.start - 1; cursor >= 0; cursor--) {
2441
+ const ch = internal.input[cursor];
2442
+ if (ch === "\n" || ch === "\r") {
2443
+ separatorDetected = true;
2444
+ break;
2445
+ }
2446
+ if (/\s/.test(ch)) {
2447
+ continue;
2448
+ }
2449
+ if (/-|;|:|\.|,/.test(ch)) {
2450
+ separatorDetected = true;
2451
+ }
2452
+ break;
2453
+ }
2454
+ }
2455
+ const sourceText = range
2456
+ ? internal.input.slice(range.start, range.end)
2457
+ : joined;
2458
+ if (!separatorDetected && !/[-;:.]/.test(sourceText)) {
2459
+ return;
2460
+ }
2461
+ const normalized = sourceText
2462
+ .replace(/\s*[-:]+\s*/g, "; ")
2463
+ .replace(/\s*(?:\r?\n)+\s*/g, "; ")
2464
+ .replace(/\s+/g, " ");
2465
+ const segments = normalized
2466
+ .split(/(?:;|\.)/)
2467
+ .map((segment) => segment.trim())
2468
+ .filter((segment) => segment.length > 0);
2469
+ const phrases = segments.length ? segments : [joined];
2470
+ const seen = new Set();
2471
+ const instructions = [];
2472
+ for (const phrase of phrases) {
2473
+ const canonical = (0, maps_1.normalizeAdditionalInstructionKey)(phrase);
2474
+ const definition = (_a = maps_1.DEFAULT_ADDITIONAL_INSTRUCTION_DEFINITIONS[canonical]) !== null && _a !== void 0 ? _a : findAdditionalInstructionDefinition(phrase, canonical);
2475
+ const key = ((_b = definition === null || definition === void 0 ? void 0 : definition.coding) === null || _b === void 0 ? void 0 : _b.code)
2476
+ ? `code:${(_c = definition.coding.system) !== null && _c !== void 0 ? _c : SNOMED_SYSTEM}|${definition.coding.code}`
2477
+ : canonical
2478
+ ? `text:${canonical}`
2479
+ : phrase.toLowerCase();
2480
+ if (key && seen.has(key)) {
2481
+ continue;
2482
+ }
2483
+ seen.add(key);
2484
+ if (definition) {
2485
+ instructions.push({
2486
+ text: (_d = definition.text) !== null && _d !== void 0 ? _d : phrase,
2487
+ coding: ((_e = definition.coding) === null || _e === void 0 ? void 0 : _e.code)
2488
+ ? {
2489
+ code: definition.coding.code,
2490
+ display: definition.coding.display,
2491
+ system: (_f = definition.coding.system) !== null && _f !== void 0 ? _f : SNOMED_SYSTEM
2492
+ }
2493
+ : undefined
2494
+ });
2495
+ }
2496
+ else {
2497
+ instructions.push({ text: phrase });
2498
+ }
2499
+ }
2500
+ if (instructions.length) {
2501
+ internal.additionalInstructions = instructions;
2502
+ for (const token of leftover) {
2503
+ mark(internal.consumed, token);
2504
+ }
2505
+ }
2506
+ }
2507
+ function lookupPrnReasonDefinition(map, canonical) {
2508
+ if (!map) {
2509
+ return undefined;
2510
+ }
2511
+ const direct = map[canonical];
2512
+ if (direct) {
2513
+ return direct;
2514
+ }
2515
+ for (const [key, definition] of (0, object_1.objectEntries)(map)) {
2516
+ if ((0, maps_1.normalizePrnReasonKey)(key) === canonical) {
2517
+ return definition;
2518
+ }
2519
+ if (definition.aliases) {
2520
+ for (const alias of definition.aliases) {
2521
+ if ((0, maps_1.normalizePrnReasonKey)(alias) === canonical) {
2522
+ return definition;
2523
+ }
2524
+ }
2525
+ }
2526
+ }
2527
+ return undefined;
2528
+ }
2529
+ function pickPrnReasonSelection(selections, request) {
2530
+ if (!selections) {
2531
+ return undefined;
2532
+ }
2533
+ const canonical = request.canonical;
2534
+ const normalizedText = (0, maps_1.normalizePrnReasonKey)(request.text);
2535
+ const requestRange = request.range;
2536
+ for (const selection of toArray(selections)) {
2537
+ if (!selection) {
2538
+ continue;
2539
+ }
2540
+ let matched = false;
2541
+ if (selection.range) {
2542
+ if (!requestRange) {
2543
+ continue;
2544
+ }
2545
+ if (selection.range.start !== requestRange.start ||
2546
+ selection.range.end !== requestRange.end) {
2547
+ continue;
2548
+ }
2549
+ matched = true;
2550
+ }
2551
+ if (selection.canonical) {
2552
+ if ((0, maps_1.normalizePrnReasonKey)(selection.canonical) !== canonical) {
2553
+ continue;
2554
+ }
2555
+ matched = true;
2556
+ }
2557
+ else if (selection.text) {
2558
+ const normalizedSelection = (0, maps_1.normalizePrnReasonKey)(selection.text);
2559
+ if (normalizedSelection !== canonical && normalizedSelection !== normalizedText) {
2560
+ continue;
2561
+ }
2562
+ matched = true;
2563
+ }
2564
+ if (!selection.range && !selection.canonical && !selection.text) {
2565
+ continue;
2566
+ }
2567
+ if (matched) {
2568
+ return selection.resolution;
2569
+ }
2570
+ }
2571
+ return undefined;
2572
+ }
2573
+ function applyPrnReasonDefinition(internal, definition) {
2574
+ var _a;
2575
+ const coding = definition.coding;
2576
+ internal.asNeededReasonCoding = (coding === null || coding === void 0 ? void 0 : coding.code)
2577
+ ? {
2578
+ code: coding.code,
2579
+ display: coding.display,
2580
+ system: (_a = coding.system) !== null && _a !== void 0 ? _a : SNOMED_SYSTEM
2581
+ }
2582
+ : undefined;
2583
+ if (definition.text && !internal.asNeededReason) {
2584
+ internal.asNeededReason = definition.text;
2585
+ }
2586
+ }
2587
+ function definitionToPrnSuggestion(definition) {
2588
+ var _a, _b, _c, _d;
2589
+ return {
2590
+ coding: ((_a = definition.coding) === null || _a === void 0 ? void 0 : _a.code)
2591
+ ? {
2592
+ code: definition.coding.code,
2593
+ display: definition.coding.display,
2594
+ system: (_b = definition.coding.system) !== null && _b !== void 0 ? _b : SNOMED_SYSTEM
2595
+ }
2596
+ : undefined,
2597
+ text: (_c = definition.text) !== null && _c !== void 0 ? _c : (_d = definition.coding) === null || _d === void 0 ? void 0 : _d.display
2598
+ };
2599
+ }
2600
+ function addReasonSuggestionToMap(map, suggestion) {
2601
+ var _a;
2602
+ if (!suggestion) {
2603
+ return;
2604
+ }
2605
+ const coding = suggestion.coding;
2606
+ const key = (coding === null || coding === void 0 ? void 0 : coding.code)
2607
+ ? `${(_a = coding.system) !== null && _a !== void 0 ? _a : SNOMED_SYSTEM}|${coding.code}`
2608
+ : suggestion.text
2609
+ ? `text:${suggestion.text.toLowerCase()}`
2610
+ : undefined;
2611
+ if (!key || map.has(key)) {
2612
+ return;
2613
+ }
2614
+ map.set(key, suggestion);
2615
+ }
2616
+ function collectReasonSuggestionResult(map, result) {
2617
+ if (!result) {
2618
+ return;
2619
+ }
2620
+ const suggestions = Array.isArray(result)
2621
+ ? result
2622
+ : typeof result === "object" && "suggestions" in result
2623
+ ? result.suggestions
2624
+ : [result];
2625
+ for (const suggestion of suggestions) {
2626
+ addReasonSuggestionToMap(map, suggestion);
2627
+ }
2628
+ }
2629
+ function collectDefaultPrnReasonDefinitions(request) {
2630
+ const canonical = request.canonical;
2631
+ const normalized = request.normalized;
2632
+ const seen = new Set();
2633
+ for (const entry of maps_1.DEFAULT_PRN_REASON_ENTRIES) {
2634
+ if (!entry.canonical) {
2635
+ continue;
2636
+ }
2637
+ if (entry.canonical === canonical) {
2638
+ seen.add(entry.definition);
2639
+ continue;
2640
+ }
2641
+ if (canonical && (entry.canonical.includes(canonical) || canonical.includes(entry.canonical))) {
2642
+ seen.add(entry.definition);
2643
+ continue;
2644
+ }
2645
+ for (const term of entry.terms) {
2646
+ const normalizedTerm = (0, maps_1.normalizePrnReasonKey)(term);
2647
+ if (!normalizedTerm) {
2648
+ continue;
2649
+ }
2650
+ if (canonical && canonical.includes(normalizedTerm)) {
2651
+ seen.add(entry.definition);
2652
+ break;
2653
+ }
2654
+ if (normalized.includes(normalizedTerm)) {
2655
+ seen.add(entry.definition);
2656
+ break;
2657
+ }
2658
+ }
2659
+ }
2660
+ if (!seen.size) {
2661
+ for (const entry of maps_1.DEFAULT_PRN_REASON_ENTRIES) {
2662
+ seen.add(entry.definition);
2663
+ }
2664
+ }
2665
+ return Array.from(seen);
2666
+ }
2667
+ function runPrnReasonResolutionSync(internal, options) {
2668
+ internal.prnReasonLookups = [];
2669
+ const request = internal.prnReasonLookupRequest;
2670
+ if (!request) {
2671
+ return;
2672
+ }
2673
+ const canonical = request.canonical;
2674
+ const selection = pickPrnReasonSelection(options === null || options === void 0 ? void 0 : options.prnReasonSelections, request);
2675
+ const customDefinition = lookupPrnReasonDefinition(options === null || options === void 0 ? void 0 : options.prnReasonMap, canonical);
2676
+ let resolution = selection !== null && selection !== void 0 ? selection : customDefinition;
2677
+ if (!resolution) {
2678
+ for (const resolver of toArray(options === null || options === void 0 ? void 0 : options.prnReasonResolvers)) {
2679
+ const result = resolver(request);
2680
+ if (isPromise(result)) {
2681
+ throw new Error("PRN reason resolver returned a Promise; use parseSigAsync for asynchronous PRN reason resolution.");
2682
+ }
2683
+ if (result) {
2684
+ resolution = result;
2685
+ break;
2686
+ }
2687
+ }
2688
+ }
2689
+ const defaultDefinition = canonical ? maps_1.DEFAULT_PRN_REASON_DEFINITIONS[canonical] : undefined;
2690
+ if (!resolution && defaultDefinition) {
2691
+ resolution = defaultDefinition;
2692
+ }
2693
+ if (resolution) {
2694
+ applyPrnReasonDefinition(internal, resolution);
2695
+ }
2696
+ else {
2697
+ internal.asNeededReasonCoding = undefined;
2698
+ }
2699
+ const needsSuggestions = request.isProbe || !resolution;
2700
+ if (!needsSuggestions) {
2701
+ return;
2702
+ }
2703
+ const suggestionMap = new Map();
2704
+ if (selection) {
2705
+ addReasonSuggestionToMap(suggestionMap, definitionToPrnSuggestion(selection));
2706
+ }
2707
+ if (customDefinition) {
2708
+ addReasonSuggestionToMap(suggestionMap, definitionToPrnSuggestion(customDefinition));
2709
+ }
2710
+ if (defaultDefinition) {
2711
+ addReasonSuggestionToMap(suggestionMap, definitionToPrnSuggestion(defaultDefinition));
2712
+ }
2713
+ for (const definition of collectDefaultPrnReasonDefinitions(request)) {
2714
+ addReasonSuggestionToMap(suggestionMap, definitionToPrnSuggestion(definition));
2715
+ }
2716
+ for (const resolver of toArray(options === null || options === void 0 ? void 0 : options.prnReasonSuggestionResolvers)) {
2717
+ const result = resolver(request);
2718
+ if (isPromise(result)) {
2719
+ throw new Error("PRN reason suggestion resolver returned a Promise; use parseSigAsync for asynchronous PRN reason suggestions.");
2720
+ }
2721
+ collectReasonSuggestionResult(suggestionMap, result);
2722
+ }
2723
+ const suggestions = Array.from(suggestionMap.values());
2724
+ if (suggestions.length || request.isProbe) {
2725
+ internal.prnReasonLookups.push({ request, suggestions });
2726
+ }
2727
+ }
2728
+ function runPrnReasonResolutionAsync(internal, options) {
2729
+ return __awaiter(this, void 0, void 0, function* () {
2730
+ internal.prnReasonLookups = [];
2731
+ const request = internal.prnReasonLookupRequest;
2732
+ if (!request) {
2733
+ return;
2734
+ }
2735
+ const canonical = request.canonical;
2736
+ const selection = pickPrnReasonSelection(options === null || options === void 0 ? void 0 : options.prnReasonSelections, request);
2737
+ const customDefinition = lookupPrnReasonDefinition(options === null || options === void 0 ? void 0 : options.prnReasonMap, canonical);
2738
+ let resolution = selection !== null && selection !== void 0 ? selection : customDefinition;
2739
+ if (!resolution) {
2740
+ for (const resolver of toArray(options === null || options === void 0 ? void 0 : options.prnReasonResolvers)) {
2741
+ const result = yield resolver(request);
2742
+ if (result) {
2743
+ resolution = result;
2744
+ break;
2745
+ }
2746
+ }
2747
+ }
2748
+ const defaultDefinition = canonical ? maps_1.DEFAULT_PRN_REASON_DEFINITIONS[canonical] : undefined;
2749
+ if (!resolution && defaultDefinition) {
2750
+ resolution = defaultDefinition;
2751
+ }
2752
+ if (resolution) {
2753
+ applyPrnReasonDefinition(internal, resolution);
2754
+ }
2755
+ else {
2756
+ internal.asNeededReasonCoding = undefined;
2757
+ }
2758
+ const needsSuggestions = request.isProbe || !resolution;
2759
+ if (!needsSuggestions) {
2760
+ return;
2761
+ }
2762
+ const suggestionMap = new Map();
2763
+ if (selection) {
2764
+ addReasonSuggestionToMap(suggestionMap, definitionToPrnSuggestion(selection));
2765
+ }
2766
+ if (customDefinition) {
2767
+ addReasonSuggestionToMap(suggestionMap, definitionToPrnSuggestion(customDefinition));
2768
+ }
2769
+ if (defaultDefinition) {
2770
+ addReasonSuggestionToMap(suggestionMap, definitionToPrnSuggestion(defaultDefinition));
2771
+ }
2772
+ for (const definition of collectDefaultPrnReasonDefinitions(request)) {
2773
+ addReasonSuggestionToMap(suggestionMap, definitionToPrnSuggestion(definition));
2774
+ }
2775
+ for (const resolver of toArray(options === null || options === void 0 ? void 0 : options.prnReasonSuggestionResolvers)) {
2776
+ const result = yield resolver(request);
2777
+ collectReasonSuggestionResult(suggestionMap, result);
2778
+ }
2779
+ const suggestions = Array.from(suggestionMap.values());
2780
+ if (suggestions.length || request.isProbe) {
2781
+ internal.prnReasonLookups.push({ request, suggestions });
2782
+ }
2783
+ });
2784
+ }
2310
2785
  /**
2311
2786
  * Wraps scalar or array configuration into an array to simplify iteration.
2312
2787
  */