@precisa-saude/fhir 0.19.0 → 0.20.1

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.
Files changed (49) hide show
  1. package/dist/biomarkers.cjs +2 -2
  2. package/dist/biomarkers.js +1 -1
  3. package/dist/{chunk-MTWOF55H.js → chunk-3KIJIRCI.js} +44 -2
  4. package/dist/chunk-3KIJIRCI.js.map +1 -0
  5. package/dist/chunk-A6HR4XDK.js +9 -0
  6. package/dist/chunk-A6HR4XDK.js.map +1 -0
  7. package/dist/{chunk-MMO356YH.cjs → chunk-ERALICUK.cjs} +48 -1
  8. package/dist/chunk-ERALICUK.cjs.map +1 -0
  9. package/dist/chunk-ETZXOGAB.cjs +165 -0
  10. package/dist/chunk-ETZXOGAB.cjs.map +1 -0
  11. package/dist/{chunk-Z5VH5QGC.cjs → chunk-NXOTXKVB.cjs} +44 -2
  12. package/dist/chunk-NXOTXKVB.cjs.map +1 -0
  13. package/dist/chunk-OR67NJDZ.cjs +9 -0
  14. package/dist/chunk-OR67NJDZ.cjs.map +1 -0
  15. package/dist/{chunk-J3QVVVVH.cjs → chunk-QJF5BZ3J.cjs} +20 -9
  16. package/dist/chunk-QJF5BZ3J.cjs.map +1 -0
  17. package/dist/{chunk-XTEKGGYQ.js → chunk-QULBXISC.js} +48 -1
  18. package/dist/chunk-QULBXISC.js.map +1 -0
  19. package/dist/{chunk-LCXTQE2B.js → chunk-SN5ZJHWS.js} +20 -9
  20. package/dist/chunk-SN5ZJHWS.js.map +1 -0
  21. package/dist/{chunk-EXG2IU2O.js → chunk-YYANW65U.js} +38 -26
  22. package/dist/chunk-YYANW65U.js.map +1 -0
  23. package/dist/cli.js +142 -31
  24. package/dist/converter.cjs +4 -3
  25. package/dist/converter.cjs.map +1 -1
  26. package/dist/converter.js +3 -2
  27. package/dist/importer.cjs +4 -3
  28. package/dist/importer.cjs.map +1 -1
  29. package/dist/importer.d.cts +2 -1
  30. package/dist/importer.d.ts +2 -1
  31. package/dist/importer.js +3 -2
  32. package/dist/index.cjs +12 -6
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +19 -1
  35. package/dist/index.d.ts +19 -1
  36. package/dist/index.js +10 -4
  37. package/dist/index.js.map +1 -1
  38. package/dist/reference-ranges.cjs +2 -2
  39. package/dist/reference-ranges.js +1 -1
  40. package/package.json +1 -1
  41. package/dist/chunk-6HKQY6VO.cjs +0 -153
  42. package/dist/chunk-6HKQY6VO.cjs.map +0 -1
  43. package/dist/chunk-EXG2IU2O.js.map +0 -1
  44. package/dist/chunk-J3QVVVVH.cjs.map +0 -1
  45. package/dist/chunk-LCXTQE2B.js.map +0 -1
  46. package/dist/chunk-MMO356YH.cjs.map +0 -1
  47. package/dist/chunk-MTWOF55H.js.map +0 -1
  48. package/dist/chunk-XTEKGGYQ.js.map +0 -1
  49. package/dist/chunk-Z5VH5QGC.cjs.map +0 -1
@@ -1,7 +1,14 @@
1
1
  import {
2
- getDefinitionByLoinc,
3
- loincToCode
4
- } from "./chunk-MTWOF55H.js";
2
+ BIOMARKER_CODE_SYSTEM,
3
+ LOINC_SYSTEM
4
+ } from "./chunk-A6HR4XDK.js";
5
+ import {
6
+ codeToLoinc,
7
+ getDefinitionByCode,
8
+ isValidCode,
9
+ loincToCode,
10
+ normalizeCode
11
+ } from "./chunk-3KIJIRCI.js";
5
12
  import {
6
13
  validateFHIRImportBundle
7
14
  } from "./chunk-N3ZCOLG2.js";
