@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 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.getPatientDeviceTelemetry(deviceId);
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. The returned resource lists are subject to the
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) => this.runExclusive(async () => {
85
- var _a, _b, _c;
86
- await ((_b = (_a = this.storage).getInitPromise) === null || _b === void 0 ? void 0 : _b.call(_a));
87
- const queue = this.readQueue();
88
- const entries = observations.map(entryForObservation);
89
- const ownerKey = (_c = this.getOwnerKey) === null || _c === void 0 ? void 0 : _c.call(this);
90
- if (this.getOwnerKey && !ownerKey) {
91
- throw new Error("Offline measurements require an active account to prevent cross-account delivery.");
92
- }
93
- const id = stableValueId({ ownerKey, entries });
94
- if (!queue.some((item) => item.id === id)) {
95
- queue.push({
96
- id,
97
- ownerKey,
98
- queuedAt: new Date().toISOString(),
99
- attempt: 0,
100
- nextAttemptAt: 0,
101
- entries,
102
- });
103
- this.writeQueue(queue);
104
- }
105
- return { id, flush: await this.flushQueue(queue, {}, ...(requestOptions === undefined ? [] : [requestOptions])) };
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 (_b) {
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 errors_1 = require("./signals/errors");
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, errors_1.mapSignalsError)((0, rate_limit_error_1.mapRateLimitError)(error), {
467
+ const mapped = (0, errors_2.mapSignalsError)((0, rate_limit_error_1.mapRateLimitError)(error), {
441
468
  signalsRequest: true,
442
469
  });
443
- return (0, errors_1.isSignalsError)(mapped) ? mapped : (0, ovok_error_1.mapOvokApiError)(mapped);
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 Error(`No saved account found for ${accountId}.`);
538
+ throw new errors_1.OvokAccountError("account_not_found");
480
539
  }
481
540
  if (this.getExpiredAccountIds().includes(accountId)) {
482
- throw new Error("This account's session has expired. Sign in again.");
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 Error(`No saved account found for ${accountId}.`);
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 this.setActiveLogin(login);
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 (this.getExpiredAccountIds().includes(accountId)) {
520
- this.removeSavedAccount(accountId);
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, OvokPatientTelemetryHistory, OvokPatientTelemetryHistoryQuery } from "./types";
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, OvokCreateProject, OvokCreatedProject, OvokI18nDocument, OvokI18nValue, OvokInviteProjectMember, OvokLocalization, OvokLocalizationQuery, OvokLocalizationUpdate, OvokLocales, OvokPage, OvokPatientObservations, OvokProjectFeature, OvokProjectFeatures, OvokProjectMember, OvokProjectMemberResponse, OvokProjectSettings, OvokProjectSettingKey, OvokProjectTextSettingKey, OvokRemoveProjectMemberResponse, OvokUpdateProjectMember } from "./types";
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.32",
51
+ version: "0.4.34",
52
52
  },
53
53
  fhirVersion: "4.0.1",
54
54
  format: ["json"],
@@ -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, usePatientDeviceTelemetry, usePatientDeviceTelemetryHistory, usePatientMeasurement, usePatientMeasurementHistory, usePatientDashboard, usePatientLatestObservations, usePatientNotifications, usePatientQuestionnaireResponses, usePatientQuestionnaires, usePatientSchedules, usePatientSlots, usePopulateQuestionnaire, useSubmitQuestionnaireResponse, } from "./patient-hooks";
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";
@@ -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.usePatientDeviceTelemetryHistory = exports.usePatientDeviceTelemetry = 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 = exports.usePatientSharingSettings = exports.usePatientSharing = void 0;
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) => client.acceptInvite(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, OvokPatientTelemetryHistory, OvokPatientTelemetryHistoryQuery } from "../client/patient/types";
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.usePatientDeviceTelemetryHistory = exports.usePatientDeviceTelemetry = exports.usePatientLatestObservations = exports.usePatientDashboard = exports.useCurrentPatientProfile = void 0;
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
- return (0, api_hooks_1.useOvokRequest)(load);
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) => client.redeemPatientSharingInvite(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) => client.revokePatientSharing(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)();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ovok/core",
3
- "version": "0.4.32",
3
+ "version": "0.4.34",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",