@ovok/core 0.4.32 → 0.4.34
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/README.md +3 -7
- package/dist/client/auth/errors.d.ts +6 -0
- package/dist/client/auth/errors.js +12 -1
- package/dist/client/invites/methods.js +8 -2
- package/dist/client/offline/offline-measurement-queue.d.ts +6 -0
- package/dist/client/offline/offline-measurement-queue.js +40 -25
- package/dist/client/ovok-client.d.ts +9 -1
- package/dist/client/ovok-client.js +88 -22
- package/dist/client/patient/methods.d.ts +1 -3
- package/dist/client/patient/methods.js +0 -9
- package/dist/client/patient/types.d.ts +0 -13
- package/dist/client/patient-sharing/methods.js +5 -1
- package/dist/client/platform/methods.d.ts +1 -6
- package/dist/client/platform/methods.js +0 -12
- package/dist/client/platform/types.d.ts +0 -8
- package/dist/conformance/api-requirements.js +0 -5
- package/dist/conformance/capability-requirements.js +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +2 -4
- package/dist/hooks/invites-hooks.js +7 -1
- package/dist/hooks/notification-invalidation.d.ts +2 -0
- package/dist/hooks/patient-hooks.d.ts +1 -3
- package/dist/hooks/patient-hooks.js +1 -18
- package/dist/hooks/patient-sharing-hooks.js +17 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -157,12 +157,7 @@ const latest = await client.getPatientLatestObservations({
|
|
|
157
157
|
code: ["8867-4", "9279-1"],
|
|
158
158
|
max: 5,
|
|
159
159
|
});
|
|
160
|
-
const currentTelemetry = await client.
|
|
161
|
-
const history = await client.getPatientDeviceTelemetryHistory(deviceId, {
|
|
162
|
-
from: "2026-09-25T00:00:00.000Z",
|
|
163
|
-
to: "2026-09-26T00:00:00.000Z",
|
|
164
|
-
pageSize: 50,
|
|
165
|
-
});
|
|
160
|
+
const currentTelemetry = await client.getSlimDeviceTelemetry(deviceId);
|
|
166
161
|
const measurements = await client.listPatientMeasurementHistory({
|
|
167
162
|
patient: `Patient/${me.profile.id}`,
|
|
168
163
|
_sort: "-date",
|
|
@@ -179,7 +174,8 @@ const notifications = await client.listPatientNotifications({
|
|
|
179
174
|
```
|
|
180
175
|
|
|
181
176
|
These helpers use bearer-authenticated `/auth/me` and `/fhir/*` contracts and are additive to the
|
|
182
|
-
native observation and offline-measurement APIs.
|
|
177
|
+
native observation and offline-measurement APIs. Live device telemetry comes from the Slim routes
|
|
178
|
+
(`getSlimDeviceTelemetry`, `listSlimLiveTelemetry`). The returned resource lists are subject to the
|
|
183
179
|
patient's backend AccessPolicy. Device pairing/claiming and notification acknowledgement are not
|
|
184
180
|
invented here because `../ovok-core` does not currently expose patient-scoped contracts for them.
|
|
185
181
|
The exported `OVOK_CORE_API_REQUIREMENTS` lists ordinary HTTP routes, while
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
export declare const REGISTRATION_FAILED_MESSAGE = "Registration failed.";
|
|
2
|
+
export type OvokAccountErrorCode = "account_not_found" | "account_expired";
|
|
3
|
+
/** A safe, stable account error that does not include the account reference. */
|
|
4
|
+
export declare class OvokAccountError extends Error {
|
|
5
|
+
readonly code: OvokAccountErrorCode;
|
|
6
|
+
constructor(code: OvokAccountErrorCode);
|
|
7
|
+
}
|
|
2
8
|
/** Returns true when signup was refused because the address already has an account. */
|
|
3
9
|
export declare function isRegistrationFailed(error: unknown): boolean;
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.REGISTRATION_FAILED_MESSAGE = void 0;
|
|
3
|
+
exports.OvokAccountError = exports.REGISTRATION_FAILED_MESSAGE = void 0;
|
|
4
4
|
exports.isRegistrationFailed = isRegistrationFailed;
|
|
5
5
|
const ovok_error_1 = require("../errors/ovok-error");
|
|
6
6
|
exports.REGISTRATION_FAILED_MESSAGE = "Registration failed.";
|
|
7
|
+
/** A safe, stable account error that does not include the account reference. */
|
|
8
|
+
class OvokAccountError extends Error {
|
|
9
|
+
constructor(code) {
|
|
10
|
+
super(code === "account_not_found"
|
|
11
|
+
? "Saved account was not found."
|
|
12
|
+
: "This account's session has expired. Sign in again.");
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.name = "OvokAccountError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.OvokAccountError = OvokAccountError;
|
|
7
18
|
/** Returns true when signup was refused because the address already has an account. */
|
|
8
19
|
function isRegistrationFailed(error) {
|
|
9
20
|
const details = (0, ovok_error_1.readOvokError)(error);
|
|
@@ -21,10 +21,16 @@ function acceptInvite(body, requestOptions) {
|
|
|
21
21
|
var _a;
|
|
22
22
|
const resourceType = (_a = this.getProfile()) === null || _a === void 0 ? void 0 : _a.resourceType;
|
|
23
23
|
if (resourceType === "Practitioner") {
|
|
24
|
-
return this.acceptPractitionerInvite(body, ...(requestOptions === undefined ? [] : [requestOptions]))
|
|
24
|
+
return this.acceptPractitionerInvite(body, ...(requestOptions === undefined ? [] : [requestOptions])).then((result) => {
|
|
25
|
+
this.invalidateUrl("/v1/patient-sharing/shares");
|
|
26
|
+
return result;
|
|
27
|
+
});
|
|
25
28
|
}
|
|
26
29
|
if (resourceType === "Patient") {
|
|
27
|
-
return this.acceptPatientInvite(body, ...(requestOptions === undefined ? [] : [requestOptions]))
|
|
30
|
+
return this.acceptPatientInvite(body, ...(requestOptions === undefined ? [] : [requestOptions])).then((result) => {
|
|
31
|
+
this.invalidateUrl("/v1/patient-sharing/shares");
|
|
32
|
+
return result;
|
|
33
|
+
});
|
|
28
34
|
}
|
|
29
35
|
throw new Error("Accepting an invite requires a signed-in Patient or Practitioner profile.");
|
|
30
36
|
}
|
|
@@ -22,6 +22,12 @@ export type OfflineMeasurementFlushResult = {
|
|
|
22
22
|
queued: number;
|
|
23
23
|
exhausted: number;
|
|
24
24
|
responses: Record<string, Bundle>;
|
|
25
|
+
failures: Record<string, OfflineMeasurementFailure>;
|
|
26
|
+
};
|
|
27
|
+
export type OfflineMeasurementFailure = {
|
|
28
|
+
name: string;
|
|
29
|
+
code?: string;
|
|
30
|
+
status?: number;
|
|
25
31
|
};
|
|
26
32
|
type MeasurementTransport = (bundle: Bundle, requestOptions?: MedplumRequestOptions) => Promise<Bundle>;
|
|
27
33
|
declare const stableMeasurementId: (observation: Observation) => string;
|
|
@@ -81,29 +81,32 @@ class OfflineMeasurementQueue {
|
|
|
81
81
|
this.storage = storage;
|
|
82
82
|
this.transport = transport;
|
|
83
83
|
this.operation = Promise.resolve();
|
|
84
|
-
this.enqueueAndFlush = (observations, requestOptions) =>
|
|
85
|
-
var _a
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
84
|
+
this.enqueueAndFlush = (observations, requestOptions) => {
|
|
85
|
+
var _a;
|
|
86
|
+
const ownerKey = (_a = this.getOwnerKey) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
87
|
+
return this.runExclusive(async () => {
|
|
88
|
+
var _a, _b;
|
|
89
|
+
await ((_b = (_a = this.storage).getInitPromise) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
90
|
+
const queue = this.readQueue();
|
|
91
|
+
const entries = observations.map(entryForObservation);
|
|
92
|
+
if (this.getOwnerKey && !ownerKey) {
|
|
93
|
+
throw new Error("Offline measurements require an active account to prevent cross-account delivery.");
|
|
94
|
+
}
|
|
95
|
+
const id = stableValueId({ ownerKey, entries });
|
|
96
|
+
if (!queue.some((item) => item.id === id)) {
|
|
97
|
+
queue.push({
|
|
98
|
+
id,
|
|
99
|
+
ownerKey,
|
|
100
|
+
queuedAt: new Date().toISOString(),
|
|
101
|
+
attempt: 0,
|
|
102
|
+
nextAttemptAt: 0,
|
|
103
|
+
entries,
|
|
104
|
+
});
|
|
105
|
+
this.writeQueue(queue);
|
|
106
|
+
}
|
|
107
|
+
return { id, flush: await this.flushQueue(queue, {}, ...(requestOptions === undefined ? [] : [requestOptions])) };
|
|
108
|
+
});
|
|
109
|
+
};
|
|
107
110
|
this.flush = (options = {}, requestOptions) => this.runExclusive(async () => {
|
|
108
111
|
var _a, _b;
|
|
109
112
|
await ((_b = (_a = this.storage).getInitPromise) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
@@ -142,11 +145,14 @@ class OfflineMeasurementQueue {
|
|
|
142
145
|
queued: 0,
|
|
143
146
|
exhausted: 0,
|
|
144
147
|
responses: {},
|
|
148
|
+
failures: {},
|
|
145
149
|
};
|
|
146
150
|
const now = Date.now();
|
|
147
|
-
const ownerKey = (_a = this.getOwnerKey) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
148
151
|
let changed = false;
|
|
149
152
|
for (const item of [...queue]) {
|
|
153
|
+
if (item.lastFailure) {
|
|
154
|
+
result.failures[item.id] = item.lastFailure;
|
|
155
|
+
}
|
|
150
156
|
if (item.exhausted && options.resetExhausted) {
|
|
151
157
|
item.attempt = 0;
|
|
152
158
|
item.exhausted = false;
|
|
@@ -163,6 +169,7 @@ class OfflineMeasurementQueue {
|
|
|
163
169
|
}
|
|
164
170
|
continue;
|
|
165
171
|
}
|
|
172
|
+
const ownerKey = (_a = this.getOwnerKey) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
166
173
|
if (this.getOwnerKey && (!ownerKey || item.ownerKey !== ownerKey)) {
|
|
167
174
|
result.queued++;
|
|
168
175
|
continue;
|
|
@@ -183,7 +190,7 @@ class OfflineMeasurementQueue {
|
|
|
183
190
|
result.responses[item.id] = response;
|
|
184
191
|
changed = true;
|
|
185
192
|
}
|
|
186
|
-
catch (
|
|
193
|
+
catch (error) {
|
|
187
194
|
item.attempt = attempt;
|
|
188
195
|
item.exhausted = attempt >= this.maxRetries;
|
|
189
196
|
item.nextAttemptAt = item.exhausted
|
|
@@ -191,6 +198,14 @@ class OfflineMeasurementQueue {
|
|
|
191
198
|
: Date.now() +
|
|
192
199
|
Math.min(this.maxRetryBackoffMs, this.retryBackoffMs * 2 ** (attempt - 1));
|
|
193
200
|
changed = true;
|
|
201
|
+
const failure = error;
|
|
202
|
+
const lastFailure = {
|
|
203
|
+
name: typeof (failure === null || failure === void 0 ? void 0 : failure.name) === "string" ? failure.name : "Error",
|
|
204
|
+
...(typeof (failure === null || failure === void 0 ? void 0 : failure.code) === "string" ? { code: failure.code } : {}),
|
|
205
|
+
...(typeof (failure === null || failure === void 0 ? void 0 : failure.status) === "number" ? { status: failure.status } : {}),
|
|
206
|
+
};
|
|
207
|
+
item.lastFailure = lastFailure;
|
|
208
|
+
result.failures[item.id] = lastFailure;
|
|
194
209
|
if (item.exhausted) {
|
|
195
210
|
result.exhausted++;
|
|
196
211
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IClientStorage, LoginState, MedplumClient, MedplumClientOptions, MedplumRequestOptions, SubscriptionManager } from "@medplum/core";
|
|
1
|
+
import { IClientStorage, LoginState, MedplumClient, MedplumClientOptions, MedplumRequestOptions, ReadablePromise, SubscriptionManager } from "@medplum/core";
|
|
2
2
|
import { Bundle, CapabilityStatement, Observation } from "@medplum/fhirtypes";
|
|
3
3
|
import { OvokPublicApiEndpoint } from "../conformance/capability";
|
|
4
4
|
import * as aiFhirMethods from "./ai-fhir/methods";
|
|
@@ -50,18 +50,25 @@ export type OvokClientOptions = Omit<MedplumClientOptions, "onUnauthenticated">
|
|
|
50
50
|
socialLoginClientId?: string;
|
|
51
51
|
requestTimeoutMs?: number;
|
|
52
52
|
offlineQueue?: OfflineMeasurementQueueOptions;
|
|
53
|
+
/** Keep the saved login when a refresh cannot reach the server. */
|
|
54
|
+
keepSessionOnRefreshUnavailable?: boolean;
|
|
53
55
|
};
|
|
54
56
|
export declare class OvokClient extends MedplumClient {
|
|
55
57
|
protected socialLoginClientId: string;
|
|
56
58
|
clientStorage: IClientStorage | undefined;
|
|
57
59
|
private readonly hasExplicitStorageAdapter;
|
|
58
60
|
private readonly offlineQueueOptions;
|
|
61
|
+
private readonly clientOptions;
|
|
62
|
+
private readonly keepSessionOnRefreshUnavailable;
|
|
63
|
+
private readonly refreshState;
|
|
59
64
|
private offlineMeasurementQueue;
|
|
60
65
|
/**
|
|
61
66
|
* @param config - The configuration for the client.
|
|
62
67
|
* @param config.socialLoginClientId - The social login client id to use for the client.
|
|
63
68
|
*/
|
|
64
69
|
constructor(config: OvokClientOptions);
|
|
70
|
+
get<T = unknown>(url: URL | string, options?: MedplumRequestOptions): ReadablePromise<T>;
|
|
71
|
+
refreshIfExpired(gracePeriod?: number): Promise<void>;
|
|
65
72
|
post<T = unknown>(url: URL | string, body?: unknown, contentType?: string, options?: MedplumRequestOptions): Promise<T>;
|
|
66
73
|
/** Lists saved accounts without exposing their access or refresh tokens. */
|
|
67
74
|
getSavedAccounts(): OvokSavedAccount[];
|
|
@@ -96,6 +103,7 @@ export declare class OvokClient extends MedplumClient {
|
|
|
96
103
|
clear(): void;
|
|
97
104
|
private getLogin;
|
|
98
105
|
private getExpiredAccountIds;
|
|
106
|
+
private createAccountSessionClient;
|
|
99
107
|
private setAccountExpired;
|
|
100
108
|
private removeSavedAccount;
|
|
101
109
|
private syncSavedAccountProfile;
|
|
@@ -39,6 +39,7 @@ const core_1 = require("@medplum/core");
|
|
|
39
39
|
const capability_1 = require("../conformance/capability");
|
|
40
40
|
const aiFhirMethods = __importStar(require("./ai-fhir/methods"));
|
|
41
41
|
const account_storage_1 = require("./auth/account-storage");
|
|
42
|
+
const errors_1 = require("./auth/errors");
|
|
42
43
|
const authMethods = __importStar(require("./auth/methods"));
|
|
43
44
|
const botMethods = __importStar(require("./bot/methods"));
|
|
44
45
|
const changeHistoryMethods = __importStar(require("./change-history/methods"));
|
|
@@ -59,7 +60,7 @@ const patientMethods = __importStar(require("./patient/methods"));
|
|
|
59
60
|
const patientSharingMethods = __importStar(require("./patient-sharing/methods"));
|
|
60
61
|
const platformMethods = __importStar(require("./platform/methods"));
|
|
61
62
|
const questionnaireResponseMethods = __importStar(require("./questionnaire-response/methods"));
|
|
62
|
-
const
|
|
63
|
+
const errors_2 = require("./signals/errors");
|
|
63
64
|
const signalsMethods = __importStar(require("./signals/methods"));
|
|
64
65
|
const slimMethods = __importStar(require("./slim/methods"));
|
|
65
66
|
exports.MAX_CONDITIONAL_OBSERVATION_ENTRIES = 8;
|
|
@@ -217,6 +218,7 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
217
218
|
let clearActiveLogin = () => undefined;
|
|
218
219
|
let terminalRefreshToken;
|
|
219
220
|
let terminalRefreshError;
|
|
221
|
+
const refreshState = { unavailable: false };
|
|
220
222
|
const isTokenRefresh = (url, options) => new URL(url, normalizedBaseUrl).href === tokenUrl &&
|
|
221
223
|
(options === null || options === void 0 ? void 0 : options.method) === "POST" &&
|
|
222
224
|
typeof options.body === "string" &&
|
|
@@ -338,6 +340,9 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
338
340
|
const response = await fetchOnce(url, options);
|
|
339
341
|
if (isTemporaryRefreshFailure(response.status)) {
|
|
340
342
|
void ((_a = response.body) === null || _a === void 0 ? void 0 : _a.cancel().catch(() => undefined));
|
|
343
|
+
if (config.keepSessionOnRefreshUnavailable) {
|
|
344
|
+
refreshState.unavailable = true;
|
|
345
|
+
}
|
|
341
346
|
throw refreshUnavailableError(response);
|
|
342
347
|
}
|
|
343
348
|
return response;
|
|
@@ -355,6 +360,11 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
355
360
|
if ((signal === null || signal === void 0 ? void 0 : signal.aborted) || !isNetworkError(error)) {
|
|
356
361
|
throw error;
|
|
357
362
|
}
|
|
363
|
+
if (config.keepSessionOnRefreshUnavailable) {
|
|
364
|
+
refreshState.unavailable = true;
|
|
365
|
+
lastNetworkError = error;
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
358
368
|
if (Date.now() >= expiresAt) {
|
|
359
369
|
lastNetworkError = error;
|
|
360
370
|
break;
|
|
@@ -369,6 +379,10 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
369
379
|
if (!isTemporaryRefreshFailure(lastResponse.status)) {
|
|
370
380
|
return lastResponse;
|
|
371
381
|
}
|
|
382
|
+
if (config.keepSessionOnRefreshUnavailable) {
|
|
383
|
+
refreshState.unavailable = true;
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
372
386
|
const remainingMs = expiresAt - Date.now();
|
|
373
387
|
if (remainingMs <= 0) {
|
|
374
388
|
break;
|
|
@@ -388,6 +402,13 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
388
402
|
type: "refresh-unavailable",
|
|
389
403
|
...(status === undefined ? {} : { status }),
|
|
390
404
|
};
|
|
405
|
+
if (config.keepSessionOnRefreshUnavailable) {
|
|
406
|
+
refreshState.unavailable = true;
|
|
407
|
+
if (lastResponse) {
|
|
408
|
+
return lastResponse;
|
|
409
|
+
}
|
|
410
|
+
throw lastNetworkError !== null && lastNetworkError !== void 0 ? lastNetworkError : refreshUnavailableError(undefined);
|
|
411
|
+
}
|
|
391
412
|
unauthenticatedReason = reason;
|
|
392
413
|
markActiveAccountExpired();
|
|
393
414
|
if (lastResponse) {
|
|
@@ -405,6 +426,9 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
405
426
|
storage,
|
|
406
427
|
onUnauthenticated: () => {
|
|
407
428
|
var _a;
|
|
429
|
+
if (refreshState.unavailable) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
408
432
|
const reason = unauthenticatedReason !== null && unauthenticatedReason !== void 0 ? unauthenticatedReason : {
|
|
409
433
|
type: "request-unauthorized",
|
|
410
434
|
status: 401,
|
|
@@ -417,6 +441,9 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
417
441
|
this.socialLoginClientId = "";
|
|
418
442
|
clearActiveLogin = this.clearActiveLogin.bind(this);
|
|
419
443
|
this.hasExplicitStorageAdapter = config.storage !== undefined;
|
|
444
|
+
this.clientOptions = config;
|
|
445
|
+
this.keepSessionOnRefreshUnavailable = config.keepSessionOnRefreshUnavailable === true;
|
|
446
|
+
this.refreshState = refreshState;
|
|
420
447
|
this.socialLoginClientId = (_e = config.socialLoginClientId) !== null && _e !== void 0 ? _e : "";
|
|
421
448
|
this.addEventListener("profileRefreshed", () => this.syncSavedAccountProfile());
|
|
422
449
|
this.bindMethods(authMethods);
|
|
@@ -437,14 +464,46 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
437
464
|
this.bindMethods(patientMethods);
|
|
438
465
|
this.bindMethods(patientSharingMethods);
|
|
439
466
|
this.bindMethods(signalsMethods, (error) => {
|
|
440
|
-
const mapped = (0,
|
|
467
|
+
const mapped = (0, errors_2.mapSignalsError)((0, rate_limit_error_1.mapRateLimitError)(error), {
|
|
441
468
|
signalsRequest: true,
|
|
442
469
|
});
|
|
443
|
-
return (0,
|
|
470
|
+
return (0, errors_2.isSignalsError)(mapped) ? mapped : (0, ovok_error_1.mapOvokApiError)(mapped);
|
|
444
471
|
});
|
|
445
472
|
this.clientStorage = storage;
|
|
446
473
|
this.offlineQueueOptions = (_f = config.offlineQueue) !== null && _f !== void 0 ? _f : {};
|
|
447
474
|
}
|
|
475
|
+
get(url, options) {
|
|
476
|
+
const request = super.get(url, options);
|
|
477
|
+
void request.catch(() => this.invalidateUrl(url));
|
|
478
|
+
return request;
|
|
479
|
+
}
|
|
480
|
+
async refreshIfExpired(gracePeriod) {
|
|
481
|
+
var _a;
|
|
482
|
+
const activeLogin = this.getActiveLogin();
|
|
483
|
+
const accessToken = this.getAccessToken();
|
|
484
|
+
const expiresAt = accessToken ? (0, core_1.tryGetJwtExpiration)(accessToken) : undefined;
|
|
485
|
+
try {
|
|
486
|
+
await super.refreshIfExpired(gracePeriod);
|
|
487
|
+
}
|
|
488
|
+
catch (error) {
|
|
489
|
+
const activeAccount = this.getSavedAccounts().find((account) => { var _a; return account.id === ((_a = activeLogin === null || activeLogin === void 0 ? void 0 : activeLogin.profile) === null || _a === void 0 ? void 0 : _a.reference); });
|
|
490
|
+
if (this.keepSessionOnRefreshUnavailable &&
|
|
491
|
+
this.refreshState.unavailable &&
|
|
492
|
+
activeLogin &&
|
|
493
|
+
accessToken &&
|
|
494
|
+
!(activeAccount === null || activeAccount === void 0 ? void 0 : activeAccount.expired) &&
|
|
495
|
+
expiresAt !== undefined &&
|
|
496
|
+
expiresAt > Date.now()) {
|
|
497
|
+
(_a = this.clientStorage) === null || _a === void 0 ? void 0 : _a.setObject("activeLogin", activeLogin);
|
|
498
|
+
this.setAccessToken(accessToken, activeLogin.refreshToken);
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
throw error;
|
|
502
|
+
}
|
|
503
|
+
finally {
|
|
504
|
+
this.refreshState.unavailable = false;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
448
507
|
post(url, body, contentType, options) {
|
|
449
508
|
const pathname = new URL(url.toString(), this.getBaseUrl()).pathname;
|
|
450
509
|
if (!isRetrySafePost(pathname)) {
|
|
@@ -476,10 +535,10 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
476
535
|
var _a, _b;
|
|
477
536
|
const login = this.getLogin(accountId);
|
|
478
537
|
if (!login) {
|
|
479
|
-
throw new
|
|
538
|
+
throw new errors_1.OvokAccountError("account_not_found");
|
|
480
539
|
}
|
|
481
540
|
if (this.getExpiredAccountIds().includes(accountId)) {
|
|
482
|
-
throw new
|
|
541
|
+
throw new errors_1.OvokAccountError("account_expired");
|
|
483
542
|
}
|
|
484
543
|
const previousLogin = this.getActiveLogin();
|
|
485
544
|
try {
|
|
@@ -507,32 +566,25 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
507
566
|
var _a;
|
|
508
567
|
const login = this.getLogin(accountId);
|
|
509
568
|
if (!login) {
|
|
510
|
-
throw new
|
|
569
|
+
throw new errors_1.OvokAccountError("account_not_found");
|
|
511
570
|
}
|
|
512
571
|
const previousLogin = this.getActiveLogin();
|
|
513
572
|
const previousAccountId = (_a = previousLogin === null || previousLogin === void 0 ? void 0 : previousLogin.profile) === null || _a === void 0 ? void 0 : _a.reference;
|
|
573
|
+
const wasActive = previousAccountId === accountId;
|
|
574
|
+
const sessionClient = this.createAccountSessionClient(login);
|
|
514
575
|
try {
|
|
515
|
-
await
|
|
516
|
-
await this.delete("auth/session/current", ...(requestOptions === undefined ? [] : [requestOptions]));
|
|
576
|
+
await sessionClient.delete("auth/session/current", ...(requestOptions === undefined ? [] : [requestOptions]));
|
|
517
577
|
}
|
|
518
578
|
catch (error) {
|
|
519
|
-
if (
|
|
520
|
-
|
|
521
|
-
if (previousLogin && previousAccountId && previousAccountId !== accountId) {
|
|
522
|
-
await this.restoreActiveLogin(previousLogin);
|
|
523
|
-
}
|
|
524
|
-
else {
|
|
525
|
-
this.clearActiveLogin();
|
|
526
|
-
}
|
|
527
|
-
return;
|
|
528
|
-
}
|
|
529
|
-
if (previousLogin && previousAccountId !== accountId) {
|
|
530
|
-
await this.restoreActiveLogin(previousLogin);
|
|
579
|
+
if (!sessionClient.getSavedAccounts().some((account) => account.id === accountId && account.expired)) {
|
|
580
|
+
throw error;
|
|
531
581
|
}
|
|
532
|
-
throw error;
|
|
533
582
|
}
|
|
534
|
-
this.clearActiveLogin();
|
|
535
583
|
this.removeSavedAccount(accountId);
|
|
584
|
+
if (!wasActive) {
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
this.clearActiveLogin();
|
|
536
588
|
const availableAccountIds = new Set(this.getSavedAccounts().filter((account) => !account.expired).map((account) => account.id));
|
|
537
589
|
let nextLogin;
|
|
538
590
|
if (previousAccountId && previousAccountId !== accountId) {
|
|
@@ -604,6 +656,7 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
604
656
|
queued: 0,
|
|
605
657
|
exhausted: 0,
|
|
606
658
|
responses: {},
|
|
659
|
+
failures: {},
|
|
607
660
|
};
|
|
608
661
|
}
|
|
609
662
|
return queue.flush(options, ...(requestOptions === undefined ? [] : [requestOptions]));
|
|
@@ -673,6 +726,19 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
673
726
|
var _a, _b;
|
|
674
727
|
return ((_b = (_a = this.clientStorage) === null || _a === void 0 ? void 0 : _a.getObject(account_storage_1.EXPIRED_ACCOUNTS_STORAGE_KEY)) !== null && _b !== void 0 ? _b : []);
|
|
675
728
|
}
|
|
729
|
+
createAccountSessionClient(login) {
|
|
730
|
+
const storage = new core_1.ClientStorage(new core_1.MemoryStorage(), this.clientOptions.storagePrefix);
|
|
731
|
+
storage.setObject("activeLogin", login);
|
|
732
|
+
storage.setObject(account_storage_1.LOGINS_STORAGE_KEY, [login]);
|
|
733
|
+
const client = new OvokClient({
|
|
734
|
+
...this.clientOptions,
|
|
735
|
+
storage,
|
|
736
|
+
offlineQueue: undefined,
|
|
737
|
+
onUnauthenticated: undefined,
|
|
738
|
+
});
|
|
739
|
+
client.setAccessToken(login.accessToken, login.refreshToken);
|
|
740
|
+
return client;
|
|
741
|
+
}
|
|
676
742
|
setAccountExpired(accountId, expired) {
|
|
677
743
|
if (this.clientStorage) {
|
|
678
744
|
(0, account_storage_1.setStoredAccountExpired)(this.clientStorage, accountId, expired);
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type { MedplumRequestOptions } from "@medplum/core";
|
|
2
2
|
import { OvokClient } from "../ovok-client";
|
|
3
|
-
import { OvokCurrentPatientProfile, OvokPatientLatestObservationsQuery, OvokPatientObservationBundle, OvokPatientAppointment, OvokPatientCarePlan, OvokPatientDashboard, OvokPatientDashboardQuery, OvokPatientDevice, OvokPatientMeasurement, OvokPatientNotification, OvokPatientQuestionnaire, OvokPatientQuestionnaireResponse, OvokPatientResourceQuery, OvokPatientSchedule, OvokPatientSchedulingQuery, OvokPatientSlot
|
|
3
|
+
import { OvokCurrentPatientProfile, OvokPatientLatestObservationsQuery, OvokPatientObservationBundle, OvokPatientAppointment, OvokPatientCarePlan, OvokPatientDashboard, OvokPatientDashboardQuery, OvokPatientDevice, OvokPatientMeasurement, OvokPatientNotification, OvokPatientQuestionnaire, OvokPatientQuestionnaireResponse, OvokPatientResourceQuery, OvokPatientSchedule, OvokPatientSchedulingQuery, OvokPatientSlot } from "./types";
|
|
4
4
|
export declare function getCurrentPatientProfile(this: OvokClient, requestOptions?: MedplumRequestOptions): Promise<OvokCurrentPatientProfile>;
|
|
5
5
|
export declare function getPatientLatestObservations(this: OvokClient, params?: OvokPatientLatestObservationsQuery, requestOptions?: MedplumRequestOptions): Promise<OvokPatientObservationBundle>;
|
|
6
|
-
export declare function getPatientDeviceTelemetry(this: OvokClient, deviceId: string, requestOptions?: MedplumRequestOptions): Promise<OvokPatientObservationBundle>;
|
|
7
|
-
export declare function getPatientDeviceTelemetryHistory(this: OvokClient, deviceId: string, params?: OvokPatientTelemetryHistoryQuery, requestOptions?: MedplumRequestOptions): Promise<OvokPatientTelemetryHistory>;
|
|
8
6
|
export declare function listPatientAppointments(this: OvokClient, params?: OvokPatientSchedulingQuery, requestOptions?: MedplumRequestOptions): Promise<OvokPatientAppointment[]>;
|
|
9
7
|
export declare function getPatientAppointment(this: OvokClient, appointmentId: string, requestOptions?: MedplumRequestOptions): Promise<OvokPatientAppointment>;
|
|
10
8
|
export declare function createPatientAppointment(this: OvokClient, appointment: OvokPatientAppointment, requestOptions?: MedplumRequestOptions): Promise<OvokPatientAppointment>;
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getCurrentPatientProfile = getCurrentPatientProfile;
|
|
4
4
|
exports.getPatientLatestObservations = getPatientLatestObservations;
|
|
5
|
-
exports.getPatientDeviceTelemetry = getPatientDeviceTelemetry;
|
|
6
|
-
exports.getPatientDeviceTelemetryHistory = getPatientDeviceTelemetryHistory;
|
|
7
5
|
exports.listPatientAppointments = listPatientAppointments;
|
|
8
6
|
exports.getPatientAppointment = getPatientAppointment;
|
|
9
7
|
exports.createPatientAppointment = createPatientAppointment;
|
|
@@ -23,7 +21,6 @@ exports.getPatientDevice = getPatientDevice;
|
|
|
23
21
|
exports.listPatientNotifications = listPatientNotifications;
|
|
24
22
|
exports.getPatientNotification = getPatientNotification;
|
|
25
23
|
exports.getPatientDashboard = getPatientDashboard;
|
|
26
|
-
const segment = (value) => encodeURIComponent(value);
|
|
27
24
|
const query = (params) => {
|
|
28
25
|
const values = new URLSearchParams();
|
|
29
26
|
for (const [key, value] of Object.entries(params)) {
|
|
@@ -45,12 +42,6 @@ async function getPatientLatestObservations(params = {}, requestOptions) {
|
|
|
45
42
|
code,
|
|
46
43
|
})}`, { ...{ cache: "no-cache" }, ...requestOptions });
|
|
47
44
|
}
|
|
48
|
-
async function getPatientDeviceTelemetry(deviceId, requestOptions) {
|
|
49
|
-
return this.get(`/fhir/Device/${segment(deviceId)}/telemetry`, ...(requestOptions === undefined ? [] : [requestOptions]));
|
|
50
|
-
}
|
|
51
|
-
async function getPatientDeviceTelemetryHistory(deviceId, params = {}, requestOptions) {
|
|
52
|
-
return this.get(`/fhir/Device/${segment(deviceId)}/telemetry/history${query(params)}`, ...(requestOptions === undefined ? [] : [requestOptions]));
|
|
53
|
-
}
|
|
54
45
|
async function listPatientAppointments(params = {}, requestOptions) {
|
|
55
46
|
return this.searchResources("Appointment", params, ...(requestOptions === undefined ? [] : [requestOptions]));
|
|
56
47
|
}
|
|
@@ -61,13 +61,6 @@ export type OvokPatientLatestObservationsQuery = {
|
|
|
61
61
|
max?: number;
|
|
62
62
|
code?: string | string[];
|
|
63
63
|
};
|
|
64
|
-
export type OvokPatientTelemetryHistoryQuery = {
|
|
65
|
-
from?: string;
|
|
66
|
-
to?: string;
|
|
67
|
-
code?: string;
|
|
68
|
-
page?: number;
|
|
69
|
-
pageSize?: number;
|
|
70
|
-
};
|
|
71
64
|
export type OvokPatientSchedulingQuery = Record<string, string | number | boolean | undefined>;
|
|
72
65
|
export type OvokPatientResourceQuery = OvokPatientSchedulingQuery;
|
|
73
66
|
export type OvokPatientDashboardQuery = {
|
|
@@ -91,9 +84,3 @@ export type OvokPatientDashboard = {
|
|
|
91
84
|
carePlans: OvokPatientCarePlan[];
|
|
92
85
|
};
|
|
93
86
|
export type OvokPatientObservationBundle = Bundle<Observation>;
|
|
94
|
-
export type OvokPatientTelemetryHistory = {
|
|
95
|
-
deviceId: string;
|
|
96
|
-
patientId: string;
|
|
97
|
-
signalsPatientId: string;
|
|
98
|
-
[key: string]: unknown;
|
|
99
|
-
};
|
|
@@ -11,7 +11,10 @@ function createPatientSharingInvite(body, requestOptions) {
|
|
|
11
11
|
return this.post("/v1/patient-sharing/invites", body, undefined, requestOptions);
|
|
12
12
|
}
|
|
13
13
|
function redeemPatientSharingInvite(body, requestOptions) {
|
|
14
|
-
return this.post("/v1/patient-sharing/invites/redeem", body, undefined, requestOptions)
|
|
14
|
+
return this.post("/v1/patient-sharing/invites/redeem", body, undefined, requestOptions).then((share) => {
|
|
15
|
+
this.invalidateUrl("/v1/patient-sharing/shares");
|
|
16
|
+
return share;
|
|
17
|
+
});
|
|
15
18
|
}
|
|
16
19
|
function listPatientSharing(requestOptions) {
|
|
17
20
|
return this.get("/v1/patient-sharing/shares", ...(requestOptions === undefined ? [] : [requestOptions])).then((shares) => {
|
|
@@ -24,6 +27,7 @@ function listPatientSharing(requestOptions) {
|
|
|
24
27
|
}
|
|
25
28
|
async function revokePatientSharing(consentId, requestOptions) {
|
|
26
29
|
await this.delete(`/v1/patient-sharing/shares/${segment(consentId)}`, ...(requestOptions === undefined ? [] : [requestOptions]));
|
|
30
|
+
this.invalidateUrl("/v1/patient-sharing/shares");
|
|
27
31
|
}
|
|
28
32
|
function getPatientSharingSettings(requestOptions) {
|
|
29
33
|
return this.get("/v1/patient-sharing/settings", ...(requestOptions === undefined ? [] : [requestOptions]));
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import type { MedplumRequestOptions } from "@medplum/core";
|
|
2
2
|
import { OvokClient } from "../ovok-client";
|
|
3
|
-
import { OvokAccount, OvokAdministeredProject,
|
|
3
|
+
import { OvokAccount, OvokAdministeredProject, OvokI18nDocument, OvokI18nValue, OvokInviteProjectMember, OvokLocalization, OvokLocalizationQuery, OvokLocalizationUpdate, OvokLocales, OvokPage, OvokPatientObservations, OvokProjectFeature, OvokProjectFeatures, OvokProjectMember, OvokProjectMemberResponse, OvokProjectSettings, OvokProjectSettingKey, OvokProjectTextSettingKey, OvokRemoveProjectMemberResponse, OvokUpdateProjectMember } from "./types";
|
|
4
4
|
export declare function getAccounts(this: OvokClient, requestOptions?: MedplumRequestOptions): Promise<OvokAccount[]>;
|
|
5
5
|
export declare function listAdministeredProjects(this: OvokClient, params?: {
|
|
6
6
|
page?: number;
|
|
7
7
|
count?: number;
|
|
8
8
|
}, requestOptions?: MedplumRequestOptions): Promise<OvokPage<OvokAdministeredProject>>;
|
|
9
|
-
export declare function createProject(this: OvokClient, body: OvokCreateProject, requestOptions?: MedplumRequestOptions): Promise<OvokCreatedProject>;
|
|
10
|
-
export declare function bootstrapProject(this: OvokClient, body: OvokCreateProject, requestOptions?: MedplumRequestOptions): Promise<OvokCreatedProject>;
|
|
11
|
-
export declare function getProjectTenantCode(this: OvokClient, requestOptions?: MedplumRequestOptions): Promise<{
|
|
12
|
-
tenantCode: string;
|
|
13
|
-
}>;
|
|
14
9
|
export declare function listProjectMembers(this: OvokClient, params?: {
|
|
15
10
|
accessPolicyId?: string;
|
|
16
11
|
profileId?: string;
|
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getAccounts = getAccounts;
|
|
4
4
|
exports.listAdministeredProjects = listAdministeredProjects;
|
|
5
|
-
exports.createProject = createProject;
|
|
6
|
-
exports.bootstrapProject = bootstrapProject;
|
|
7
|
-
exports.getProjectTenantCode = getProjectTenantCode;
|
|
8
5
|
exports.listProjectMembers = listProjectMembers;
|
|
9
6
|
exports.inviteProjectMember = inviteProjectMember;
|
|
10
7
|
exports.updateProjectMember = updateProjectMember;
|
|
@@ -40,15 +37,6 @@ async function getAccounts(requestOptions) {
|
|
|
40
37
|
async function listAdministeredProjects(params = {}, requestOptions) {
|
|
41
38
|
return this.get(`/v1/projects${query(params)}`, ...(requestOptions === undefined ? [] : [requestOptions]));
|
|
42
39
|
}
|
|
43
|
-
async function createProject(body, requestOptions) {
|
|
44
|
-
return this.post("/v1/projects", body, undefined, requestOptions);
|
|
45
|
-
}
|
|
46
|
-
async function bootstrapProject(body, requestOptions) {
|
|
47
|
-
return this.post("/v1/projects/bootstrap", body, undefined, requestOptions);
|
|
48
|
-
}
|
|
49
|
-
async function getProjectTenantCode(requestOptions) {
|
|
50
|
-
return this.get("/v1/projects/me/tenant-code", ...(requestOptions === undefined ? [] : [requestOptions]));
|
|
51
|
-
}
|
|
52
40
|
async function listProjectMembers(params = {}, requestOptions) {
|
|
53
41
|
return this.get(`/v1/projects/me/members${query(params)}`, ...(requestOptions === undefined ? [] : [requestOptions]));
|
|
54
42
|
}
|
|
@@ -16,14 +16,6 @@ export type OvokAdministeredProject = {
|
|
|
16
16
|
isMainProject: boolean | null;
|
|
17
17
|
parentProjectId: string | null;
|
|
18
18
|
};
|
|
19
|
-
export type OvokCreateProject = {
|
|
20
|
-
name: string;
|
|
21
|
-
};
|
|
22
|
-
export type OvokCreatedProject = {
|
|
23
|
-
projectId: string;
|
|
24
|
-
tenantCode: string;
|
|
25
|
-
name: string;
|
|
26
|
-
};
|
|
27
19
|
export type OvokProjectMemberReference = {
|
|
28
20
|
reference?: string;
|
|
29
21
|
display?: string;
|
|
@@ -75,9 +75,6 @@ exports.OVOK_CORE_API_REQUIREMENTS = {
|
|
|
75
75
|
{ method: "POST", path: "/video-call/livekit/notification/active-call/:appointmentId", group: "Video" },
|
|
76
76
|
{ method: "GET", path: "/accounts", group: "Accounts" },
|
|
77
77
|
{ method: "GET", path: "/v1/projects", group: "Projects" },
|
|
78
|
-
{ method: "POST", path: "/v1/projects", group: "Projects" },
|
|
79
|
-
{ method: "POST", path: "/v1/projects/bootstrap", group: "Projects" },
|
|
80
|
-
{ method: "GET", path: "/v1/projects/me/tenant-code", group: "Projects" },
|
|
81
78
|
{ method: "GET", path: "/v1/projects/me/members", group: "Projects" },
|
|
82
79
|
{ method: "POST", path: "/v1/projects/me/members", group: "Projects" },
|
|
83
80
|
{ method: "PATCH", path: "/v1/projects/me/members/:membershipId", group: "Projects" },
|
|
@@ -108,8 +105,6 @@ exports.OVOK_CORE_API_REQUIREMENTS = {
|
|
|
108
105
|
{ method: "PATCH", path: "/localization/i18next/:language", group: "Localization" },
|
|
109
106
|
{ method: "GET", path: "/patient/:id/observation", group: "Patient" },
|
|
110
107
|
{ method: "GET", path: "/fhir/Observation/$lastn", group: "Patient" },
|
|
111
|
-
{ method: "GET", path: "/fhir/Device/:id/telemetry", group: "Patient" },
|
|
112
|
-
{ method: "GET", path: "/fhir/Device/:id/telemetry/history", group: "Patient" },
|
|
113
108
|
{ method: "POST", path: "/fhir/Questionnaire/:id/$populate", group: "Questionnaire" },
|
|
114
109
|
{ method: "POST", path: "/fhir/QuestionnaireResponse/:id/$extract", group: "Questionnaire" },
|
|
115
110
|
{ method: "GET", path: "/v1/slim/patient", group: "Slim/Patient" },
|
|
@@ -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.4.
|
|
51
|
+
version: "0.4.34",
|
|
52
52
|
},
|
|
53
53
|
fhirVersion: "4.0.1",
|
|
54
54
|
format: ["json"],
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -19,6 +19,6 @@ export { useCreateNotificationNote, useCreateSignalsAlertNote, useCreateSignalsR
|
|
|
19
19
|
export { useAcknowledgeSlimAlarm, useAcknowledgeSlimMedicalNotification, } from "./notification-ack-hooks";
|
|
20
20
|
export { useCmsDocument, useCmsDocuments, useLegalPage, useReleaseNotes, useTranslations, } from "./cms-hooks";
|
|
21
21
|
export { useAcceptInvite, useInvitePatient, useInvitePractitioner, } from "./invites-hooks";
|
|
22
|
-
export { useCurrentPatientProfile, useExtractQuestionnaireObservations, usePatientAppointments, usePatientCarePlans, usePatientDevices,
|
|
22
|
+
export { useCurrentPatientProfile, useExtractQuestionnaireObservations, usePatientAppointments, usePatientCarePlans, usePatientDevices, usePatientMeasurement, usePatientMeasurementHistory, usePatientDashboard, usePatientLatestObservations, usePatientNotifications, usePatientQuestionnaireResponses, usePatientQuestionnaires, usePatientSchedules, usePatientSlots, usePopulateQuestionnaire, useSubmitQuestionnaireResponse, } from "./patient-hooks";
|
|
23
23
|
export { useCreatePatientSharingInvite, usePatientSharing, usePatientSharingSettings, useRedeemPatientSharingInvite, useRevokePatientSharing, useUpdatePatientSharingSettings, } from "./patient-sharing-hooks";
|
|
24
24
|
export { useAcknowledgeSignalsAlert, useEnableSignalsForPatient, useRemoveSignalsThreshold, useSetSignalsThreshold, useSignalsAlert, useSignalsAlerts, useSignalsSettings, useSignalsThresholds, useUpdateSignalsSettings, } from "./signals-hooks";
|
package/dist/hooks/index.js
CHANGED
|
@@ -35,8 +35,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
exports.useSetLegalConsent = exports.useRepushUnconfirmedLimits = exports.useMedicalConsent = exports.useLegalConsent = exports.useChangeHistory = exports.useEmailTemplates = exports.useUpdateProjectTextSetting = exports.useUpdateLocalization = exports.useUpdateI18nextDocument = exports.useLocalizations = exports.useLocales = exports.useI18nextDocument = exports.useVideoCallAppointments = exports.useVideoCallAccess = exports.useDocuments = exports.useCreateVideoCallUserAccess = exports.useCreateVideoCallAppointment = exports.useContent = exports.useConsentSignature = exports.useOvokPoll = exports.useRecentSlimNotifications = exports.usePublicApiEndpoints = exports.useProjectSettings = exports.useProjectFeatures = exports.useOvokRequest = exports.useOvokMutation = exports.useCapabilityStatement = exports.useSlimPatients = exports.useSlimNotifications = exports.useSlimDevices = exports.useSlimDeviceTelemetry = exports.useAdministeredProjects = exports.useUrineTests = exports.useSaveMeasurement = exports.useObservations = exports.useEcgRecording = exports.observationsToMeasurements = exports.OvokProvider = exports.useClient = exports.useCachedBinaryUrl = exports.reactContext = exports.useSubscription = exports.useSearchResources = exports.useSearchOne = exports.useSearch = exports.useResource = exports.usePrevious = exports.useMedplumProfile = exports.useMedplumNavigate = exports.useMedplumContext = void 0;
|
|
38
|
-
exports.useCreatePatientSharingInvite = exports.useSubmitQuestionnaireResponse = exports.usePopulateQuestionnaire = exports.usePatientSlots = exports.usePatientSchedules = exports.usePatientQuestionnaires = exports.usePatientQuestionnaireResponses = exports.usePatientNotifications = exports.usePatientLatestObservations = exports.usePatientDashboard = exports.usePatientMeasurementHistory = exports.usePatientMeasurement = exports.
|
|
39
|
-
exports.useUpdateSignalsSettings = exports.useSignalsThresholds = exports.useSignalsSettings = exports.useSignalsAlerts = exports.useSignalsAlert = exports.useSetSignalsThreshold = exports.useRemoveSignalsThreshold = exports.useEnableSignalsForPatient = exports.useAcknowledgeSignalsAlert = exports.useUpdatePatientSharingSettings = exports.useRevokePatientSharing = exports.useRedeemPatientSharingInvite =
|
|
38
|
+
exports.usePatientSharingSettings = exports.usePatientSharing = exports.useCreatePatientSharingInvite = exports.useSubmitQuestionnaireResponse = exports.usePopulateQuestionnaire = exports.usePatientSlots = exports.usePatientSchedules = exports.usePatientQuestionnaires = exports.usePatientQuestionnaireResponses = exports.usePatientNotifications = exports.usePatientLatestObservations = exports.usePatientDashboard = exports.usePatientMeasurementHistory = exports.usePatientMeasurement = exports.usePatientDevices = exports.usePatientCarePlans = exports.usePatientAppointments = exports.useExtractQuestionnaireObservations = exports.useCurrentPatientProfile = exports.useInvitePractitioner = exports.useInvitePatient = exports.useAcceptInvite = exports.useTranslations = exports.useReleaseNotes = exports.useLegalPage = exports.useCmsDocuments = exports.useCmsDocument = exports.useAcknowledgeSlimMedicalNotification = exports.useAcknowledgeSlimAlarm = exports.useUpdateSignalsNote = exports.useUpdateNotificationNote = exports.useSignalsRawAlertNotes = exports.useSignalsAlertNotes = exports.useNotificationNotes = exports.useDeleteSignalsNote = exports.useDeleteNotificationNote = exports.useCreateSignalsRawAlertNote = exports.useCreateSignalsAlertNote = exports.useCreateNotificationNote = exports.useSlimOutOfBedNotifications = exports.useSlimMedicalNotifications = exports.useSlimAlarms = exports.useRecentOutOfBed = exports.useRecentAlarms = exports.useUpdateSlimThresholdV2 = exports.useUpdateSlimPatientThresholdV2 = exports.useUnconfirmedLimits = exports.useSlimThresholdV2 = exports.useSlimPatientThresholdV2 = exports.useSetMedicalConsent = void 0;
|
|
39
|
+
exports.useUpdateSignalsSettings = exports.useSignalsThresholds = exports.useSignalsSettings = exports.useSignalsAlerts = exports.useSignalsAlert = exports.useSetSignalsThreshold = exports.useRemoveSignalsThreshold = exports.useEnableSignalsForPatient = exports.useAcknowledgeSignalsAlert = exports.useUpdatePatientSharingSettings = exports.useRevokePatientSharing = exports.useRedeemPatientSharingInvite = void 0;
|
|
40
40
|
/*
|
|
41
41
|
* The only React-dependent module in the package.
|
|
42
42
|
*
|
|
@@ -158,8 +158,6 @@ Object.defineProperty(exports, "useExtractQuestionnaireObservations", { enumerab
|
|
|
158
158
|
Object.defineProperty(exports, "usePatientAppointments", { enumerable: true, get: function () { return patient_hooks_1.usePatientAppointments; } });
|
|
159
159
|
Object.defineProperty(exports, "usePatientCarePlans", { enumerable: true, get: function () { return patient_hooks_1.usePatientCarePlans; } });
|
|
160
160
|
Object.defineProperty(exports, "usePatientDevices", { enumerable: true, get: function () { return patient_hooks_1.usePatientDevices; } });
|
|
161
|
-
Object.defineProperty(exports, "usePatientDeviceTelemetry", { enumerable: true, get: function () { return patient_hooks_1.usePatientDeviceTelemetry; } });
|
|
162
|
-
Object.defineProperty(exports, "usePatientDeviceTelemetryHistory", { enumerable: true, get: function () { return patient_hooks_1.usePatientDeviceTelemetryHistory; } });
|
|
163
161
|
Object.defineProperty(exports, "usePatientMeasurement", { enumerable: true, get: function () { return patient_hooks_1.usePatientMeasurement; } });
|
|
164
162
|
Object.defineProperty(exports, "usePatientMeasurementHistory", { enumerable: true, get: function () { return patient_hooks_1.usePatientMeasurementHistory; } });
|
|
165
163
|
Object.defineProperty(exports, "usePatientDashboard", { enumerable: true, get: function () { return patient_hooks_1.usePatientDashboard; } });
|
|
@@ -3,9 +3,15 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.useAcceptInvite = exports.useInvitePatient = exports.useInvitePractitioner = void 0;
|
|
5
5
|
const api_hooks_1 = require("./api-hooks");
|
|
6
|
+
const notification_invalidation_1 = require("./notification-invalidation");
|
|
6
7
|
const useInvitePractitioner = () => (0, api_hooks_1.useOvokMutation)((client, body) => client.invitePractitioner(body));
|
|
7
8
|
exports.useInvitePractitioner = useInvitePractitioner;
|
|
8
9
|
const useInvitePatient = () => (0, api_hooks_1.useOvokMutation)((client, body) => client.invitePatient(body));
|
|
9
10
|
exports.useInvitePatient = useInvitePatient;
|
|
10
|
-
const useAcceptInvite = () => (0, api_hooks_1.useOvokMutation)((client, body) =>
|
|
11
|
+
const useAcceptInvite = () => (0, api_hooks_1.useOvokMutation)(async (client, body) => {
|
|
12
|
+
const result = await client.acceptInvite(body);
|
|
13
|
+
client.invalidateUrl("/v1/patient-sharing/shares");
|
|
14
|
+
(0, notification_invalidation_1.notifyNotificationChanges)(client, { type: "patient-sharing" });
|
|
15
|
+
return result;
|
|
16
|
+
});
|
|
11
17
|
exports.useAcceptInvite = useAcceptInvite;
|
|
@@ -3,6 +3,8 @@ import { OvokClient } from "../client/ovok-client";
|
|
|
3
3
|
import { SignalsAlert, SignalsRawAlert } from "../client/signals/types";
|
|
4
4
|
import { SlimNotification } from "../client/slim/types";
|
|
5
5
|
export type NotificationChange = {
|
|
6
|
+
type: "patient-sharing";
|
|
7
|
+
} | {
|
|
6
8
|
type: "slim";
|
|
7
9
|
notification: SlimNotification | SlimMedicalNotificationRow;
|
|
8
10
|
} | {
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { Bundle, Observation, Parameters, QuestionnaireResponse } from "@medplum/fhirtypes";
|
|
2
|
-
import { OvokCurrentPatientProfile, OvokPatientAppointment, OvokPatientCarePlan, OvokPatientDashboard, OvokPatientDashboardQuery, OvokPatientDevice, OvokPatientLatestObservationsQuery, OvokPatientMeasurement, OvokPatientNotification, OvokPatientObservationBundle, OvokPatientQuestionnaire, OvokPatientQuestionnaireResponse, OvokPatientResourceQuery, OvokPatientSchedule, OvokPatientSchedulingQuery, OvokPatientSlot
|
|
2
|
+
import { OvokCurrentPatientProfile, OvokPatientAppointment, OvokPatientCarePlan, OvokPatientDashboard, OvokPatientDashboardQuery, OvokPatientDevice, OvokPatientLatestObservationsQuery, OvokPatientMeasurement, OvokPatientNotification, OvokPatientObservationBundle, OvokPatientQuestionnaire, OvokPatientQuestionnaireResponse, OvokPatientResourceQuery, OvokPatientSchedule, OvokPatientSchedulingQuery, OvokPatientSlot } from "../client/patient/types";
|
|
3
3
|
import { OvokQuestionnaireOperationResponse } from "../client/questionnaire-response/types";
|
|
4
4
|
import { OvokMutationState, OvokRequestState } from "./api-hooks";
|
|
5
5
|
export declare const useCurrentPatientProfile: () => OvokRequestState<OvokCurrentPatientProfile>;
|
|
6
6
|
export declare const usePatientDashboard: (params?: OvokPatientDashboardQuery) => OvokRequestState<OvokPatientDashboard>;
|
|
7
7
|
export declare const usePatientLatestObservations: (params?: OvokPatientLatestObservationsQuery) => OvokRequestState<OvokPatientObservationBundle>;
|
|
8
|
-
export declare const usePatientDeviceTelemetry: (deviceId?: string) => OvokRequestState<OvokPatientObservationBundle>;
|
|
9
|
-
export declare const usePatientDeviceTelemetryHistory: (deviceId: string | undefined, params?: OvokPatientTelemetryHistoryQuery) => OvokRequestState<OvokPatientTelemetryHistory>;
|
|
10
8
|
export declare const usePatientAppointments: (params?: OvokPatientSchedulingQuery) => OvokRequestState<OvokPatientAppointment[]>;
|
|
11
9
|
export declare const usePatientSchedules: (params?: OvokPatientSchedulingQuery) => OvokRequestState<OvokPatientSchedule[]>;
|
|
12
10
|
export declare const usePatientSlots: (params?: OvokPatientSchedulingQuery) => OvokRequestState<OvokPatientSlot[]>;
|
|
@@ -34,7 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
};
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
exports.useExtractQuestionnaireObservations = exports.useSubmitQuestionnaireResponse = exports.usePopulateQuestionnaire = exports.usePatientNotifications = exports.usePatientDevices = exports.usePatientQuestionnaireResponses = exports.usePatientQuestionnaires = exports.usePatientCarePlans = exports.usePatientMeasurement = exports.usePatientMeasurementHistory = exports.usePatientSlots = exports.usePatientSchedules = exports.usePatientAppointments = exports.
|
|
37
|
+
exports.useExtractQuestionnaireObservations = exports.useSubmitQuestionnaireResponse = exports.usePopulateQuestionnaire = exports.usePatientNotifications = exports.usePatientDevices = exports.usePatientQuestionnaireResponses = exports.usePatientQuestionnaires = exports.usePatientCarePlans = exports.usePatientMeasurement = exports.usePatientMeasurementHistory = exports.usePatientSlots = exports.usePatientSchedules = exports.usePatientAppointments = exports.usePatientLatestObservations = exports.usePatientDashboard = exports.useCurrentPatientProfile = void 0;
|
|
38
38
|
const React = __importStar(require("react"));
|
|
39
39
|
const api_hooks_1 = require("./api-hooks");
|
|
40
40
|
const index_1 = require("./index");
|
|
@@ -58,23 +58,6 @@ const usePatientLatestObservations = (params = {}) => {
|
|
|
58
58
|
return (0, api_hooks_1.useOvokRequest)(load);
|
|
59
59
|
};
|
|
60
60
|
exports.usePatientLatestObservations = usePatientLatestObservations;
|
|
61
|
-
const usePatientDeviceTelemetry = (deviceId) => {
|
|
62
|
-
const client = (0, index_1.useClient)();
|
|
63
|
-
const load = React.useCallback((signal) => deviceId
|
|
64
|
-
? client.getPatientDeviceTelemetry(deviceId, { signal })
|
|
65
|
-
: Promise.reject(new Error("deviceId is required")), [client, deviceId]);
|
|
66
|
-
return (0, api_hooks_1.useOvokRequest)(load, deviceId !== undefined);
|
|
67
|
-
};
|
|
68
|
-
exports.usePatientDeviceTelemetry = usePatientDeviceTelemetry;
|
|
69
|
-
const usePatientDeviceTelemetryHistory = (deviceId, params = {}) => {
|
|
70
|
-
const client = (0, index_1.useClient)();
|
|
71
|
-
const serialized = JSON.stringify(params);
|
|
72
|
-
const load = React.useCallback((signal) => deviceId
|
|
73
|
-
? client.getPatientDeviceTelemetryHistory(deviceId, params, { signal })
|
|
74
|
-
: Promise.reject(new Error("deviceId is required")), [client, deviceId, serialized]);
|
|
75
|
-
return (0, api_hooks_1.useOvokRequest)(load, deviceId !== undefined);
|
|
76
|
-
};
|
|
77
|
-
exports.usePatientDeviceTelemetryHistory = usePatientDeviceTelemetryHistory;
|
|
78
61
|
const usePatientAppointments = (params = {}) => {
|
|
79
62
|
const client = (0, index_1.useClient)();
|
|
80
63
|
const serialized = JSON.stringify(params);
|
|
@@ -37,18 +37,32 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
37
37
|
exports.useUpdatePatientSharingSettings = exports.usePatientSharingSettings = exports.useRevokePatientSharing = exports.useRedeemPatientSharingInvite = exports.useCreatePatientSharingInvite = exports.usePatientSharing = void 0;
|
|
38
38
|
const React = __importStar(require("react"));
|
|
39
39
|
const api_hooks_1 = require("./api-hooks");
|
|
40
|
+
const notification_invalidation_1 = require("./notification-invalidation");
|
|
40
41
|
const index_1 = require("./index");
|
|
41
42
|
const usePatientSharing = () => {
|
|
42
43
|
const client = (0, index_1.useClient)();
|
|
43
44
|
const load = React.useCallback((signal) => client.listPatientSharing({ signal }), [client]);
|
|
44
|
-
|
|
45
|
+
const state = (0, api_hooks_1.useOvokRequestWithUpdater)(load);
|
|
46
|
+
React.useEffect(() => (0, notification_invalidation_1.subscribeToNotificationChanges)(client, (change) => {
|
|
47
|
+
if ((change === null || change === void 0 ? void 0 : change.type) === "patient-sharing") {
|
|
48
|
+
state.reload();
|
|
49
|
+
}
|
|
50
|
+
}), [client, state.reload]);
|
|
51
|
+
return state;
|
|
45
52
|
};
|
|
46
53
|
exports.usePatientSharing = usePatientSharing;
|
|
47
54
|
const useCreatePatientSharingInvite = () => (0, api_hooks_1.useOvokMutation)((client, params) => client.createPatientSharingInvite(params));
|
|
48
55
|
exports.useCreatePatientSharingInvite = useCreatePatientSharingInvite;
|
|
49
|
-
const useRedeemPatientSharingInvite = () => (0, api_hooks_1.useOvokMutation)((client, params) =>
|
|
56
|
+
const useRedeemPatientSharingInvite = () => (0, api_hooks_1.useOvokMutation)(async (client, params) => {
|
|
57
|
+
const share = await client.redeemPatientSharingInvite(params);
|
|
58
|
+
(0, notification_invalidation_1.notifyNotificationChanges)(client, { type: "patient-sharing" });
|
|
59
|
+
return share;
|
|
60
|
+
});
|
|
50
61
|
exports.useRedeemPatientSharingInvite = useRedeemPatientSharingInvite;
|
|
51
|
-
const useRevokePatientSharing = () => (0, api_hooks_1.useOvokMutation)((client, consentId) =>
|
|
62
|
+
const useRevokePatientSharing = () => (0, api_hooks_1.useOvokMutation)(async (client, consentId) => {
|
|
63
|
+
await client.revokePatientSharing(consentId);
|
|
64
|
+
(0, notification_invalidation_1.notifyNotificationChanges)(client, { type: "patient-sharing" });
|
|
65
|
+
});
|
|
52
66
|
exports.useRevokePatientSharing = useRevokePatientSharing;
|
|
53
67
|
const usePatientSharingSettings = () => {
|
|
54
68
|
const client = (0, index_1.useClient)();
|