@@ -9,10 +16,30 @@ import {
9
16
  // src/importer.ts
10
17
  var MAX_OBSERVATIONS = 5e3;
11
18
  var MAX_FILE_SIZE = 15 * 1024 * 1024;
12
- function extractLoincCode(observation) {
13
- if (!observation.code?.coding) return void 0;
14
- const loincCoding = observation.code.coding.find((c) => c.system === "http://loinc.org");
15
- return loincCoding?.code;
19
+ function resolveBiomarkerCode(observation) {
20
+ const coding = observation.code?.coding ?? [];
21
+ const loincCode = coding.find((c) => c.system === LOINC_SYSTEM)?.code;
22
+ const declaredCode = coding.find((c) => c.system === BIOMARKER_CODE_SYSTEM)?.code;
23
+ const seenCodes = [
24
+ ...loincCode ? [`LOINC ${loincCode}`] : [],
25
+ ...declaredCode ? [`biomarker code ${declaredCode}`] : []
26
+ ];
27
+ let reason;
28
+ if (seenCodes.length > 0) {
29
+ reason = `Unknown code: ${seenCodes.join(", ")}`;
30
+ } else if (coding.length > 0) {
31
+ const systems = [...new Set(coding.map((c) => c.system ?? "(sem system)"))];
32
+ reason = `No code in a supported system (found: ${systems.join(", ")})`;
33
+ } else {
34
+ reason = "No code found in observation coding";
35
+ }
36
+ const fromLoinc = loincCode ? loincToCode(loincCode) : void 0;
37
+ if (fromLoinc) return { internalCode: fromLoinc, loincCode, reason };
38
+ if (declaredCode && isValidCode(declaredCode)) {
39
+ const canonical = normalizeCode(declaredCode);
40
+ return { internalCode: canonical, loincCode: codeToLoinc(canonical), reason };
41
+ }
42
+ return { loincCode, reason };
16
43
  }
17
44
  function extractFlag(observation) {
18
45
  const code = observation.interpretation?.[0]?.coding?.[0]?.code;
@@ -41,28 +68,13 @@ function extractObservationsFromBundle(bundle) {
41
68
  return { observations, skipped };
42
69
  }
43
70
  function mapFHIRObservationToInternal(observation, index) {
44
- const loincCode = extractLoincCode(observation);
45
- if (!loincCode) {
46
- return {
47
- skipped: {
48
- index,
49
- reason: "No LOINC code found in observation coding",
50
- resourceType: "Observation"
51
- }
52
- };
53
- }
54
- const internalCode = loincToCode(loincCode);
71
+ const { internalCode, loincCode, reason } = resolveBiomarkerCode(observation);
55
72
  if (!internalCode) {
56
73
  return {
57
- skipped: {
58
- index,
59
- loincCode,
60
- reason: `Unknown LOINC code: ${loincCode}`,
61
- resourceType: "Observation"
62
- }
74
+ skipped: { index, loincCode, reason, resourceType: "Observation" }
63
75
  };
64
76
  }
65
- const definition = getDefinitionByLoinc(loincCode);
77
+ const definition = getDefinitionByCode(internalCode);
66
78
  let value;
67
79
  let unit = "";
68
80
  let isQualitative = false;
@@ -150,4 +162,4 @@ export {
150
162
  mapFHIRObservationToInternal,
151
163
  processImportBundle
152
164
  };
153
- //# sourceMappingURL=chunk-EXG2IU2O.js.map
165
+ //# sourceMappingURL=chunk-YYANW65U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/importer.ts"],"sourcesContent":["/**\n * FHIR Importer\n *\n * Parses FHIR R4 Bundles and extracts Observation resources with known LOINC codes,\n * mapping them to internal biomarker codes for storage as lab results.\n */\n\nimport {\n codeToLoinc,\n getDefinitionByCode,\n isValidCode,\n loincToCode,\n normalizeCode,\n} from './biomarkers';\nimport { BIOMARKER_CODE_SYSTEM, LOINC_SYSTEM } from './code-systems';\nimport type { FHIRBundle, FHIRObservation } from './fhir-types';\nimport { validateFHIRImportBundle } from './validators';\n\nexport interface ImportedObservation {\n biomarkerCode: string;\n biomarkerName: string;\n collectionDate: string;\n flag: 'H' | 'L' | '';\n isQualitative: boolean;\n /** Ausente nos biomarcadores sem LOINC publicado, como composição corporal. */\n loincCode?: string;\n referenceMax?: number;\n referenceMin?: number;\n unit: string;\n value: number | string;\n}\n\nexport interface SkippedEntry {\n index: number;\n loincCode?: string;\n reason: string;\n resourceType?: string;\n}\n\nexport interface ImportError {\n details: string;\n field: string;\n}\n\nexport interface FHIRImportResult {\n errors: ImportError[];\n imported: ImportedObservation[];\n skipped: SkippedEntry[];\n totalProcessed: number;\n}\n\n/**\n * Limites de importação.\n *\n * Uma Observation exportada ocupa cerca de 1,25KB em JSON compacto e 2,75KB\n * quando o arquivo vem indentado, medido sobre um histórico real de 998\n * Observations em 61 laudos. Nesse tamanho, 5000 Observations dão 6,0MB\n * compactos ou 13,1MB indentados, e por isso o teto de arquivo é 15MB: cobre\n * as duas formas com folga.\n *\n * Na densidade desse mesmo histórico (16 Observations por laudo), 5000\n * equivalem a cerca de 300 laudos.\n */\nconst MAX_OBSERVATIONS = 5000;\nconst MAX_FILE_SIZE = 15 * 1024 * 1024; // 15MB\n\n/**\n * Resolve o código interno do biomarcador a partir do `code.coding`.\n *\n * LOINC primeiro, que é o vocabulário que arquivos de terceiros usam. Quando\n * não resolve, cai para o coding de códigos internos, presente nos arquivos\n * exportados pela própria plataforma.\n *\n * O fallback cobre dois casos: biomarcadores sem LOINC publicado (composição\n * corporal, densidade óssea, escore de cálcio) e arquivos antigos, exportados\n * quando esses biomarcadores saíam com o placeholder `99999-9`, que não\n * resolve para nada.\n */\nfunction resolveBiomarkerCode(observation: FHIRObservation): {\n internalCode?: string;\n loincCode?: string;\n reason: string;\n} {\n const coding = observation.code?.coding ?? [];\n const loincCode = coding.find((c) => c.system === LOINC_SYSTEM)?.code;\n const declaredCode = coding.find((c) => c.system === BIOMARKER_CODE_SYSTEM)?.code;\n\n const seenCodes = [\n ...(loincCode ? [`LOINC ${loincCode}`] : []),\n ...(declaredCode ? [`biomarker code ${declaredCode}`] : []),\n ];\n\n // Três motivos distintos de descarte, que antes se confundiam num só. Sem\n // essa separação, um arquivo em SNOMED relatava \"nenhum código encontrado\",\n // sugerindo `coding` vazio quando na verdade o código existia e estava num\n // system que não tratamos. Para importação de terceiros, é a diferença entre\n // um diagnóstico acionável e um enigma.\n let reason: string;\n if (seenCodes.length > 0) {\n reason = `Unknown code: ${seenCodes.join(', ')}`;\n } else if (coding.length > 0) {\n const systems = [...new Set(coding.map((c) => c.system ?? '(sem system)'))];\n reason = `No code in a supported system (found: ${systems.join(', ')})`;\n } else {\n reason = 'No code found in observation coding';\n }\n\n const fromLoinc = loincCode ? loincToCode(loincCode) : undefined;\n if (fromLoinc) return { internalCode: fromLoinc, loincCode, reason };\n\n if (declaredCode && isValidCode(declaredCode)) {\n // `isValidCode` aceita alias, mas alias não serve como código armazenado:\n // 49 definições têm um, e tanto `codeToLoinc` quanto as faixas de\n // referência são indexadas só pelo canônico. Sem normalizar, `VLDL_Cholesterol`\n // entraria no lugar de `VLDL` e perderia o LOINC 13458-5 que ele tem.\n // Importar um Bundle é fronteira de dados, que é onde `normalizeCode` deve\n // ser aplicado.\n const canonical = normalizeCode(declaredCode);\n\n // `codeToLoinc` devolve undefined para quem não tem LOINC, que é o caso\n // esperado aqui. O campo fica de fora em vez de receber um valor inventado.\n return { internalCode: canonical, loincCode: codeToLoinc(canonical), reason };\n }\n\n return { loincCode, reason };\n}\n\n/**\n * Extract interpretation flag from Observation\n */\nfunction extractFlag(observation: FHIRObservation): 'H' | 'L' | '' {\n const code = observation.interpretation?.[0]?.coding?.[0]?.code;\n if (code === 'H' || code === 'HH') return 'H';\n if (code === 'L' || code === 'LL') return 'L';\n return '';\n}\n\n/**\n * Extract Observation resources from a FHIR Bundle\n */\nexport function extractObservationsFromBundle(bundle: FHIRBundle): {\n observations: FHIRObservation[];\n skipped: SkippedEntry[];\n} {\n const observations: FHIRObservation[] = [];\n const skipped: SkippedEntry[] = [];\n\n for (let i = 0; i < bundle.entry.length; i++) {\n const entry = bundle.entry[i]!;\n if (!entry.resource) {\n skipped.push({ index: i, reason: 'Entry has no resource' });\n continue;\n }\n\n if (entry.resource.resourceType !== 'Observation') {\n // Non-observation resources are silently skipped (Patient, DiagnosticReport, etc.)\n continue;\n }\n\n if (observations.length >= MAX_OBSERVATIONS) {\n skipped.push({ index: i, reason: `Maximum of ${MAX_OBSERVATIONS} observations exceeded` });\n continue;\n }\n\n observations.push(entry.resource as FHIRObservation);\n }\n\n return { observations, skipped };\n}\n\n/**\n * Map a FHIR Observation to internal format using LOINC→biomarker code lookup\n */\nexport function mapFHIRObservationToInternal(\n observation: FHIRObservation,\n index: number,\n): { observation: ImportedObservation } | { skipped: SkippedEntry } {\n const { internalCode, loincCode, reason } = resolveBiomarkerCode(observation);\n\n if (!internalCode) {\n return {\n skipped: { index, loincCode, reason, resourceType: 'Observation' },\n };\n }\n\n const definition = getDefinitionByCode(internalCode);\n\n // Extract value\n let value: number | string;\n let unit = '';\n let isQualitative = false;\n\n if (observation.valueQuantity?.value !== undefined) {\n value = observation.valueQuantity.value;\n unit = observation.valueQuantity.unit || observation.valueQuantity.code || '';\n } else if (observation.valueString) {\n value = observation.valueString;\n isQualitative = true;\n } else {\n return {\n skipped: {\n index,\n loincCode,\n reason: 'Observation has no value (valueQuantity or valueString)',\n resourceType: 'Observation',\n },\n };\n }\n\n // Extract collection date (effectiveDateTime or effectivePeriod.start)\n const collectionDate = observation.effectiveDateTime || observation.effectivePeriod?.start || '';\n if (!collectionDate) {\n return {\n skipped: {\n index,\n loincCode,\n reason: 'Observation has no effectiveDateTime or effectivePeriod.start',\n resourceType: 'Observation',\n },\n };\n }\n\n // Extract reference ranges\n let referenceMin: number | undefined;\n let referenceMax: number | undefined;\n if (observation.referenceRange?.[0]) {\n referenceMin = observation.referenceRange[0].low?.value;\n referenceMax = observation.referenceRange[0].high?.value;\n }\n\n const imported: ImportedObservation = {\n biomarkerCode: internalCode,\n biomarkerName:\n definition?.names.pt[0] || definition?.names.en[0] || observation.code.text || internalCode,\n collectionDate,\n flag: extractFlag(observation),\n isQualitative,\n loincCode,\n referenceMax,\n referenceMin,\n unit: unit || definition?.unit || '',\n value,\n };\n\n return { observation: imported };\n}\n\n/**\n * Process a complete FHIR Bundle for import\n */\nexport function processImportBundle(data: unknown): FHIRImportResult {\n // Structural validation\n const validationErrors = validateFHIRImportBundle(data);\n if (validationErrors.length > 0) {\n return {\n errors: validationErrors,\n imported: [],\n skipped: [],\n totalProcessed: 0,\n };\n }\n\n const bundle = data as FHIRBundle;\n\n // Extract observations\n const { observations, skipped } = extractObservationsFromBundle(bundle);\n\n // Map each observation to internal format\n const imported: ImportedObservation[] = [];\n const allSkipped: SkippedEntry[] = [...skipped];\n\n for (let i = 0; i < observations.length; i++) {\n const result = mapFHIRObservationToInternal(observations[i]!, i);\n\n if ('observation' in result) {\n imported.push(result.observation);\n } else {\n allSkipped.push(result.skipped);\n }\n }\n\n return {\n errors: [],\n imported,\n skipped: allSkipped,\n totalProcessed: observations.length,\n };\n}\n\nexport { MAX_FILE_SIZE, MAX_OBSERVATIONS };\n"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -2252,8 +2252,9 @@ var BIOMARKER_DEFINITIONS = [
2252
2252
  // múltiplas formulações: "total body water" não devolve nada, "body water"
2253
2253
  // devolve os dois códigos abaixo.
2254
2254
  //
2255
- // As 12 entradas sem código, e o motivo de cada uma:
2255
+ // As 13 entradas sem código, e o motivo de cada uma:
2256
2256
  //
2257
+ // MuscleMassIndex corte publicado é sobre massa apendicular, não total
2257
2258
  // VisceralFatLevel índice de 1 a 20; 73707-2 é área, outra grandeza
2258
2259
  // ResidualMass conceito de fracionamento antropométrico, não LOINC
2259
2260
  // BasalMetabolicRate candidatos são índice ou RMR medido, ver nota local
@@ -2303,6 +2304,35 @@ var BIOMARKER_DEFINITIONS = [
2303
2304
  },
2304
2305
  unit: "kg"
2305
2306
  },
2307
+ // Derivado, não extraído: `MuscleMass / altura²`, calculado pelo
2308
+ // `calculadoras-clinicas` a partir da altura que o usuário informa no
2309
+ // cadastro. Mesmo ajuste que o IMC faz com o peso, e serve para a medida
2310
+ // ser comparável entre estaturas diferentes e ao longo do tempo.
2311
+ //
2312
+ // Sem `loinc` e sem faixa, e agora com fonte para a decisão em vez de só
2313
+ // cautela. O EWGSOP2 (Age and Ageing, 2019, DOI 10.1093/ageing/afy169)
2314
+ // separa explicitamente "total body Skeletal Muscle Mass (SMM)" de
2315
+ // "Appendicular Skeletal Muscle Mass (ASM)", e os cortes publicados são
2316
+ // sobre ASM. `MuscleMass` aqui é total, então o corte não se aplica.
2317
+ //
2318
+ // O mesmo consenso ainda diz, sobre ajustar por tamanho corporal: "The
2319
+ // authors make no recommendation to adjust for body size, but adjustment
2320
+ // can be made if data are available for a relevant normative population."
2321
+ // Não temos população normativa brasileira para bioimpedância, e o
2322
+ // consenso registra que a equação de Sergi, padrão do método, foi
2323
+ // derivada em europeus idosos.
2324
+ //
2325
+ // Por isso o índice existe para acompanhar a própria evolução, e não para
2326
+ // classificar.
2327
+ {
2328
+ category: "composicao-corporal",
2329
+ code: "MuscleMassIndex",
2330
+ names: {
2331
+ en: ["Muscle Mass Index", "Skeletal Muscle Mass Index", "SMI", "SMMI"],
2332
+ pt: ["\xCDndice de Massa Muscular", "IMM", "\xCDndice de Massa Muscular Esquel\xE9tica"]
2333
+ },
2334
+ unit: "kg/m2"
2335
+ },
2306
2336
  {
2307
2337
  category: "composicao-corporal",
2308
2338
  code: "PhaseAngle",
@@ -2404,6 +2434,18 @@ var BIOMARKER_DEFINITIONS = [
2404
2434
  },
2405
2435
  unit: "cm"
2406
2436
  },
2437
+ // O EWGSOP2 usa a panturrilha como proxy de massa muscular onde não há
2438
+ // outro método disponível, o que a torna útil em consulta sem aparelho.
2439
+ {
2440
+ category: "composicao-corporal",
2441
+ code: "CalfCircumference",
2442
+ loinc: "107112-5",
2443
+ names: {
2444
+ en: ["Calf Circumference", "Calf Girth"],
2445
+ pt: ["Circunfer\xEAncia da Panturrilha", "Per\xEDmetro da Panturrilha", "Panturrilha"]
2446
+ },
2447
+ unit: "cm"
2448
+ },
2407
2449
  {
2408
2450
  category: "composicao-corporal",
2409
2451
  code: "WaistToHeightRatio",
@@ -2984,6 +3026,12 @@ function loincToCode(loinc) {
2984
3026
  function codeToLoinc(code) {
2985
3027
  return codeToLoincMap.get(code);
2986
3028
  }
3029
+ function isValidCode(code) {
3030
+ return validCodeSet.has(code);
3031
+ }
3032
+ function normalizeCode(code) {
3033
+ return codeAliasToCanonicalMap.get(code) ?? code;
3034
+ }
2987
3035
  function getDefinitionByCode(code) {
2988
3036
  return codeToDefinitionMap.get(code);
2989
3037
  }
@@ -3048,6 +3096,10 @@ async function categories(_args, json) {
3048
3096
  outputText(lines.join("\n"));
3049
3097
  }
3050
3098
 
3099
+ // src/code-systems.ts
3100
+ var LOINC_SYSTEM = "http://loinc.org";
3101
+ var BIOMARKER_CODE_SYSTEM = "http://fhir-brasil.dev/biomarker-codes";
3102
+
3051
3103
  // src/units.ts
3052
3104
  var UNIT_TO_UCUM = {
3053
3105
  // Dimensionless / special measurements
@@ -3918,7 +3970,7 @@ function interpretationDisplay(flag) {
3918
3970
  }
3919
3971
  }
3920
3972
  function labObservationToFHIR(observation, patientId, laboratoryName) {
3921
- const loincCode = codeToLoinc(observation.biomarkerCode) || "99999-9";
3973
+ const loincCode = codeToLoinc(observation.biomarkerCode);
3922
3974
  const sourceUnit = observation.unit || getDefaultUnit(observation.biomarkerCode) || observation.unit;
3923
3975
  const ucumUnit = unitToUCUM(sourceUnit);
3924
3976
  const isQualitative = observation.isQualitative || typeof observation.value === "string";
@@ -3935,16 +3987,23 @@ function labObservationToFHIR(observation, patientId, laboratoryName) {
3935
3987
  }
3936
3988
  ],
3937
3989
  code: {
3990
+ // Sem LOINC, o coding LOINC simplesmente não sai. Antes ia `99999-9`,
3991
+ // que não é código LOINC nenhum: publicava sob `http://loinc.org` uma
3992
+ // afirmação falsa, e quem consumisse o bundle confiando no system
3993
+ // trataria aquilo como código de verdade. Composição corporal, densidade
3994
+ // óssea e escore de cálcio não têm LOINC, e o certo é a lacuna explícita.
3938
3995
  coding: [
3939
- {
3940
- code: loincCode,
3941
- display: observation.biomarkerName,
3942
- system: "http://loinc.org"
3943
- },
3996
+ ...loincCode ? [
3997
+ {
3998
+ code: loincCode,
3999
+ display: observation.biomarkerName,
4000
+ system: LOINC_SYSTEM
4001
+ }
4002
+ ] : [],
3944
4003
  {
3945
4004
  code: observation.biomarkerCode,
3946
4005
  display: observation.biomarkerName,
3947
- system: "http://fhir-brasil.dev/biomarker-codes"
4006
+ system: BIOMARKER_CODE_SYSTEM
3948
4007
  }
3949
4008
  ],
3950
4009
  text: observation.biomarkerName
@@ -4175,10 +4234,30 @@ function validateFHIRImportBundle(data) {
4175
4234
  // src/importer.ts
4176
4235
  var MAX_OBSERVATIONS = 5e3;
4177
4236
  var MAX_FILE_SIZE = 15 * 1024 * 1024;
4178
- function extractLoincCode(observation) {
4179
- if (!observation.code?.coding) return void 0;
4180
- const loincCoding = observation.code.coding.find((c) => c.system === "http://loinc.org");
4181
- return loincCoding?.code;
4237
+ function resolveBiomarkerCode(observation) {
4238
+ const coding = observation.code?.coding ?? [];
4239
+ const loincCode = coding.find((c) => c.system === LOINC_SYSTEM)?.code;
4240
+ const declaredCode = coding.find((c) => c.system === BIOMARKER_CODE_SYSTEM)?.code;
4241
+ const seenCodes = [
4242
+ ...loincCode ? [`LOINC ${loincCode}`] : [],
4243
+ ...declaredCode ? [`biomarker code ${declaredCode}`] : []
4244
+ ];
4245
+ let reason;
4246
+ if (seenCodes.length > 0) {
4247
+ reason = `Unknown code: ${seenCodes.join(", ")}`;
4248
+ } else if (coding.length > 0) {
4249
+ const systems = [...new Set(coding.map((c) => c.system ?? "(sem system)"))];
4250
+ reason = `No code in a supported system (found: ${systems.join(", ")})`;
4251
+ } else {
4252
+ reason = "No code found in observation coding";
4253
+ }
4254
+ const fromLoinc = loincCode ? loincToCode(loincCode) : void 0;
4255
+ if (fromLoinc) return { internalCode: fromLoinc, loincCode, reason };
4256
+ if (declaredCode && isValidCode(declaredCode)) {
4257
+ const canonical = normalizeCode(declaredCode);
4258
+ return { internalCode: canonical, loincCode: codeToLoinc(canonical), reason };
4259
+ }
4260
+ return { loincCode, reason };
4182
4261
  }
4183
4262
  function extractFlag(observation) {
4184
4263
  const code = observation.interpretation?.[0]?.coding?.[0]?.code;
@@ -4207,28 +4286,13 @@ function extractObservationsFromBundle(bundle) {
4207
4286
  return { observations, skipped };
4208
4287
  }
4209
4288
  function mapFHIRObservationToInternal(observation, index) {
4210
- const loincCode = extractLoincCode(observation);
4211
- if (!loincCode) {
4212
- return {
4213
- skipped: {
4214
- index,
4215
- reason: "No LOINC code found in observation coding",
4216
- resourceType: "Observation"
4217
- }
4218
- };
4219
- }
4220
- const internalCode = loincToCode(loincCode);
4289
+ const { internalCode, loincCode, reason } = resolveBiomarkerCode(observation);
4221
4290
  if (!internalCode) {
4222
4291
  return {
4223
- skipped: {
4224
- index,
4225
- loincCode,
4226
- reason: `Unknown LOINC code: ${loincCode}`,
4227
- resourceType: "Observation"
4228
- }
4292
+ skipped: { index, loincCode, reason, resourceType: "Observation" }
4229
4293
  };
4230
4294
  }
4231
- const definition = getDefinitionByLoinc(loincCode);
4295
+ const definition = getDefinitionByCode(internalCode);
4232
4296
  let value;
4233
4297
  let unit = "";
4234
4298
  let isQualitative = false;
@@ -5935,6 +5999,53 @@ var biomarkerRangeDefinitions = {
5935
5999
  // Só `max`. O limite inferior não entra porque a revisão não estabelece
5936
6000
  // piso, e inventar um transformaria em alteração um valor que a fonte não
5937
6001
  // classifica.
6002
+ // O EWGSOP2 traz um único corte, <31 cm, e o enuncia restrito: "Calf
6003
+ // circumference has been shown to predict performance and survival in
6004
+ // older people (cut-off point <31 cm)". Por isso entra como variante por
6005
+ // idade, e não como padrão para todo adulto — estender o número para
6006
+ // gente de 30 anos seria ir além do que a fonte diz.
6007
+ //
6008
+ // O padrão fica sem `min` de propósito: não há corte publicado para
6009
+ // adulto jovem, e o consumidor lê a medida sem zona em vez de ler uma
6010
+ // zona inventada.
6011
+ //
6012
+ // Como interpretar, por faixa etária:
6013
+ //
6014
+ // 60+ a medida tem corte e classifica: abaixo de 31 cm é sinal de
6015
+ // alerta para perda de massa muscular.
6016
+ // <60 a medida é válida e comparável com ela mesma ao longo do tempo,
6017
+ // mas não classifica. Uma queda consistente entre exames importa
6018
+ // mais do que o valor absoluto num único dia, e é assim que o
6019
+ // conteúdo do marcador orienta o usuário.
6020
+ //
6021
+ // A ausência de zona abaixo dos 60 não é lacuna a preencher com o número
6022
+ // dos idosos: massa muscular tem trajetória própria por idade, e o
6023
+ // consenso deriva o corte justamente na faixa em que a perda vira
6024
+ // desfecho.
6025
+ //
6026
+ // Recência conferida em 28/08/2026. Existe consenso mais novo, o GLIS
6027
+ // 2024 (Age and Ageing, DOI 10.1093/ageing/afae052), primeiro global
6028
+ // sobre sarcopenia, com Cruz-Jentoft e Chen entre os autores — ou seja,
6029
+ // os líderes do EWGSOP2 e do AWGS. Ele **não** substitui este corte: é
6030
+ // conceitual, e o próprio texto diz que servirá "to develop an
6031
+ // operational definition for clinical and research settings". Enquanto a
6032
+ // definição operacional não sai, o EWGSOP2 segue sendo a referência de
6033
+ // ponto de corte.
6034
+ //
6035
+ // Nota: o consenso asiático (AWGS 2019) usa 34 cm para homens e 33 para
6036
+ // mulheres, em outra população e como triagem, não como corte de massa.
6037
+ // Os números não são intercambiáveis.
6038
+ CalfCircumference: {
6039
+ default: { unit: "cm" },
6040
+ direction: "higher-better",
6041
+ source: "ewgsop2-2019",
6042
+ // O corte não é específico por sexo na fonte; as duas variantes existem
6043
+ // porque `RangeVariant` exige o campo, e carregam o mesmo número.
6044
+ variants: [
6045
+ { ageMin: 60, range: { min: 31, unit: "cm" }, sex: "F" },
6046
+ { ageMin: 60, range: { min: 31, unit: "cm" }, sex: "M" }
6047
+ ]
6048
+ },
5938
6049
  WaistToHeightRatio: {
5939
6050
  default: { max: 0.5, unit: "" },
5940
6051
  direction: "lower-better",
@@ -6489,7 +6600,7 @@ async function main() {
6489
6600
  strict: false
6490
6601
  });
6491
6602
  if (values.version) {
6492
- process.stdout.write(`${"0.19.0"}
6603
+ process.stdout.write(`${"0.20.1"}
6493
6604
  `);
6494
6605
  return;
6495
6606
  }
@@ -3,13 +3,14 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkJ3QVVVVHcjs = require('./chunk-J3QVVVVH.cjs');
7
- require('./chunk-Z5VH5QGC.cjs');
6
+ var _chunkQJF5BZ3Jcjs = require('./chunk-QJF5BZ3J.cjs');
7
+ require('./chunk-OR67NJDZ.cjs');
8
+ require('./chunk-NXOTXKVB.cjs');
8
9
  require('./chunk-MJ254F5K.cjs');
9
10
 
10
11
 
11
12
 
12
13
 
13
14
 
14
- exports.labObservationToFHIR = _chunkJ3QVVVVHcjs.labObservationToFHIR; exports.labReportToFHIR = _chunkJ3QVVVVHcjs.labReportToFHIR; exports.labResultToFHIRBundle = _chunkJ3QVVVVHcjs.labResultToFHIRBundle; exports.userProfileToFHIR = _chunkJ3QVVVVHcjs.userProfileToFHIR;
15
+ exports.labObservationToFHIR = _chunkQJF5BZ3Jcjs.labObservationToFHIR; exports.labReportToFHIR = _chunkQJF5BZ3Jcjs.labReportToFHIR; exports.labResultToFHIRBundle = _chunkQJF5BZ3Jcjs.labResultToFHIRBundle; exports.userProfileToFHIR = _chunkQJF5BZ3Jcjs.userProfileToFHIR;
15
16
  //# sourceMappingURL=converter.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/fhir-brasil/fhir-brasil/packages/core/dist/converter.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACF,6QAAC","file":"/home/runner/work/fhir-brasil/fhir-brasil/packages/core/dist/converter.cjs"}
1
+ {"version":3,"sources":["/home/runner/work/fhir-brasil/fhir-brasil/packages/core/dist/converter.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACF,6QAAC","file":"/home/runner/work/fhir-brasil/fhir-brasil/packages/core/dist/converter.cjs"}
package/dist/converter.js CHANGED
@@ -3,8 +3,9 @@ import {
3
3
  labReportToFHIR,
4
4
  labResultToFHIRBundle,
5
5
  userProfileToFHIR
6
- } from "./chunk-LCXTQE2B.js";
7
- import "./chunk-MTWOF55H.js";
6
+ } from "./chunk-SN5ZJHWS.js";
7
+ import "./chunk-A6HR4XDK.js";
8
+ import "./chunk-3KIJIRCI.js";
8
9
  import "./chunk-R4MUCMO3.js";
9
10
  export {
10
11
  labObservationToFHIR,
package/dist/importer.cjs CHANGED
@@ -4,8 +4,9 @@
4
4
 
5
5
 
6
6
 
7
- var _chunk6HKQY6VOcjs = require('./chunk-6HKQY6VO.cjs');
8
- require('./chunk-Z5VH5QGC.cjs');
7
+ var _chunkETZXOGABcjs = require('./chunk-ETZXOGAB.cjs');
8
+ require('./chunk-OR67NJDZ.cjs');
9
+ require('./chunk-NXOTXKVB.cjs');
9
10
  require('./chunk-3ILBFLVQ.cjs');
10
11
 
11
12
 
@@ -13,5 +14,5 @@ require('./chunk-3ILBFLVQ.cjs');
13
14
 
14
15
 
15
16
 
16
- exports.MAX_FILE_SIZE = _chunk6HKQY6VOcjs.MAX_FILE_SIZE; exports.MAX_OBSERVATIONS = _chunk6HKQY6VOcjs.MAX_OBSERVATIONS; exports.extractObservationsFromBundle = _chunk6HKQY6VOcjs.extractObservationsFromBundle; exports.mapFHIRObservationToInternal = _chunk6HKQY6VOcjs.mapFHIRObservationToInternal; exports.processImportBundle = _chunk6HKQY6VOcjs.processImportBundle;
17
+ exports.MAX_FILE_SIZE = _chunkETZXOGABcjs.MAX_FILE_SIZE; exports.MAX_OBSERVATIONS = _chunkETZXOGABcjs.MAX_OBSERVATIONS; exports.extractObservationsFromBundle = _chunkETZXOGABcjs.extractObservationsFromBundle; exports.mapFHIRObservationToInternal = _chunkETZXOGABcjs.mapFHIRObservationToInternal; exports.processImportBundle = _chunkETZXOGABcjs.processImportBundle;
17
18
  //# sourceMappingURL=importer.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/fhir-brasil/fhir-brasil/packages/core/dist/importer.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACF,4WAAC","file":"/home/runner/work/fhir-brasil/fhir-brasil/packages/core/dist/importer.cjs"}
1
+ {"version":3,"sources":["/home/runner/work/fhir-brasil/fhir-brasil/packages/core/dist/importer.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACF,4WAAC","file":"/home/runner/work/fhir-brasil/fhir-brasil/packages/core/dist/importer.cjs"}
@@ -13,7 +13,8 @@ interface ImportedObservation {
13
13
  collectionDate: string;
14
14
  flag: 'H' | 'L' | '';
15
15
  isQualitative: boolean;
16
- loincCode: string;
16
+ /** Ausente nos biomarcadores sem LOINC publicado, como composição corporal. */
17
+ loincCode?: string;
17
18
  referenceMax?: number;
18
19
  referenceMin?: number;
19
20
  unit: string;
@@ -13,7 +13,8 @@ interface ImportedObservation {
13
13
  collectionDate: string;
14
14
  flag: 'H' | 'L' | '';
15
15
  isQualitative: boolean;
16
- loincCode: string;
16
+ /** Ausente nos biomarcadores sem LOINC publicado, como composição corporal. */
17
+ loincCode?: string;
17
18
  referenceMax?: number;
18
19
  referenceMin?: number;
19
20
  unit: string;
package/dist/importer.js CHANGED
@@ -4,8 +4,9 @@ import {
4
4
  extractObservationsFromBundle,
5
5
  mapFHIRObservationToInternal,
6
6
  processImportBundle
7
- } from "./chunk-EXG2IU2O.js";
8
- import "./chunk-MTWOF55H.js";
7
+ } from "./chunk-YYANW65U.js";
8
+ import "./chunk-A6HR4XDK.js";
9
+ import "./chunk-3KIJIRCI.js";
9
10
  import "./chunk-N3ZCOLG2.js";
10
11
  export {
11
12
  MAX_FILE_SIZE,
package/dist/index.cjs CHANGED
@@ -3,17 +3,18 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkJ3QVVVVHcjs = require('./chunk-J3QVVVVH.cjs');
6
+ var _chunkQJF5BZ3Jcjs = require('./chunk-QJF5BZ3J.cjs');
7
7
 
8
8
 
9
9
 
10
10
 
11
11
 
12
12
 
13
- var _chunk6HKQY6VOcjs = require('./chunk-6HKQY6VO.cjs');
13
+ var _chunkETZXOGABcjs = require('./chunk-ETZXOGAB.cjs');
14
14
 
15
15
 
16
16
 
17
+ var _chunkOR67NJDZcjs = require('./chunk-OR67NJDZ.cjs');
17
18
 
18
19
 
19
20
 
@@ -43,15 +44,18 @@ var _chunk6HKQY6VOcjs = require('./chunk-6HKQY6VO.cjs');
43
44
 
44
45
 
45
46
 
46
- var _chunkZ5VH5QGCcjs = require('./chunk-Z5VH5QGC.cjs');
47
47
 
48
48
 
49
49
 
50
+ var _chunkNXOTXKVBcjs = require('./chunk-NXOTXKVB.cjs');
50
51
 
51
52
 
52
53
 
53
54
 
54
- var _chunkMMO356YHcjs = require('./chunk-MMO356YH.cjs');
55
+
56
+
57
+
58
+ var _chunkERALICUKcjs = require('./chunk-ERALICUK.cjs');
55
59
 
56
60
 
57
61
 
@@ -228,7 +232,7 @@ function interventionToFHIRObservation(intervention, patientId) {
228
232
  }
229
233
  function interventionsToFHIRBundle(interventions, userProfile) {
230
234
  const patientId = userProfile.userId;
231
- const fhirPatient = _chunkJ3QVVVVHcjs.userProfileToFHIR.call(void 0, userProfile);
235
+ const fhirPatient = _chunkQJF5BZ3Jcjs.userProfileToFHIR.call(void 0, userProfile);
232
236
  const entries = interventions.map((intervention) => {
233
237
  const isMedication = intervention.type === "medication" || intervention.type === "supplement";
234
238
  const resource = isMedication ? interventionToFHIRMedicationStatement(intervention, patientId) : interventionToFHIRObservation(intervention, patientId);
@@ -691,5 +695,7 @@ function cnsToFHIRIdentifier(cns) {
691
695
 
692
696
 
693
697
 
694
- exports.AGE_BRACKETS = AGE_BRACKETS; exports.BIOMARKER_DEFAULT_UNIT = _chunkMJ254F5Kcjs.BIOMARKER_DEFAULT_UNIT; exports.BIOMARKER_DEFINITIONS = _chunkZ5VH5QGCcjs.BIOMARKER_DEFINITIONS; exports.BIOMARKER_UNITS = _chunkMJ254F5Kcjs.BIOMARKER_UNITS; exports.BODY_FAT_ZONES = BODY_FAT_ZONES; exports.CAC_INDICATOR_CODES = _chunkZ5VH5QGCcjs.CAC_INDICATOR_CODES; exports.CATEGORY_GROUPS = CATEGORY_GROUPS; exports.CATEGORY_SCREENING_INTERVALS = CATEGORY_SCREENING_INTERVALS; exports.DEXA_CATEGORIES = _chunkZ5VH5QGCcjs.DEXA_CATEGORIES; exports.DEXA_INDICATOR_CODES = _chunkZ5VH5QGCcjs.DEXA_INDICATOR_CODES; exports.MAX_FILE_SIZE = _chunk6HKQY6VOcjs.MAX_FILE_SIZE; exports.MAX_OBSERVATIONS = _chunk6HKQY6VOcjs.MAX_OBSERVATIONS; exports.T_SCORE_ZONES = T_SCORE_ZONES; exports.UNIT_TO_UCUM = _chunkMJ254F5Kcjs.UNIT_TO_UCUM; exports.ZONE_DEFS = ZONE_DEFS; exports.applyFallbackReferenceRanges = _chunkMMO356YHcjs.applyFallbackReferenceRanges; exports.biomarkerRangeDefinitions = _chunkMMO356YHcjs.biomarkerRangeDefinitions; exports.calculateNextScreeningDate = calculateNextScreeningDate; exports.cnsToFHIRIdentifier = cnsToFHIRIdentifier; exports.codeToLoinc = _chunkZ5VH5QGCcjs.codeToLoinc; exports.convertUnit = _chunkMJ254F5Kcjs.convertUnit; exports.cpfToFHIRIdentifier = cpfToFHIRIdentifier; exports.defaultReferenceRanges = _chunkMMO356YHcjs.defaultReferenceRanges; exports.extractObservationsFromBundle = _chunk6HKQY6VOcjs.extractObservationsFromBundle; exports.filterVisibleBiomarkers = _chunkZ5VH5QGCcjs.filterVisibleBiomarkers; exports.findCodeByName = _chunkZ5VH5QGCcjs.findCodeByName; exports.formatCNS = formatCNS; exports.formatCPF = formatCPF; exports.generateCacFullReference = _chunkZ5VH5QGCcjs.generateCacFullReference; exports.generateDexaFullReference = _chunkZ5VH5QGCcjs.generateDexaFullReference; exports.generateFilteredLLMReference = _chunkZ5VH5QGCcjs.generateFilteredLLMReference; exports.generateLLMReference = _chunkZ5VH5QGCcjs.generateLLMReference; exports.getAllCodes = _chunkZ5VH5QGCcjs.getAllCodes; exports.getAllDefinitions = _chunkZ5VH5QGCcjs.getAllDefinitions; exports.getAllLoincCodes = _chunkZ5VH5QGCcjs.getAllLoincCodes; exports.getAllSearchPatterns = _chunkZ5VH5QGCcjs.getAllSearchPatterns; exports.getBiomarkersByCategory = _chunkZ5VH5QGCcjs.getBiomarkersByCategory; exports.getBiomarkersForCategories = _chunkZ5VH5QGCcjs.getBiomarkersForCategories; exports.getCanonicalUnit = _chunkMJ254F5Kcjs.getCanonicalUnit; exports.getCategoriesByInterval = getCategoriesByInterval; exports.getCategoryGroup = getCategoryGroup; exports.getDaysUntilScreening = getDaysUntilScreening; exports.getDefaultUnit = _chunkMJ254F5Kcjs.getDefaultUnit; exports.getDefinitionByCode = _chunkZ5VH5QGCcjs.getDefinitionByCode; exports.getDefinitionByLoinc = _chunkZ5VH5QGCcjs.getDefinitionByLoinc; exports.getDefinitionsBySex = _chunkZ5VH5QGCcjs.getDefinitionsBySex; exports.getDueCategories = getDueCategories; exports.getFallbackReferenceRange = _chunkMMO356YHcjs.getFallbackReferenceRange; exports.getRangeDirection = _chunkMMO356YHcjs.getRangeDirection; exports.getReferenceRange = _chunkMMO356YHcjs.getReferenceRange; exports.getSIUnit = _chunkMJ254F5Kcjs.getSIUnit; exports.getScreeningInterval = getScreeningInterval; exports.getSexForCode = _chunkZ5VH5QGCcjs.getSexForCode; exports.getVisibleDefinitions = _chunkZ5VH5QGCcjs.getVisibleDefinitions; exports.interventionToFHIRMedicationStatement = interventionToFHIRMedicationStatement; exports.interventionToFHIRObservation = interventionToFHIRObservation; exports.interventionsToFHIRBundle = interventionsToFHIRBundle; exports.isBiomarkerVisible = _chunkZ5VH5QGCcjs.isBiomarkerVisible; exports.isCacDocument = _chunkZ5VH5QGCcjs.isCacDocument; exports.isDexaDocument = _chunkZ5VH5QGCcjs.isDexaDocument; exports.isScreeningDue = isScreeningDue; exports.isValidCode = _chunkZ5VH5QGCcjs.isValidCode; exports.isValidLoinc = _chunkZ5VH5QGCcjs.isValidLoinc; exports.labObservationToFHIR = _chunkJ3QVVVVHcjs.labObservationToFHIR; exports.labReportToFHIR = _chunkJ3QVVVVHcjs.labReportToFHIR; exports.labResultToFHIRBundle = _chunkJ3QVVVVHcjs.labResultToFHIRBundle; exports.listMappedSubcategories = listMappedSubcategories; exports.loincToCode = _chunkZ5VH5QGCcjs.loincToCode; exports.mapFHIRObservationToInternal = _chunk6HKQY6VOcjs.mapFHIRObservationToInternal; exports.normalizeCode = _chunkZ5VH5QGCcjs.normalizeCode; exports.plural = plural; exports.pluralCount = pluralCount; exports.pluralPhrase = pluralPhrase; exports.pluralPhraseCount = pluralPhraseCount; exports.processImportBundle = _chunk6HKQY6VOcjs.processImportBundle; exports.toBiomarkerTests = _chunkZ5VH5QGCcjs.toBiomarkerTests; exports.unitToUCUM = _chunkMJ254F5Kcjs.unitToUCUM; exports.userProfileToFHIR = _chunkJ3QVVVVHcjs.userProfileToFHIR; exports.validateCNS = validateCNS; exports.validateCPF = validateCPF; exports.validateFHIRDiagnosticReport = _chunk3ILBFLVQcjs.validateFHIRDiagnosticReport; exports.validateFHIRImportBundle = _chunk3ILBFLVQcjs.validateFHIRImportBundle; exports.validateFHIRObservation = _chunk3ILBFLVQcjs.validateFHIRObservation; exports.validateLoincNameMatch = _chunkZ5VH5QGCcjs.validateLoincNameMatch;
698
+
699
+
700
+ exports.AGE_BRACKETS = AGE_BRACKETS; exports.BIOMARKER_CODE_SYSTEM = _chunkOR67NJDZcjs.BIOMARKER_CODE_SYSTEM; exports.BIOMARKER_DEFAULT_UNIT = _chunkMJ254F5Kcjs.BIOMARKER_DEFAULT_UNIT; exports.BIOMARKER_DEFINITIONS = _chunkNXOTXKVBcjs.BIOMARKER_DEFINITIONS; exports.BIOMARKER_UNITS = _chunkMJ254F5Kcjs.BIOMARKER_UNITS; exports.BODY_FAT_ZONES = BODY_FAT_ZONES; exports.CAC_INDICATOR_CODES = _chunkNXOTXKVBcjs.CAC_INDICATOR_CODES; exports.CATEGORY_GROUPS = CATEGORY_GROUPS; exports.CATEGORY_SCREENING_INTERVALS = CATEGORY_SCREENING_INTERVALS; exports.DEXA_CATEGORIES = _chunkNXOTXKVBcjs.DEXA_CATEGORIES; exports.DEXA_INDICATOR_CODES = _chunkNXOTXKVBcjs.DEXA_INDICATOR_CODES; exports.LOINC_SYSTEM = _chunkOR67NJDZcjs.LOINC_SYSTEM; exports.MAX_FILE_SIZE = _chunkETZXOGABcjs.MAX_FILE_SIZE; exports.MAX_OBSERVATIONS = _chunkETZXOGABcjs.MAX_OBSERVATIONS; exports.T_SCORE_ZONES = T_SCORE_ZONES; exports.UNIT_TO_UCUM = _chunkMJ254F5Kcjs.UNIT_TO_UCUM; exports.ZONE_DEFS = ZONE_DEFS; exports.applyFallbackReferenceRanges = _chunkERALICUKcjs.applyFallbackReferenceRanges; exports.biomarkerRangeDefinitions = _chunkERALICUKcjs.biomarkerRangeDefinitions; exports.calculateNextScreeningDate = calculateNextScreeningDate; exports.cnsToFHIRIdentifier = cnsToFHIRIdentifier; exports.codeToLoinc = _chunkNXOTXKVBcjs.codeToLoinc; exports.convertUnit = _chunkMJ254F5Kcjs.convertUnit; exports.cpfToFHIRIdentifier = cpfToFHIRIdentifier; exports.defaultReferenceRanges = _chunkERALICUKcjs.defaultReferenceRanges; exports.extractObservationsFromBundle = _chunkETZXOGABcjs.extractObservationsFromBundle; exports.filterVisibleBiomarkers = _chunkNXOTXKVBcjs.filterVisibleBiomarkers; exports.findCodeByName = _chunkNXOTXKVBcjs.findCodeByName; exports.formatCNS = formatCNS; exports.formatCPF = formatCPF; exports.generateCacFullReference = _chunkNXOTXKVBcjs.generateCacFullReference; exports.generateDexaFullReference = _chunkNXOTXKVBcjs.generateDexaFullReference; exports.generateFilteredLLMReference = _chunkNXOTXKVBcjs.generateFilteredLLMReference; exports.generateLLMReference = _chunkNXOTXKVBcjs.generateLLMReference; exports.getAllCodes = _chunkNXOTXKVBcjs.getAllCodes; exports.getAllDefinitions = _chunkNXOTXKVBcjs.getAllDefinitions; exports.getAllLoincCodes = _chunkNXOTXKVBcjs.getAllLoincCodes; exports.getAllSearchPatterns = _chunkNXOTXKVBcjs.getAllSearchPatterns; exports.getBiomarkersByCategory = _chunkNXOTXKVBcjs.getBiomarkersByCategory; exports.getBiomarkersForCategories = _chunkNXOTXKVBcjs.getBiomarkersForCategories; exports.getCanonicalUnit = _chunkMJ254F5Kcjs.getCanonicalUnit; exports.getCategoriesByInterval = getCategoriesByInterval; exports.getCategoryGroup = getCategoryGroup; exports.getDaysUntilScreening = getDaysUntilScreening; exports.getDefaultUnit = _chunkMJ254F5Kcjs.getDefaultUnit; exports.getDefinitionByCode = _chunkNXOTXKVBcjs.getDefinitionByCode; exports.getDefinitionByLoinc = _chunkNXOTXKVBcjs.getDefinitionByLoinc; exports.getDefinitionsBySex = _chunkNXOTXKVBcjs.getDefinitionsBySex; exports.getDueCategories = getDueCategories; exports.getFallbackReferenceRange = _chunkERALICUKcjs.getFallbackReferenceRange; exports.getRangeDirection = _chunkERALICUKcjs.getRangeDirection; exports.getReferenceRange = _chunkERALICUKcjs.getReferenceRange; exports.getSIUnit = _chunkMJ254F5Kcjs.getSIUnit; exports.getScreeningInterval = getScreeningInterval; exports.getSexForCode = _chunkNXOTXKVBcjs.getSexForCode; exports.getVisibleDefinitions = _chunkNXOTXKVBcjs.getVisibleDefinitions; exports.interventionToFHIRMedicationStatement = interventionToFHIRMedicationStatement; exports.interventionToFHIRObservation = interventionToFHIRObservation; exports.interventionsToFHIRBundle = interventionsToFHIRBundle; exports.isBiomarkerVisible = _chunkNXOTXKVBcjs.isBiomarkerVisible; exports.isCacDocument = _chunkNXOTXKVBcjs.isCacDocument; exports.isDexaDocument = _chunkNXOTXKVBcjs.isDexaDocument; exports.isScreeningDue = isScreeningDue; exports.isValidCode = _chunkNXOTXKVBcjs.isValidCode; exports.isValidLoinc = _chunkNXOTXKVBcjs.isValidLoinc; exports.labObservationToFHIR = _chunkQJF5BZ3Jcjs.labObservationToFHIR; exports.labReportToFHIR = _chunkQJF5BZ3Jcjs.labReportToFHIR; exports.labResultToFHIRBundle = _chunkQJF5BZ3Jcjs.labResultToFHIRBundle; exports.listMappedSubcategories = listMappedSubcategories; exports.loincToCode = _chunkNXOTXKVBcjs.loincToCode; exports.mapFHIRObservationToInternal = _chunkETZXOGABcjs.mapFHIRObservationToInternal; exports.normalizeCode = _chunkNXOTXKVBcjs.normalizeCode; exports.plural = plural; exports.pluralCount = pluralCount; exports.pluralPhrase = pluralPhrase; exports.pluralPhraseCount = pluralPhraseCount; exports.processImportBundle = _chunkETZXOGABcjs.processImportBundle; exports.toBiomarkerTests = _chunkNXOTXKVBcjs.toBiomarkerTests; exports.unitToUCUM = _chunkMJ254F5Kcjs.unitToUCUM; exports.userProfileToFHIR = _chunkQJF5BZ3Jcjs.userProfileToFHIR; exports.validateCNS = validateCNS; exports.validateCPF = validateCPF; exports.validateFHIRDiagnosticReport = _chunk3ILBFLVQcjs.validateFHIRDiagnosticReport; exports.validateFHIRImportBundle = _chunk3ILBFLVQcjs.validateFHIRImportBundle; exports.validateFHIRObservation = _chunk3ILBFLVQcjs.validateFHIRObservation; exports.validateLoincNameMatch = _chunkNXOTXKVBcjs.validateLoincNameMatch;
695
701
  //# sourceMappingURL=index.cjs.map