@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.
- package/dist/biomarkers.cjs +2 -2
- package/dist/biomarkers.js +1 -1
- package/dist/{chunk-MTWOF55H.js → chunk-3KIJIRCI.js} +44 -2
- package/dist/chunk-3KIJIRCI.js.map +1 -0
- package/dist/chunk-A6HR4XDK.js +9 -0
- package/dist/chunk-A6HR4XDK.js.map +1 -0
- package/dist/{chunk-MMO356YH.cjs → chunk-ERALICUK.cjs} +48 -1
- package/dist/chunk-ERALICUK.cjs.map +1 -0
- package/dist/chunk-ETZXOGAB.cjs +165 -0
- package/dist/chunk-ETZXOGAB.cjs.map +1 -0
- package/dist/{chunk-Z5VH5QGC.cjs → chunk-NXOTXKVB.cjs} +44 -2
- package/dist/chunk-NXOTXKVB.cjs.map +1 -0
- package/dist/chunk-OR67NJDZ.cjs +9 -0
- package/dist/chunk-OR67NJDZ.cjs.map +1 -0
- package/dist/{chunk-J3QVVVVH.cjs → chunk-QJF5BZ3J.cjs} +20 -9
- package/dist/chunk-QJF5BZ3J.cjs.map +1 -0
- package/dist/{chunk-XTEKGGYQ.js → chunk-QULBXISC.js} +48 -1
- package/dist/chunk-QULBXISC.js.map +1 -0
- package/dist/{chunk-LCXTQE2B.js → chunk-SN5ZJHWS.js} +20 -9
- package/dist/chunk-SN5ZJHWS.js.map +1 -0
- package/dist/{chunk-EXG2IU2O.js → chunk-YYANW65U.js} +38 -26
- package/dist/chunk-YYANW65U.js.map +1 -0
- package/dist/cli.js +142 -31
- package/dist/converter.cjs +4 -3
- package/dist/converter.cjs.map +1 -1
- package/dist/converter.js +3 -2
- package/dist/importer.cjs +4 -3
- package/dist/importer.cjs.map +1 -1
- package/dist/importer.d.cts +2 -1
- package/dist/importer.d.ts +2 -1
- package/dist/importer.js +3 -2
- package/dist/index.cjs +12 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/reference-ranges.cjs +2 -2
- package/dist/reference-ranges.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-6HKQY6VO.cjs +0 -153
- package/dist/chunk-6HKQY6VO.cjs.map +0 -1
- package/dist/chunk-EXG2IU2O.js.map +0 -1
- package/dist/chunk-J3QVVVVH.cjs.map +0 -1
- package/dist/chunk-LCXTQE2B.js.map +0 -1
- package/dist/chunk-MMO356YH.cjs.map +0 -1
- package/dist/chunk-MTWOF55H.js.map +0 -1
- package/dist/chunk-XTEKGGYQ.js.map +0 -1
- package/dist/chunk-Z5VH5QGC.cjs.map +0 -1
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "./chunk-
|
|
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
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
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 =
|
|
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 =
|
|
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-
|
|
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
|
|
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)
|
|
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
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
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:
|
|
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
|
|
4179
|
-
|
|
4180
|
-
const
|
|
4181
|
-
|
|
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 =
|
|
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 =
|
|
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.
|
|
6603
|
+
process.stdout.write(`${"0.20.1"}
|
|
6493
6604
|
`);
|
|
6494
6605
|
return;
|
|
6495
6606
|
}
|
package/dist/converter.cjs
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
7
|
-
require('./chunk-
|
|
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 =
|
|
15
|
+
exports.labObservationToFHIR = _chunkQJF5BZ3Jcjs.labObservationToFHIR; exports.labReportToFHIR = _chunkQJF5BZ3Jcjs.labReportToFHIR; exports.labResultToFHIRBundle = _chunkQJF5BZ3Jcjs.labResultToFHIRBundle; exports.userProfileToFHIR = _chunkQJF5BZ3Jcjs.userProfileToFHIR;
|
|
15
16
|
//# sourceMappingURL=converter.cjs.map
|
package/dist/converter.cjs.map
CHANGED
|
@@ -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-
|
|
7
|
-
import "./chunk-
|
|
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
|
|
8
|
-
require('./chunk-
|
|
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 =
|
|
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
|
package/dist/importer.cjs.map
CHANGED
|
@@ -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"}
|
package/dist/importer.d.cts
CHANGED
|
@@ -13,7 +13,8 @@ interface ImportedObservation {
|
|
|
13
13
|
collectionDate: string;
|
|
14
14
|
flag: 'H' | 'L' | '';
|
|
15
15
|
isQualitative: boolean;
|
|
16
|
-
|
|
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.d.ts
CHANGED
|
@@ -13,7 +13,8 @@ interface ImportedObservation {
|
|
|
13
13
|
collectionDate: string;
|
|
14
14
|
flag: 'H' | 'L' | '';
|
|
15
15
|
isQualitative: boolean;
|
|
16
|
-
|
|
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-
|
|
8
|
-
import "./chunk-
|
|
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
|
|
6
|
+
var _chunkQJF5BZ3Jcjs = require('./chunk-QJF5BZ3J.cjs');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
var
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|