@ovok/core 0.3.21 → 0.3.23

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 (21) hide show
  1. package/dist/client/observation/methods/generateObservationBodiesByMeasurement.js +3 -2
  2. package/dist/client/observation/methods/observationsToMeasurements.d.ts +2 -2
  3. package/dist/client/observation/methods/observationsToMeasurements.js +84 -1
  4. package/dist/client/observation/services/creator.js +4 -0
  5. package/dist/client/observation/services/lipid-panel.d.ts +28 -0
  6. package/dist/client/observation/services/lipid-panel.js +134 -0
  7. package/dist/client/observation/services/respiratory-therapy.d.ts +28 -0
  8. package/dist/client/observation/services/respiratory-therapy.js +69 -0
  9. package/dist/client/observation/types/MeasurementTypeKey.d.ts +3 -1
  10. package/dist/client/observation/types/MeasurementTypeKey.js +2 -0
  11. package/dist/client/observation/types/ObservationCode.d.ts +12 -1
  12. package/dist/client/observation/types/ObservationCode.js +11 -0
  13. package/dist/client/observation/types/measurement/BloodPressureMeasurement.d.ts +2 -0
  14. package/dist/client/observation/types/measurement/LipidPanelMeasurement.d.ts +11 -0
  15. package/dist/client/observation/types/measurement/LipidPanelMeasurement.js +2 -0
  16. package/dist/client/observation/types/measurement/RespiratoryTherapyMeasurement.d.ts +12 -0
  17. package/dist/client/observation/types/measurement/RespiratoryTherapyMeasurement.js +2 -0
  18. package/dist/client/observation/types/measurement/index.d.ts +2 -0
  19. package/dist/client/observation/types/measurement/index.js +2 -0
  20. package/dist/conformance/capability-requirements.js +1 -1
  21. package/package.json +1 -1
@@ -58,8 +58,9 @@ async function generateObservationBodiesByMeasurement(params) {
58
58
  return observationBodies.filter(hasObservationValue).map(applyEffectiveDateTime);
59
59
  }
