@ovok/core 0.3.16 → 0.3.17
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/client/observation/methods/observationsToMeasurements.d.ts +8 -1
- package/dist/client/observation/methods/observationsToMeasurements.js +137 -28
- package/dist/client/observation/observation-bundle-utils.js +58 -7
- package/dist/conformance/capability-requirements.js +1 -1
- package/dist/hooks/observation-hooks.d.ts +4 -1
- package/dist/hooks/observation-hooks.js +2 -2
- package/package.json +1 -1
|
@@ -2,9 +2,16 @@ import { Observation } from "@medplum/fhirtypes";
|
|
|
2
2
|
import { BloodGlucoseMeasurement, BloodPressureMeasurement, BodyTemperatureMeasurement, BodyWeightMeasurement, EcgMeasurement, HeartRateMeasurement, HeartRateVariabilityMeasurement, Measurement, MeasurementTypeKey, PulseOximeterMeasurement, RespiratoryRateMeasurement, RestingHeartRateMeasurement, StepCountMeasurement, UrineAnalyzeMeasurement, Vo2MaxMeasurement, WalkingHeartRateAverageMeasurement } from "../../../types";
|
|
3
3
|
export type SupportedMeasurement = BloodGlucoseMeasurement | BloodPressureMeasurement | BodyTemperatureMeasurement | BodyWeightMeasurement | EcgMeasurement | HeartRateMeasurement | HeartRateVariabilityMeasurement | PulseOximeterMeasurement | RespiratoryRateMeasurement | RestingHeartRateMeasurement | StepCountMeasurement | UrineAnalyzeMeasurement | Vo2MaxMeasurement | WalkingHeartRateAverageMeasurement | Measurement;
|
|
4
4
|
type SupportedType = Exclude<MeasurementTypeKey, MeasurementTypeKey.symptomQuestionnaire>;
|
|
5
|
+
export type ObservationGrouping = "hasMember" | "time" | ((observation: Observation, index: number, observations: readonly Observation[]) => string);
|
|
6
|
+
export interface ObservationsToMeasurementsOptions {
|
|
7
|
+
/** How related Observation resources should be reconstructed into measurements. */
|
|
8
|
+
groupBy?: ObservationGrouping;
|
|
9
|
+
/** Maximum timestamp difference used by the time-based fallback. */
|
|
10
|
+
timeToleranceMs?: number;
|
|
11
|
+
}
|
|
5
12
|
export declare const observationCodesForTypes: (types: readonly SupportedType[]) => string;
|
|
6
13
|
/** Converts FHIR observations back into SDK measurements without patient/app assumptions. */
|
|
7
|
-
export declare const observationsToMeasurements: <T extends readonly SupportedType[]>(observations: readonly Observation[], types: T) => Array<Extract<SupportedMeasurement, {
|
|
14
|
+
export declare const observationsToMeasurements: <T extends readonly SupportedType[]>(observations: readonly Observation[], types: T, options?: ObservationsToMeasurementsOptions) => Array<Extract<SupportedMeasurement, {
|
|
8
15
|
measurementTypeKey: T[number];
|
|
9
16
|
}>>;
|
|
10
17
|
export {};
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.observationsToMeasurements = exports.observationCodesForTypes = void 0;
|
|
5
5
|
const types_1 = require("../../../types");
|
|
6
|
+
const DEFAULT_OBSERVATION_TIME_TOLERANCE_MS = 1000;
|
|
6
7
|
const codeOf = (observation) => {
|
|
7
8
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
8
9
|
return (_d = (_c = (_b = (_a = observation.code) === null || _a === void 0 ? void 0 : _a.coding) === null || _b === void 0 ? void 0 : _b.find((coding) => coding.system === "http://loinc.org")) === null || _c === void 0 ? void 0 : _c.code) !== null && _d !== void 0 ? _d : (_g = (_f = (_e = observation.code) === null || _e === void 0 ? void 0 : _e.coding) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.code;
|
|
@@ -50,28 +51,138 @@ const ecgGroupKey = (observation, observations) => {
|
|
|
50
51
|
});
|
|
51
52
|
return root ? groupKey(root) : groupKey(observation);
|
|
52
53
|
};
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const
|
|
54
|
+
const referenceKeys = (reference) => {
|
|
55
|
+
const id = reference.replace(/^urn:uuid:/, "").replace(/^Observation\//, "");
|
|
56
|
+
return [reference, id, `Observation/${id}`, `urn:uuid:${id}`];
|
|
57
|
+
};
|
|
58
|
+
const observationGroups = (observations) => {
|
|
59
|
+
const byReference = new Map();
|
|
60
|
+
observations.forEach((observation, index) => {
|
|
61
|
+
if (observation.id) {
|
|
62
|
+
referenceKeys(observation.id).forEach((key) => byReference.set(key, index));
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
const parent = observations.map((_, index) => index);
|
|
66
|
+
const find = (index) => {
|
|
67
|
+
if (parent[index] !== index) {
|
|
68
|
+
parent[index] = find(parent[index]);
|
|
69
|
+
}
|
|
70
|
+
return parent[index];
|
|
71
|
+
};
|
|
72
|
+
const union = (left, right) => {
|
|
73
|
+
const leftRoot = find(left);
|
|
74
|
+
const rightRoot = find(right);
|
|
75
|
+
if (leftRoot !== rightRoot) {
|
|
76
|
+
parent[rightRoot] = leftRoot;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const linked = new Set();
|
|
80
|
+
observations.forEach((observation, index) => {
|
|
59
81
|
var _a;
|
|
60
|
-
flattened.push(observation);
|
|
61
82
|
(_a = observation.hasMember) === null || _a === void 0 ? void 0 : _a.forEach((reference) => {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
83
|
+
const referenced = reference.reference
|
|
84
|
+
? referenceKeys(reference.reference)
|
|
85
|
+
.map((key) => byReference.get(key))
|
|
86
|
+
.find((candidate) => candidate !== undefined)
|
|
87
|
+
: undefined;
|
|
88
|
+
if (referenced !== undefined) {
|
|
89
|
+
linked.add(index);
|
|
90
|
+
linked.add(referenced);
|
|
91
|
+
union(index, referenced);
|
|
65
92
|
}
|
|
66
93
|
});
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
componentOf: new Map(observations.map((_, index) => [index, find(index)])),
|
|
97
|
+
linked,
|
|
67
98
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
99
|
+
};
|
|
100
|
+
const addToGroup = (groups, key, observation, index) => {
|
|
101
|
+
const group = groups.get(key);
|
|
102
|
+
if (group) {
|
|
103
|
+
group.observations.push(observation);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
groups.set(key, { firstIndex: index, observations: [observation] });
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const groupByTime = (observations, timeToleranceMs) => {
|
|
110
|
+
const groups = [];
|
|
111
|
+
observations.forEach((observation, index) => {
|
|
112
|
+
var _a;
|
|
113
|
+
const recordedAt = (_a = recordedAtOf(observation)) === null || _a === void 0 ? void 0 : _a.getTime();
|
|
114
|
+
const group = recordedAt === undefined
|
|
115
|
+
? undefined
|
|
116
|
+
: groups.find((candidate) => candidate.anchor !== undefined &&
|
|
117
|
+
Math.abs(candidate.anchor - recordedAt) <= timeToleranceMs);
|
|
118
|
+
if (group) {
|
|
119
|
+
group.observations.push(observation);
|
|
120
|
+
return;
|
|
72
121
|
}
|
|
122
|
+
groups.push({
|
|
123
|
+
firstIndex: index,
|
|
124
|
+
...(recordedAt !== undefined ? { anchor: recordedAt } : {}),
|
|
125
|
+
observations: [observation],
|
|
126
|
+
});
|
|
73
127
|
});
|
|
74
|
-
return
|
|
128
|
+
return groups;
|
|
129
|
+
};
|
|
130
|
+
const groupObservations = (observations, options, legacyKey) => {
|
|
131
|
+
var _a, _b;
|
|
132
|
+
const grouping = (_a = options.groupBy) !== null && _a !== void 0 ? _a : "hasMember";
|
|
133
|
+
const tolerance = Math.max(0, (_b = options.timeToleranceMs) !== null && _b !== void 0 ? _b : DEFAULT_OBSERVATION_TIME_TOLERANCE_MS);
|
|
134
|
+
if (grouping === "time") {
|
|
135
|
+
return groupByTime(observations, tolerance);
|
|
136
|
+
}
|
|
137
|
+
if (typeof grouping === "function") {
|
|
138
|
+
const groups = new Map();
|
|
139
|
+
observations.forEach((observation, index) => {
|
|
140
|
+
addToGroup(groups, grouping(observation, index, observations), observation, index);
|
|
141
|
+
});
|
|
142
|
+
return [...groups.values()].sort((left, right) => left.firstIndex - right.firstIndex);
|
|
143
|
+
}
|
|
144
|
+
const { componentOf, linked } = observationGroups(observations);
|
|
145
|
+
const componentSizes = new Map();
|
|
146
|
+
componentOf.forEach((root) => {
|
|
147
|
+
var _a;
|
|
148
|
+
componentSizes.set(root, ((_a = componentSizes.get(root)) !== null && _a !== void 0 ? _a : 0) + 1);
|
|
149
|
+
});
|
|
150
|
+
const groups = new Map();
|
|
151
|
+
const fallback = observations.filter((_, index) => {
|
|
152
|
+
var _a;
|
|
153
|
+
const root = componentOf.get(index);
|
|
154
|
+
return ((_a = componentSizes.get(root)) !== null && _a !== void 0 ? _a : 0) === 1;
|
|
155
|
+
});
|
|
156
|
+
observations.forEach((observation, index) => {
|
|
157
|
+
var _a;
|
|
158
|
+
const root = componentOf.get(index);
|
|
159
|
+
if (((_a = componentSizes.get(root)) !== null && _a !== void 0 ? _a : 0) > 1) {
|
|
160
|
+
addToGroup(groups, `member:${root}`, observation, index);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
if (fallback.length > 0) {
|
|
164
|
+
const fallbackIndexes = new Set(fallback.map((observation) => observations.indexOf(observation)));
|
|
165
|
+
const unlinked = observations.filter((_, index) => fallbackIndexes.has(index) && !linked.has(index));
|
|
166
|
+
const unresolved = observations.filter((_, index) => fallbackIndexes.has(index) && linked.has(index));
|
|
167
|
+
groupByTime(unlinked, tolerance).forEach((group) => {
|
|
168
|
+
const first = group.observations[0];
|
|
169
|
+
const firstIndex = observations.indexOf(first);
|
|
170
|
+
const key = legacyKey
|
|
171
|
+
? `legacy:${legacyKey(first, firstIndex)}`
|
|
172
|
+
: `time:${firstIndex}`;
|
|
173
|
+
addToGroup(groups, key, first, firstIndex);
|
|
174
|
+
group.observations.slice(1).forEach((observation) => {
|
|
175
|
+
const index = observations.indexOf(observation);
|
|
176
|
+
addToGroup(groups, key, observation, index);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
unresolved.forEach((observation) => {
|
|
180
|
+
var _a;
|
|
181
|
+
const index = observations.indexOf(observation);
|
|
182
|
+
addToGroup(groups, `unresolved:${(_a = observation.id) !== null && _a !== void 0 ? _a : index}`, observation, index);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
return [...groups.values()].sort((left, right) => left.firstIndex - right.firstIndex);
|
|
75
186
|
};
|
|
76
187
|
const firstValue = (observations, code) => observations.find((observation) => codeOf(observation) === code)
|
|
77
188
|
? valueOf(observations.find((observation) => codeOf(observation) === code))
|
|
@@ -82,7 +193,11 @@ const baseMeasurement = (measurementTypeKey, observation) => ({
|
|
|
82
193
|
});
|
|
83
194
|
const inverseGroup = (type, observations) => {
|
|
84
195
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
85
|
-
const first = observations
|
|
196
|
+
const first = [...observations].sort((left, right) => {
|
|
197
|
+
var _a, _b, _c, _d;
|
|
198
|
+
return ((_b = (_a = recordedAtOf(left)) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : Number.MAX_SAFE_INTEGER) -
|
|
199
|
+
((_d = (_c = recordedAtOf(right)) === null || _c === void 0 ? void 0 : _c.getTime()) !== null && _d !== void 0 ? _d : Number.MAX_SAFE_INTEGER);
|
|
200
|
+
})[0];
|
|
86
201
|
const measurement = baseMeasurement(type, first);
|
|
87
202
|
const value = (code) => firstValue(observations, code);
|
|
88
203
|
switch (type) {
|
|
@@ -225,22 +340,16 @@ const codesForType = {
|
|
|
225
340
|
const observationCodesForTypes = (types) => [...new Set(types.flatMap((type) => { var _a; return (_a = codesForType[type]) !== null && _a !== void 0 ? _a : []; }))].join(",");
|
|
226
341
|
exports.observationCodesForTypes = observationCodesForTypes;
|
|
227
342
|
/** Converts FHIR observations back into SDK measurements without patient/app assumptions. */
|
|
228
|
-
const observationsToMeasurements = (observations, types) => {
|
|
229
|
-
const source = flattenMembers(observations);
|
|
343
|
+
const observationsToMeasurements = (observations, types, options = {}) => {
|
|
230
344
|
const output = [];
|
|
231
345
|
types.forEach((type) => {
|
|
232
346
|
var _a;
|
|
233
347
|
const codes = (_a = codesForType[type]) !== null && _a !== void 0 ? _a : [];
|
|
234
|
-
const matching =
|
|
235
|
-
const groups =
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
? ecgGroupKey(observation, matching)
|
|
240
|
-
: (_b = (_a = recordedAtOf(observation)) === null || _a === void 0 ? void 0 : _a.toISOString()) !== null && _b !== void 0 ? _b : "unknown";
|
|
241
|
-
groups.set(key, [...((_c = groups.get(key)) !== null && _c !== void 0 ? _c : []), observation]);
|
|
242
|
-
});
|
|
243
|
-
groups.forEach((group) => output.push(inverseGroup(type, group)));
|
|
348
|
+
const matching = observations.filter((observation) => { var _a; return codes.includes((_a = codeOf(observation)) !== null && _a !== void 0 ? _a : ""); });
|
|
349
|
+
const groups = groupObservations(matching, options, type === types_1.MeasurementTypeKey.ecg
|
|
350
|
+
? (observation, index) => ecgGroupKey(observation, matching) || `ecg:${index}`
|
|
351
|
+
: undefined);
|
|
352
|
+
groups.forEach((group) => output.push(inverseGroup(type, group.observations)));
|
|
244
353
|
});
|
|
245
354
|
return output;
|
|
246
355
|
};
|
|
@@ -24,6 +24,34 @@ const linkObservationMembers = (observations) => {
|
|
|
24
24
|
});
|
|
25
25
|
};
|
|
26
26
|
exports.linkObservationMembers = linkObservationMembers;
|
|
27
|
+
const createdObservationReference = (response, index) => {
|
|
28
|
+
var _a, _b, _c, _d;
|
|
29
|
+
const entry = (_a = response.entry) === null || _a === void 0 ? void 0 : _a[index];
|
|
30
|
+
const id = ((_b = entry === null || entry === void 0 ? void 0 : entry.resource) === null || _b === void 0 ? void 0 : _b.resourceType) === "Observation"
|
|
31
|
+
? entry.resource.id
|
|
32
|
+
: undefined;
|
|
33
|
+
if (id) {
|
|
34
|
+
return `Observation/${id}`;
|
|
35
|
+
}
|
|
36
|
+
const location = (_d = (_c = entry === null || entry === void 0 ? void 0 : entry.response) === null || _c === void 0 ? void 0 : _c.location) === null || _d === void 0 ? void 0 : _d.split("?")[0];
|
|
37
|
+
const match = location === null || location === void 0 ? void 0 : location.match(/(?:^|\/)(Observation\/[^/]+)(?:\/_history\/[^/]+)?$/);
|
|
38
|
+
return match === null || match === void 0 ? void 0 : match[1];
|
|
39
|
+
};
|
|
40
|
+
const rewriteObservationReference = (entry, from, to) => {
|
|
41
|
+
var _a;
|
|
42
|
+
const resource = entry.resource;
|
|
43
|
+
if ((resource === null || resource === void 0 ? void 0 : resource.resourceType) !== "Observation" || !((_a = resource.hasMember) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
44
|
+
return entry;
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
...entry,
|
|
48
|
+
resource: {
|
|
49
|
+
...resource,
|
|
50
|
+
hasMember: resource.hasMember.map((reference) => reference.reference === from ? { ...reference, reference: to } : reference),
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
const rewriteObservationReferences = (entries, from, to) => entries.map((entry) => rewriteObservationReference(entry, from, to));
|
|
27
55
|
const splitObservationBundleEntries = (bundle) => {
|
|
28
56
|
var _a;
|
|
29
57
|
const entries = (_a = bundle.entry) !== null && _a !== void 0 ? _a : [];
|
|
@@ -50,26 +78,49 @@ const splitObservationBundleEntries = (bundle) => {
|
|
|
50
78
|
};
|
|
51
79
|
exports.splitObservationBundleEntries = splitObservationBundleEntries;
|
|
52
80
|
const executeObservationBundle = async (bundle, executeBatch) => {
|
|
53
|
-
var _a, _b, _c, _d;
|
|
81
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
54
82
|
const entries = (_a = bundle.entry) !== null && _a !== void 0 ? _a : [];
|
|
55
83
|
if (bundle.type === "transaction" &&
|
|
56
84
|
entries.length > exports.MAX_CONDITIONAL_OBSERVATION_ENTRIES) {
|
|
85
|
+
const rootReference = (_c = (_b = entries[0]) === null || _b === void 0 ? void 0 : _b.fullUrl) !== null && _c !== void 0 ? _c : (((_e = (_d = entries[0]) === null || _d === void 0 ? void 0 : _d.resource) === null || _e === void 0 ? void 0 : _e.resourceType) === "Observation"
|
|
86
|
+
? `urn:uuid:${(0, offline_1.stableMeasurementId)(entries[0].resource)}`
|
|
87
|
+
: undefined);
|
|
57
88
|
const transactionResponse = await (0, exports.executeObservationBundle)({ ...bundle, entry: entries.slice(0, 1) }, executeBatch);
|
|
58
|
-
const
|
|
89
|
+
const savedRootReference = rootReference
|
|
90
|
+
? createdObservationReference(transactionResponse, 0)
|
|
91
|
+
: undefined;
|
|
92
|
+
const batchResponse = await (0, exports.executeObservationBundle)({
|
|
93
|
+
...bundle,
|
|
94
|
+
type: "batch",
|
|
95
|
+
entry: savedRootReference
|
|
96
|
+
? rewriteObservationReferences(entries.slice(1), rootReference, savedRootReference)
|
|
97
|
+
: entries.slice(1),
|
|
98
|
+
}, executeBatch);
|
|
59
99
|
return {
|
|
60
100
|
resourceType: "Bundle",
|
|
61
101
|
type: "batch-response",
|
|
62
102
|
entry: [
|
|
63
|
-
...((
|
|
64
|
-
...((
|
|
103
|
+
...((_f = transactionResponse.entry) !== null && _f !== void 0 ? _f : []),
|
|
104
|
+
...((_g = batchResponse.entry) !== null && _g !== void 0 ? _g : []),
|
|
65
105
|
],
|
|
66
106
|
};
|
|
67
107
|
}
|
|
68
108
|
const chunks = (0, exports.splitObservationBundleEntries)(bundle);
|
|
69
109
|
if (chunks) {
|
|
70
110
|
const responses = [];
|
|
71
|
-
|
|
72
|
-
|
|
111
|
+
const rootReference = (_j = (_h = entries[0]) === null || _h === void 0 ? void 0 : _h.fullUrl) !== null && _j !== void 0 ? _j : (((_l = (_k = entries[0]) === null || _k === void 0 ? void 0 : _k.resource) === null || _l === void 0 ? void 0 : _l.resourceType) === "Observation"
|
|
112
|
+
? `urn:uuid:${(0, offline_1.stableMeasurementId)(entries[0].resource)}`
|
|
113
|
+
: undefined);
|
|
114
|
+
let savedRootReference;
|
|
115
|
+
for (const [index, entry] of chunks.entries()) {
|
|
116
|
+
const chunkEntries = index > 0 && rootReference && savedRootReference
|
|
117
|
+
? rewriteObservationReferences(entry, rootReference, savedRootReference)
|
|
118
|
+
: entry;
|
|
119
|
+
const response = await (0, exports.executeObservationBundle)({ ...bundle, entry: chunkEntries }, executeBatch);
|
|
120
|
+
if (index === 0 && rootReference) {
|
|
121
|
+
savedRootReference = createdObservationReference(response, 0);
|
|
122
|
+
}
|
|
123
|
+
responses.push(response);
|
|
73
124
|
}
|
|
74
125
|
return {
|
|
75
126
|
resourceType: "Bundle",
|
|
@@ -78,7 +129,7 @@ const executeObservationBundle = async (bundle, executeBatch) => {
|
|
|
78
129
|
};
|
|
79
130
|
}
|
|
80
131
|
const response = await executeBatch(bundle);
|
|
81
|
-
if ((
|
|
132
|
+
if ((_m = response.entry) === null || _m === void 0 ? void 0 : _m.some((entry) => {
|
|
82
133
|
var _a, _b;
|
|
83
134
|
const status = (_b = (_a = entry.response) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : "";
|
|
84
135
|
return status.startsWith("4") || status.startsWith("5");
|
|
@@ -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.
|
|
51
|
+
version: "0.3.17",
|
|
52
52
|
},
|
|
53
53
|
fhirVersion: "4.0.1",
|
|
54
54
|
format: ["json"],
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Observation } from "@medplum/fhirtypes";
|
|
2
|
+
import type { ObservationsToMeasurementsOptions } from "../client/observation/methods/observationsToMeasurements";
|
|
2
3
|
import { observationsToMeasurements, SupportedMeasurement } from "../client/observation/methods/observationsToMeasurements";
|
|
3
4
|
import { GenerateObservationBodyParams } from "../client/observation/types/generate-observation-body/GenerateObservationBodyParams";
|
|
4
5
|
import { OvokClient } from "../client/ovok-client";
|
|
@@ -12,10 +13,12 @@ export interface UseObservationsOptions<T extends readonly SupportedType[]> {
|
|
|
12
13
|
types: T;
|
|
13
14
|
period?: ObservationPeriod;
|
|
14
15
|
patientId?: string;
|
|
16
|
+
groupBy?: ObservationsToMeasurementsOptions["groupBy"];
|
|
17
|
+
timeToleranceMs?: number;
|
|
15
18
|
}
|
|
16
19
|
/** Plain inverse mapping for apps that already fetched their Observation resources. */
|
|
17
20
|
export { observationsToMeasurements };
|
|
18
|
-
export declare const useObservations: <T extends readonly SupportedType[]>({ types, period, patientId, }: UseObservationsOptions<T>) => {
|
|
21
|
+
export declare const useObservations: <T extends readonly SupportedType[]>({ types, period, patientId, groupBy, timeToleranceMs, }: UseObservationsOptions<T>) => {
|
|
19
22
|
measurements: Array<Extract<SupportedMeasurement, {
|
|
20
23
|
measurementTypeKey: T[number];
|
|
21
24
|
}>>;
|
|
@@ -41,7 +41,7 @@ const observationsToMeasurements_1 = require("../client/observation/methods/obse
|
|
|
41
41
|
Object.defineProperty(exports, "observationsToMeasurements", { enumerable: true, get: function () { return observationsToMeasurements_1.observationsToMeasurements; } });
|
|
42
42
|
const types_1 = require("../types");
|
|
43
43
|
const index_1 = require("./index");
|
|
44
|
-
const useObservations = ({ types, period, patientId, }) => {
|
|
44
|
+
const useObservations = ({ types, period, patientId, groupBy, timeToleranceMs, }) => {
|
|
45
45
|
var _a, _b, _c;
|
|
46
46
|
// A broad search is intentional: one measurement can expand into several
|
|
47
47
|
// observations, and the inverse mapper performs the type-specific grouping.
|
|
@@ -60,7 +60,7 @@ const useObservations = ({ types, period, patientId, }) => {
|
|
|
60
60
|
}), [codes, patientId, period === null || period === void 0 ? void 0 : period.end, period === null || period === void 0 ? void 0 : period.start]);
|
|
61
61
|
const [resources, loading, outcome] = (0, react_hooks_1.useSearchResources)("Observation", query);
|
|
62
62
|
const observations = resources !== null && resources !== void 0 ? resources : [];
|
|
63
|
-
const measurements = React.useMemo(() => (0, observationsToMeasurements_1.observationsToMeasurements)(observations, types), [observations, types]);
|
|
63
|
+
const measurements = React.useMemo(() => (0, observationsToMeasurements_1.observationsToMeasurements)(observations, types, { groupBy, timeToleranceMs }), [groupBy, observations, timeToleranceMs, types]);
|
|
64
64
|
return {
|
|
65
65
|
measurements,
|
|
66
66
|
loading,
|