60
60
  const hasObservationValue = (observation) => {
61
- var _a, _b, _c, _d, _e;
61
+ var _a, _b, _c, _d, _e, _f;
62
62
  return ((_a = observation.valueQuantity) === null || _a === void 0 ? void 0 : _a.value) !== undefined ||
63
63
  Boolean((_b = observation.valueSampledData) === null || _b === void 0 ? void 0 : _b.data) ||
64
- Boolean((_e = (_d = (_c = observation.valueCodeableConcept) === null || _c === void 0 ? void 0 : _c.coding) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.code);
64
+ Boolean((_e = (_d = (_c = observation.valueCodeableConcept) === null || _c === void 0 ? void 0 : _c.coding) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.code) ||
65
+ Boolean((_f = observation.component) === null || _f === void 0 ? void 0 : _f.length);
65
66
  };
@@ -1,6 +1,6 @@
1
1
  import { Observation } from "@medplum/fhirtypes";
2
- import { BloodGlucoseMeasurement, BloodPressureMeasurement, BodyTemperatureMeasurement, BodyWeightMeasurement, EcgMeasurement, HeartRateMeasurement, HeartRateVariabilityMeasurement, Measurement, MeasurementTypeKey, PulseOximeterMeasurement, RespiratoryRateMeasurement, RestingHeartRateMeasurement, StepCountMeasurement, UrineAnalyzeMeasurement, Vo2MaxMeasurement, WalkingHeartRateAverageMeasurement } from "../../../types";
3
- export type SupportedMeasurement = BloodGlucoseMeasurement | BloodPressureMeasurement | BodyTemperatureMeasurement | BodyWeightMeasurement | EcgMeasurement | HeartRateMeasurement | HeartRateVariabilityMeasurement | PulseOximeterMeasurement | RespiratoryRateMeasurement | RestingHeartRateMeasurement | StepCountMeasurement | UrineAnalyzeMeasurement | Vo2MaxMeasurement | WalkingHeartRateAverageMeasurement | Measurement;
2
+ import { BloodGlucoseMeasurement, BloodPressureMeasurement, BodyTemperatureMeasurement, BodyWeightMeasurement, EcgMeasurement, HeartRateMeasurement, HeartRateVariabilityMeasurement, LipidPanelMeasurement, Measurement, MeasurementTypeKey, PulseOximeterMeasurement, RespiratoryRateMeasurement, RespiratoryTherapyMeasurement, RestingHeartRateMeasurement, StepCountMeasurement, UrineAnalyzeMeasurement, Vo2MaxMeasurement, WalkingHeartRateAverageMeasurement } from "../../../types";
3
+ export type SupportedMeasurement = BloodGlucoseMeasurement | BloodPressureMeasurement | BodyTemperatureMeasurement | BodyWeightMeasurement | EcgMeasurement | HeartRateMeasurement | HeartRateVariabilityMeasurement | LipidPanelMeasurement | PulseOximeterMeasurement | RespiratoryRateMeasurement | RespiratoryTherapyMeasurement | RestingHeartRateMeasurement | StepCountMeasurement | UrineAnalyzeMeasurement | Vo2MaxMeasurement | WalkingHeartRateAverageMeasurement | Measurement;
4
4
  type SupportedType = Exclude<MeasurementTypeKey, MeasurementTypeKey.symptomQuestionnaire>;
5
5
  export type ObservationGrouping = "hasMember" | "time" | ((observation: Observation, index: number, observations: readonly Observation[]) => string);
6
6
  export interface ObservationsToMeasurementsOptions {
@@ -187,6 +187,58 @@ const groupObservations = (observations, options, legacyKey) => {
187
187
  const firstValue = (observations, code) => observations.find((observation) => codeOf(observation) === code)
188
188
  ? valueOf(observations.find((observation) => codeOf(observation) === code))
189
189
  : undefined;
190
+ const LIPID_FIELDS = [
191
+ { key: "totalCholesterol", codes: [types_1.ObservationCode.TOTAL_CHOLESTEROL_MASS, types_1.ObservationCode.TOTAL_CHOLESTEROL_MOLAR] },
192
+ { key: "hdlCholesterol", codes: [types_1.ObservationCode.HDL_CHOLESTEROL_MASS, types_1.ObservationCode.HDL_CHOLESTEROL_MOLAR] },
193
+ { key: "ldlCholesterol", codes: [types_1.ObservationCode.LDL_CHOLESTEROL_MASS, types_1.ObservationCode.LDL_CHOLESTEROL_MOLAR] },
194
+ { key: "triglycerides", codes: [types_1.ObservationCode.TRIGLYCERIDES_MASS, types_1.ObservationCode.TRIGLYCERIDES_MOLAR] },
195
+ { key: "totalCholesterolHdlRatio", codes: [types_1.ObservationCode.TOTAL_CHOLESTEROL_HDL_RATIO] },
196
+ ];
197
+ const lipidValue = (observations, field) => {
198
+ var _a, _b, _c;
199
+ for (const observation of observations) {
200
+ const component = (_a = observation.component) === null || _a === void 0 ? void 0 : _a.find((candidate) => { var _a; return (_a = candidate.code.coding) === null || _a === void 0 ? void 0 : _a.some((coding) => field.codes.includes(coding.code)); });
201
+ const value = (_c = (_b = component === null || component === void 0 ? void 0 : component.valueQuantity) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : (field.codes.includes(codeOf(observation)) ? valueOf(observation) : undefined);
202
+ if (typeof value === "number") {
203
+ return value;
204
+ }
205
+ }
206
+ return undefined;
207
+ };
208
+ const lipidUnit = (observations) => {
209
+ var _a, _b, _c, _d, _e, _f;
210
+ for (const observation of observations) {
211
+ for (const component of (_a = observation.component) !== null && _a !== void 0 ? _a : []) {
212
+ const code = (_c = (_b = component.code.coding) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.code;
213
+ if ([types_1.ObservationCode.TOTAL_CHOLESTEROL_MOLAR, types_1.ObservationCode.HDL_CHOLESTEROL_MOLAR,
214
+ types_1.ObservationCode.LDL_CHOLESTEROL_MOLAR, types_1.ObservationCode.TRIGLYCERIDES_MOLAR].includes(code)) {
215
+ return "mmol/L";
216
+ }
217
+ if ([types_1.ObservationCode.TOTAL_CHOLESTEROL_MASS, types_1.ObservationCode.HDL_CHOLESTEROL_MASS,
218
+ types_1.ObservationCode.LDL_CHOLESTEROL_MASS, types_1.ObservationCode.TRIGLYCERIDES_MASS].includes(code)) {
219
+ return "mg/dL";
220
+ }
221
+ if (((_d = component.valueQuantity) === null || _d === void 0 ? void 0 : _d.unit) === "mmol/L" || ((_e = component.valueQuantity) === null || _e === void 0 ? void 0 : _e.unit) === "mg/dL") {
222
+ return component.valueQuantity.unit;
223
+ }
224
+ }
225
+ const code = codeOf(observation);
226
+ const unit = (_f = observation.valueQuantity) === null || _f === void 0 ? void 0 : _f.unit;
227
+ if (code && [types_1.ObservationCode.TOTAL_CHOLESTEROL_MOLAR, types_1.ObservationCode.HDL_CHOLESTEROL_MOLAR,
228
+ types_1.ObservationCode.LDL_CHOLESTEROL_MOLAR, types_1.ObservationCode.TRIGLYCERIDES_MOLAR].includes(code)) {
229
+ return "mmol/L";
230
+ }
231
+ if (code && [types_1.ObservationCode.TOTAL_CHOLESTEROL_MASS, types_1.ObservationCode.HDL_CHOLESTEROL_MASS,
232
+ types_1.ObservationCode.LDL_CHOLESTEROL_MASS, types_1.ObservationCode.TRIGLYCERIDES_MASS].includes(code)) {
233
+ return "mg/dL";
234
+ }
235
+ if (unit === "mmol/L" || unit === "mg/dL") {
236
+ return unit;
237
+ }
238
+ }
239
+ return "mg/dL";
240
+ };
241
+ const respiratoryComponents = (observations) => observations.flatMap((observation) => { var _a; return (_a = observation.component) !== null && _a !== void 0 ? _a : []; });
190
242
  const baseMeasurement = (measurementTypeKey, observation) => ({
191
243
  measurementTypeKey,
192
244
  ...(observation.id ? { id: observation.id } : {}),
@@ -316,6 +368,22 @@ const inverseGroup = (type, observations) => {
316
368
  }
317
369
  return result;
318
370
  }
371
+ case types_1.MeasurementTypeKey.lipidPanel:
372
+ return {
373
+ ...measurement,
374
+ measurementTypeKey: type,
375
+ unit: lipidUnit(observations),
376
+ ...Object.fromEntries(LIPID_FIELDS.flatMap(({ key, codes }) => {
377
+ const value = lipidValue(observations, { key, codes });
378
+ return value === undefined ? [] : [[key, value]];
379
+ })),
380
+ };
381
+ case types_1.MeasurementTypeKey.respiratoryTherapy:
382
+ return {
383
+ ...measurement,
384
+ measurementTypeKey: type,
385
+ components: respiratoryComponents(observations),
386
+ };
319
387
  default:
320
388
  return measurement;
321
389
  }
@@ -342,6 +410,11 @@ const codesForType = {
342
410
  types_1.ObservationCode.URIC_ACID,
343
411
  ...types_1.URINE_ANALYTE_DEFINITIONS.map((analyte) => analyte.code),
344
412
  ],
413
+ [types_1.MeasurementTypeKey.lipidPanel]: [
414
+ types_1.ObservationCode.LIPID_PANEL,
415
+ ...LIPID_FIELDS.flatMap(({ codes }) => codes),
416
+ ],
417
+ [types_1.MeasurementTypeKey.respiratoryTherapy]: [types_1.ObservationCode.RESPIRATORY_THERAPY],
345
418
  };
346
419
  const observationCodesForTypes = (types) => [...new Set(types.flatMap((type) => { var _a; return (_a = codesForType[type]) !== null && _a !== void 0 ? _a : []; }))].join(",");
347
420
  exports.observationCodesForTypes = observationCodesForTypes;
@@ -355,7 +428,17 @@ const observationsToMeasurements = (observations, types, options = {}) => {
355
428
  const groups = groupObservations(matching, options, type === types_1.MeasurementTypeKey.ecg
356
429
  ? (observation, index) => ecgGroupKey(observation, matching) || `ecg:${index}`
357
430
  : undefined);
358
- groups.forEach((group) => output.push(inverseGroup(type, group.observations)));
431
+ groups.forEach((group) => {
432
+ if (type === types_1.MeasurementTypeKey.lipidPanel &&
433
+ !LIPID_FIELDS.some((field) => lipidValue(group.observations, field) !== undefined)) {
434
+ return;
435
+ }
436
+ if (type === types_1.MeasurementTypeKey.respiratoryTherapy &&
437
+ respiratoryComponents(group.observations).length === 0) {
438
+ return;
439
+ }
440
+ output.push(inverseGroup(type, group.observations));
441
+ });
359
442
  });
360
443
  return output;
361
444
  };
@@ -10,7 +10,9 @@ const body_weight_1 = require("./body-weight");
10
10
  const ecg_1 = require("./ecg");
11
11
  const heart_rate_1 = require("./heart-rate");
12
12
  const heart_rate_variability_1 = require("./heart-rate-variability");
13
+ const lipid_panel_1 = require("./lipid-panel");
13
14
  const respiratory_rate_1 = require("./respiratory-rate");
15
+ const respiratory_therapy_1 = require("./respiratory-therapy");
14
16
  const resting_heart_rate_1 = require("./resting-heart-rate");
15
17
  const step_count_1 = require("./step-count");
16
18
  const uric_acid_service_1 = require("./uric-acid-service");
@@ -43,6 +45,8 @@ class ObservationServiceCreator {
43
45
  this.services.set(types_1.MeasurementTypeKey.vo2Max, new vo2_max_1.Vo2MaxService());
44
46
  this.services.set(types_1.MeasurementTypeKey.urineAnalysis, new uric_acid_service_1.UricAcidService());
45
47
  this.services.set(types_1.MeasurementTypeKey.uricAcid, new uric_acid_service_1.UricAcidService());
48
+ this.services.set(types_1.MeasurementTypeKey.lipidPanel, new lipid_panel_1.LipidPanelService());
49
+ this.services.set(types_1.MeasurementTypeKey.respiratoryTherapy, new respiratory_therapy_1.RespiratoryTherapyService());
46
50
  }
47
51
  getService(type) {
48
52
  const service = this.services.get(type);
@@ -0,0 +1,28 @@
1
+ import { Observation } from "@medplum/fhirtypes";
2
+ import { LipidPanelMeasurement, Measurement, MeasurementTypeKey, ObservationCode } from "../../../types";
3
+ import { RecordResult, RecordType } from "../types/generate-measurement/HealthConnectTypes";
4
+ import { Sample } from "../types/generate-measurement/Sample";
5
+ import { ObservationFragment } from "../types/generate-observation-body/ObservationFragment";
6
+ import { ObservationValue } from "../types/generate-observation-body/ObservationValue";
7
+ import { ObservationMetadata } from "../types/service/ObservationMetadata";
8
+ import { BaseObservationService } from "./base-observation-service";
9
+ export declare class LipidPanelService extends BaseObservationService<LipidPanelMeasurement> {
10
+ protected measurementTypeKey: MeasurementTypeKey;
11
+ protected measurementTypeName: string;
12
+ protected observationMetadata: ObservationMetadata<LipidPanelMeasurement>[];
13
+ generateObservationFragments(measurement: Measurement): ObservationFragment[];
14
+ getObservationCodes(): {
15
+ coding: {
16
+ code: ObservationCode;
17
+ display: string;
18
+ system: string;
19
+ }[];
20
+ }[];
21
+ getAdditionalProperties(measurement: Measurement): Partial<Observation>[];
22
+ generateValues(_measurement: Measurement): ObservationValue[];
23
+ getUnits(): string[];
24
+ getMeasurementDisplay(measurement: Measurement): string;
25
+ getObservationDisplay(observations: Observation[]): string | undefined;
26
+ convertSamplesToMeasurement(_samples: Sample[]): LipidPanelMeasurement;
27
+ convertRecordToMeasurement(_record: RecordResult<RecordType>): LipidPanelMeasurement;
28
+ }
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LipidPanelService = void 0;
4
+ const types_1 = require("../../../types");
5
+ const base_observation_service_1 = require("./base-observation-service");
6
+ const UCUM_SYSTEM = "http://unitsofmeasure.org";
7
+ const LOINC_SYSTEM = "http://loinc.org";
8
+ const COMPONENTS = [
9
+ {
10
+ key: "totalCholesterol",
11
+ display: "Total cholesterol",
12
+ massCode: types_1.ObservationCode.TOTAL_CHOLESTEROL_MASS,
13
+ molarCode: types_1.ObservationCode.TOTAL_CHOLESTEROL_MOLAR,
14
+ },
15
+ {
16
+ key: "hdlCholesterol",
17
+ display: "HDL cholesterol",
18
+ massCode: types_1.ObservationCode.HDL_CHOLESTEROL_MASS,
19
+ molarCode: types_1.ObservationCode.HDL_CHOLESTEROL_MOLAR,
20
+ },
21
+ {
22
+ key: "ldlCholesterol",
23
+ display: "LDL cholesterol",
24
+ massCode: types_1.ObservationCode.LDL_CHOLESTEROL_MASS,
25
+ molarCode: types_1.ObservationCode.LDL_CHOLESTEROL_MOLAR,
26
+ },
27
+ {
28
+ key: "triglycerides",
29
+ display: "Triglycerides",
30
+ massCode: types_1.ObservationCode.TRIGLYCERIDES_MASS,
31
+ molarCode: types_1.ObservationCode.TRIGLYCERIDES_MOLAR,
32
+ },
33
+ {
34
+ key: "totalCholesterolHdlRatio",
35
+ display: "Total cholesterol/HDL ratio",
36
+ massCode: types_1.ObservationCode.TOTAL_CHOLESTEROL_HDL_RATIO,
37
+ },
38
+ ];
39
+ const recordedAt = (measurement) => measurement.recordedAt instanceof Date &&
40
+ !Number.isNaN(measurement.recordedAt.getTime())
41
+ ? measurement.recordedAt.toISOString()
42
+ : new Date().toISOString();
43
+ class LipidPanelService extends base_observation_service_1.BaseObservationService {
44
+ constructor() {
45
+ super(...arguments);
46
+ this.measurementTypeKey = types_1.MeasurementTypeKey.lipidPanel;
47
+ this.measurementTypeName = "lipid panel";
48
+ this.observationMetadata = [];
49
+ }
50
+ generateObservationFragments(measurement) {
51
+ const lipidPanel = this.getCastedMeasurement(measurement);
52
+ const components = COMPONENTS.flatMap((item) => {
53
+ const value = lipidPanel[item.key];
54
+ if (typeof value !== "number" || !Number.isFinite(value)) {
55
+ return [];
56
+ }
57
+ const code = lipidPanel.unit === "mmol/L" ? item.molarCode : item.massCode;
58
+ if (!code) {
59
+ return [];
60
+ }
61
+ const unit = item.key === "totalCholesterolHdlRatio" ? "{ratio}" : lipidPanel.unit;
62
+ return [{
63
+ code: {
64
+ coding: [{ code, display: item.display, system: LOINC_SYSTEM }],
65
+ text: item.display,
66
+ },
67
+ valueQuantity: {
68
+ value,
69
+ unit,
70
+ code: unit,
71
+ system: UCUM_SYSTEM,
72
+ },
73
+ }];
74
+ });
75
+ if (components.length === 0) {
76
+ return [];
77
+ }
78
+ return [{
79
+ code: {
80
+ coding: [{
81
+ code: types_1.ObservationCode.LIPID_PANEL,
82
+ display: "Lipid panel - Serum or Plasma",
83
+ system: LOINC_SYSTEM,
84
+ }],
85
+ },
86
+ additionalProperties: {
87
+ effectiveDateTime: recordedAt(lipidPanel),
88
+ component: components,
89
+ },
90
+ }];
91
+ }
92
+ getObservationCodes() {
93
+ return [{
94
+ coding: [{
95
+ code: types_1.ObservationCode.LIPID_PANEL,
96
+ display: "Lipid panel - Serum or Plasma",
97
+ system: LOINC_SYSTEM,
98
+ }],
99
+ }];
100
+ }
101
+ getAdditionalProperties(measurement) {
102
+ return [{ effectiveDateTime: recordedAt(this.getCastedMeasurement(measurement)) }];
103
+ }
104
+ generateValues(_measurement) {
105
+ return [];
106
+ }
107
+ getUnits() {
108
+ return ["mg/dL", "mmol/L", "{ratio}"];
109
+ }
110
+ getMeasurementDisplay(measurement) {
111
+ const lipidPanel = this.getCastedMeasurement(measurement);
112
+ return COMPONENTS.flatMap(({ key, display }) => {
113
+ const value = lipidPanel[key];
114
+ return value === undefined ? [] : [`${display}: ${value}`];
115
+ }).join(", ");
116
+ }
117
+ getObservationDisplay(observations) {
118
+ const components = observations.flatMap((observation) => { var _a; return (_a = observation.component) !== null && _a !== void 0 ? _a : []; });
119
+ const values = components.flatMap((component) => {
120
+ var _a, _b, _c, _d;
121
+ const display = (_a = component.code.text) !== null && _a !== void 0 ? _a : (_c = (_b = component.code.coding) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.display;
122
+ const value = (_d = component.valueQuantity) === null || _d === void 0 ? void 0 : _d.value;
123
+ return display && typeof value === "number" ? [`${display}: ${value}`] : [];
124
+ });
125
+ return values.length ? values.join(", ") : undefined;
126
+ }
127
+ convertSamplesToMeasurement(_samples) {
128
+ throw new Error("Lipid panel samples are not supported.");
129
+ }
130
+ convertRecordToMeasurement(_record) {
131
+ throw new Error("Lipid panel Health Connect records are not supported.");
132
+ }
133
+ }
134
+ exports.LipidPanelService = LipidPanelService;
@@ -0,0 +1,28 @@
1
+ import { Observation } from "@medplum/fhirtypes";
2
+ import { Measurement, MeasurementTypeKey, ObservationCode, RespiratoryTherapyMeasurement } from "../../../types";
3
+ import { RecordResult, RecordType } from "../types/generate-measurement/HealthConnectTypes";
4
+ import { Sample } from "../types/generate-measurement/Sample";
5
+ import { ObservationFragment } from "../types/generate-observation-body/ObservationFragment";
6
+ import { ObservationValue } from "../types/generate-observation-body/ObservationValue";
7
+ import { ObservationMetadata } from "../types/service/ObservationMetadata";
8
+ import { BaseObservationService } from "./base-observation-service";
9
+ export declare class RespiratoryTherapyService extends BaseObservationService<RespiratoryTherapyMeasurement> {
10
+ protected measurementTypeKey: MeasurementTypeKey;
11
+ protected measurementTypeName: string;
12
+ protected observationMetadata: ObservationMetadata<RespiratoryTherapyMeasurement>[];
13
+ generateObservationFragments(measurement: Measurement): ObservationFragment[];
14
+ getObservationCodes(): {
15
+ coding: {
16
+ code: ObservationCode;
17
+ display: string;
18
+ system: string;
19
+ }[];
20
+ }[];
21
+ getAdditionalProperties(measurement: Measurement): Partial<Observation>[];
22
+ generateValues(_measurement: Measurement): ObservationValue[];
23
+ getUnits(): string[];
24
+ getMeasurementDisplay(measurement: Measurement): string;
25
+ getObservationDisplay(observations: Observation[]): string | undefined;
26
+ convertSamplesToMeasurement(_samples: Sample[]): RespiratoryTherapyMeasurement;
27
+ convertRecordToMeasurement(_record: RecordResult<RecordType>): RespiratoryTherapyMeasurement;
28
+ }
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RespiratoryTherapyService = void 0;
4
+ const types_1 = require("../../../types");
5
+ const base_observation_service_1 = require("./base-observation-service");
6
+ const RESPIRATORY_THERAPY_SYSTEM = "https://sdk.ovok.com/fhir/CodeSystem/measurement-type";
7
+ const recordedAt = (measurement) => measurement.recordedAt instanceof Date &&
8
+ !Number.isNaN(measurement.recordedAt.getTime())
9
+ ? measurement.recordedAt.toISOString()
10
+ : new Date().toISOString();
11
+ class RespiratoryTherapyService extends base_observation_service_1.BaseObservationService {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.measurementTypeKey = types_1.MeasurementTypeKey.respiratoryTherapy;
15
+ this.measurementTypeName = "respiratory therapy";
16
+ this.observationMetadata = [];
17
+ }
18
+ generateObservationFragments(measurement) {
19
+ const respiratoryTherapy = this.getCastedMeasurement(measurement);
20
+ if (respiratoryTherapy.components.length === 0) {
21
+ return [];
22
+ }
23
+ return [{
24
+ code: {
25
+ coding: [{
26
+ code: types_1.ObservationCode.RESPIRATORY_THERAPY,
27
+ display: "Respiratory therapy observation",
28
+ system: RESPIRATORY_THERAPY_SYSTEM,
29
+ }],
30
+ },
31
+ additionalProperties: {
32
+ effectiveDateTime: recordedAt(respiratoryTherapy),
33
+ component: respiratoryTherapy.components,
34
+ },
35
+ }];
36
+ }
37
+ getObservationCodes() {
38
+ return [{
39
+ coding: [{
40
+ code: types_1.ObservationCode.RESPIRATORY_THERAPY,
41
+ display: "Respiratory therapy observation",
42
+ system: RESPIRATORY_THERAPY_SYSTEM,
43
+ }],
44
+ }];
45
+ }
46
+ getAdditionalProperties(measurement) {
47
+ return [{ effectiveDateTime: recordedAt(this.getCastedMeasurement(measurement)) }];
48
+ }
49
+ generateValues(_measurement) {
50
+ return [];
51
+ }
52
+ getUnits() {
53
+ return [];
54
+ }
55
+ getMeasurementDisplay(measurement) {
56
+ return `${this.getCastedMeasurement(measurement).components.length} respiratory therapy metrics`;
57
+ }
58
+ getObservationDisplay(observations) {
59
+ const count = observations.reduce((total, observation) => { var _a, _b; return total + ((_b = (_a = observation.component) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0); }, 0);
60
+ return count ? `${count} respiratory therapy metrics` : undefined;
61
+ }
62
+ convertSamplesToMeasurement(_samples) {
63
+ throw new Error("Respiratory therapy samples are not supported.");
64
+ }
65
+ convertRecordToMeasurement(_record) {
66
+ throw new Error("Respiratory therapy Health Connect records are not supported.");
67
+ }
68
+ }
69
+ exports.RespiratoryTherapyService = RespiratoryTherapyService;
@@ -18,5 +18,7 @@ export declare enum MeasurementTypeKey {
18
18
  spirometryPanel = "spirometry-panel",
19
19
  stepCount = "step-count",
20
20
  restingHeartRate = "resting-heart-rate",
21
- walkingHeartRateAverage = "walking-heart-rate-average"
21
+ walkingHeartRateAverage = "walking-heart-rate-average",
22
+ lipidPanel = "lipid-panel",
23
+ respiratoryTherapy = "respiratory-therapy"
22
24
  }
@@ -23,4 +23,6 @@ var MeasurementTypeKey;
23
23
  MeasurementTypeKey["stepCount"] = "step-count";
24
24
  MeasurementTypeKey["restingHeartRate"] = "resting-heart-rate";
25
25
  MeasurementTypeKey["walkingHeartRateAverage"] = "walking-heart-rate-average";
26
+ MeasurementTypeKey["lipidPanel"] = "lipid-panel";
27
+ MeasurementTypeKey["respiratoryTherapy"] = "respiratory-therapy";
26
28
  })(MeasurementTypeKey || (exports.MeasurementTypeKey = MeasurementTypeKey = {}));
@@ -34,5 +34,16 @@ export declare enum ObservationCode {
34
34
  PHOTOGRAPHIC_IMAGE = "72170-4",
35
35
  PHENX_RESPIRATORY = "62628-3",
36
36
  RESTING_HEART_RATE = "40443-4",
37
- WALKING_HEART_RATE_AVERAGE = "40442-6"
37
+ WALKING_HEART_RATE_AVERAGE = "40442-6",
38
+ LIPID_PANEL = "100898-6",
39
+ TOTAL_CHOLESTEROL_MASS = "2093-3",
40
+ TOTAL_CHOLESTEROL_MOLAR = "14647-2",
41
+ HDL_CHOLESTEROL_MASS = "2085-9",
42
+ HDL_CHOLESTEROL_MOLAR = "14646-4",
43
+ LDL_CHOLESTEROL_MASS = "13457-7",
44
+ LDL_CHOLESTEROL_MOLAR = "39469-2",
45
+ TRIGLYCERIDES_MASS = "2571-8",
46
+ TRIGLYCERIDES_MOLAR = "14927-8",
47
+ TOTAL_CHOLESTEROL_HDL_RATIO = "9830-1",
48
+ RESPIRATORY_THERAPY = "respiratory-therapy"
38
49
  }
@@ -39,4 +39,15 @@ var ObservationCode;
39
39
  ObservationCode["PHENX_RESPIRATORY"] = "62628-3";
40
40
  ObservationCode["RESTING_HEART_RATE"] = "40443-4";
41
41
  ObservationCode["WALKING_HEART_RATE_AVERAGE"] = "40442-6";
42
+ ObservationCode["LIPID_PANEL"] = "100898-6";
43
+ ObservationCode["TOTAL_CHOLESTEROL_MASS"] = "2093-3";
44
+ ObservationCode["TOTAL_CHOLESTEROL_MOLAR"] = "14647-2";
45
+ ObservationCode["HDL_CHOLESTEROL_MASS"] = "2085-9";
46
+ ObservationCode["HDL_CHOLESTEROL_MOLAR"] = "14646-4";
47
+ ObservationCode["LDL_CHOLESTEROL_MASS"] = "13457-7";
48
+ ObservationCode["LDL_CHOLESTEROL_MOLAR"] = "39469-2";
49
+ ObservationCode["TRIGLYCERIDES_MASS"] = "2571-8";
50
+ ObservationCode["TRIGLYCERIDES_MOLAR"] = "14927-8";
51
+ ObservationCode["TOTAL_CHOLESTEROL_HDL_RATIO"] = "9830-1";
52
+ ObservationCode["RESPIRATORY_THERAPY"] = "respiratory-therapy";
42
53
  })(ObservationCode || (exports.ObservationCode = ObservationCode = {}));
@@ -8,6 +8,8 @@ export type BloodPressureMeasurement = Measurement & {
8
8
  /** Mean arterial pressure, in mmHg. Reported by the device rather than derived. */
9
9
  meanArterialPressure?: number;
10
10
  heartRate?: number;
11
+ /** User memory slot reported by a device, when available. */
12
+ memorySlot?: number;
11
13
  status?: BloodPressureStates;
12
14
  /** Whether the device detected an irregular heartbeat during the reading. */
13
15
  irregularHeartbeat?: boolean;
@@ -0,0 +1,11 @@
1
+ import { MeasurementTypeKey } from "../MeasurementTypeKey";
2
+ import { Measurement } from "./Measurement";
3
+ export type LipidPanelMeasurement = Measurement & {
4
+ measurementTypeKey: MeasurementTypeKey.lipidPanel;
5
+ totalCholesterol?: number;
6
+ hdlCholesterol?: number;
7
+ ldlCholesterol?: number;
8
+ triglycerides?: number;
9
+ totalCholesterolHdlRatio?: number;
10
+ unit: "mg/dL" | "mmol/L";
11
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,12 @@
1
+ import { ObservationComponent } from "@medplum/fhirtypes";
2
+ import { MeasurementTypeKey } from "../MeasurementTypeKey";
3
+ import { Measurement } from "./Measurement";
4
+ /**
5
+ * A coded set of respiratory-therapy observations. Keeping the values as FHIR components
6
+ * lets devices and consuming applications add their own metrics without Core assigning
7
+ * device-specific meaning to them.
8
+ */
9
+ export type RespiratoryTherapyMeasurement = Measurement & {
10
+ measurementTypeKey: MeasurementTypeKey.respiratoryTherapy;
11
+ components: ObservationComponent[];
12
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -15,3 +15,5 @@ export * from "./RespiratoryRateMeasurement";
15
15
  export * from "./RestingHeartRateMeasurement";
16
16
  export * from "./Vo2MaxMeasurement";
17
17
  export * from "./WalkingHeartRateAverageMeasurement";
18
+ export * from "./LipidPanelMeasurement";
19
+ export * from "./RespiratoryTherapyMeasurement";
@@ -31,3 +31,5 @@ __exportStar(require("./RespiratoryRateMeasurement"), exports);
31
31
  __exportStar(require("./RestingHeartRateMeasurement"), exports);
32
32
  __exportStar(require("./Vo2MaxMeasurement"), exports);
33
33
  __exportStar(require("./WalkingHeartRateAverageMeasurement"), exports);
34
+ __exportStar(require("./LipidPanelMeasurement"), exports);
35
+ __exportStar(require("./RespiratoryTherapyMeasurement"), exports);
@@ -48,7 +48,7 @@ exports.OVOK_CORE_REQUIREMENTS = {
48
48
  description: "The FHIR surface a server must provide for the @ovok/core client library's own methods to function.",
49
49
  software: {
50
50
  name: "@ovok/core",
51
- version: "0.3.21",
51
+ version: "0.3.23",
52
52
  },
53
53
  fhirVersion: "4.0.1",
54
54
  format: ["json"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ovok/core",
3
- "version": "0.3.21",
3
+ "version": "0.3.23",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",