@ovok/core 0.4.21 → 0.4.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/auth/types/Account.d.ts +10 -0
- package/dist/client/auth/types/Account.js +2 -0
- package/dist/client/offline/offline-measurement-queue.d.ts +5 -2
- package/dist/client/offline/offline-measurement-queue.js +20 -7
- package/dist/client/ovok-client.d.ts +26 -1
- package/dist/client/ovok-client.js +164 -7
- package/dist/conformance/capability-requirements.js +1 -1
- package/dist/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ProfileResource } from "@medplum/core";
|
|
2
|
+
import { Project, Reference } from "@medplum/fhirtypes";
|
|
3
|
+
/** Safe account metadata for account pickers; authentication tokens are omitted. */
|
|
4
|
+
export interface OvokSavedAccount {
|
|
5
|
+
id: string;
|
|
6
|
+
profile: Reference<ProfileResource>;
|
|
7
|
+
project: Reference<Project>;
|
|
8
|
+
active: boolean;
|
|
9
|
+
expired: boolean;
|
|
10
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IClientStorage } from "@medplum/core";
|
|
2
2
|
import { Bundle, BundleEntry, Observation } from "@medplum/fhirtypes";
|
|
3
|
-
declare const
|
|
3
|
+
export declare const OFFLINE_MEASUREMENT_QUEUE_STORAGE_KEY = "ovok.core.offline-measurements";
|
|
4
4
|
declare const IDENTIFIER_SYSTEM = "https://api.ovok.com/fhir/StructureDefinition/offline-measurement-id";
|
|
5
5
|
export type OfflineMeasurementQueueOptions = {
|
|
6
6
|
enabled?: boolean;
|
|
@@ -8,6 +8,8 @@ export type OfflineMeasurementQueueOptions = {
|
|
|
8
8
|
maxRetries?: number;
|
|
9
9
|
retryBackoffMs?: number;
|
|
10
10
|
maxRetryBackoffMs?: number;
|
|
11
|
+
/** Returns the active account key. Queue items are delivered only to their owner. */
|
|
12
|
+
getOwnerKey?: () => string | undefined;
|
|
11
13
|
};
|
|
12
14
|
export type OfflineMeasurementFlushOptions = {
|
|
13
15
|
includeExhausted?: boolean;
|
|
@@ -30,6 +32,7 @@ export declare class OfflineMeasurementQueue {
|
|
|
30
32
|
private readonly maxRetries;
|
|
31
33
|
private readonly retryBackoffMs;
|
|
32
34
|
private readonly maxRetryBackoffMs;
|
|
35
|
+
private readonly getOwnerKey?;
|
|
33
36
|
private operation;
|
|
34
37
|
constructor(storage: IClientStorage, transport: MeasurementTransport, options?: OfflineMeasurementQueueOptions);
|
|
35
38
|
enqueueAndFlush: (observations: Observation[]) => Promise<{
|
|
@@ -42,4 +45,4 @@ export declare class OfflineMeasurementQueue {
|
|
|
42
45
|
private writeQueue;
|
|
43
46
|
private flushQueue;
|
|
44
47
|
}
|
|
45
|
-
export {
|
|
48
|
+
export { OFFLINE_MEASUREMENT_QUEUE_STORAGE_KEY as DEFAULT_OFFLINE_MEASUREMENT_QUEUE_KEY, IDENTIFIER_SYSTEM as OFFLINE_MEASUREMENT_IDENTIFIER_SYSTEM, entryForObservation, stableMeasurementId, };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.stableMeasurementId = exports.entryForObservation = exports.OFFLINE_MEASUREMENT_IDENTIFIER_SYSTEM = exports.DEFAULT_OFFLINE_MEASUREMENT_QUEUE_KEY = exports.OfflineMeasurementQueue = void 0;
|
|
4
|
-
|
|
5
|
-
exports.DEFAULT_OFFLINE_MEASUREMENT_QUEUE_KEY =
|
|
3
|
+
exports.stableMeasurementId = exports.entryForObservation = exports.OFFLINE_MEASUREMENT_IDENTIFIER_SYSTEM = exports.DEFAULT_OFFLINE_MEASUREMENT_QUEUE_KEY = exports.OfflineMeasurementQueue = exports.OFFLINE_MEASUREMENT_QUEUE_STORAGE_KEY = void 0;
|
|
4
|
+
exports.OFFLINE_MEASUREMENT_QUEUE_STORAGE_KEY = "ovok.core.offline-measurements";
|
|
5
|
+
exports.DEFAULT_OFFLINE_MEASUREMENT_QUEUE_KEY = exports.OFFLINE_MEASUREMENT_QUEUE_STORAGE_KEY;
|
|
6
6
|
const DEFAULT_MAX_RETRIES = 8;
|
|
7
7
|
const DEFAULT_RETRY_BACKOFF_MS = 5000;
|
|
8
8
|
const DEFAULT_MAX_RETRY_BACKOFF_MS = 60 * 60 * 1000;
|
|
@@ -82,14 +82,19 @@ class OfflineMeasurementQueue {
|
|
|
82
82
|
this.transport = transport;
|
|
83
83
|
this.operation = Promise.resolve();
|
|
84
84
|
this.enqueueAndFlush = (observations) => this.runExclusive(async () => {
|
|
85
|
-
var _a, _b;
|
|
85
|
+
var _a, _b, _c;
|
|
86
86
|
await ((_b = (_a = this.storage).getInitPromise) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
87
87
|
const queue = this.readQueue();
|
|
88
88
|
const entries = observations.map(entryForObservation);
|
|
89
|
-
const
|
|
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 });
|
|
90
94
|
if (!queue.some((item) => item.id === id)) {
|
|
91
95
|
queue.push({
|
|
92
96
|
id,
|
|
97
|
+
ownerKey,
|
|
93
98
|
queuedAt: new Date().toISOString(),
|
|
94
99
|
attempt: 0,
|
|
95
100
|
nextAttemptAt: 0,
|
|
@@ -130,6 +135,7 @@ class OfflineMeasurementQueue {
|
|
|
130
135
|
}
|
|
131
136
|
};
|
|
132
137
|
this.flushQueue = async (queue, options = {}) => {
|
|
138
|
+
var _a;
|
|
133
139
|
const result = {
|
|
134
140
|
attempted: 0,
|
|
135
141
|
saved: 0,
|
|
@@ -138,6 +144,7 @@ class OfflineMeasurementQueue {
|
|
|
138
144
|
responses: {},
|
|
139
145
|
};
|
|
140
146
|
const now = Date.now();
|
|
147
|
+
const ownerKey = (_a = this.getOwnerKey) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
141
148
|
let changed = false;
|
|
142
149
|
for (const item of [...queue]) {
|
|
143
150
|
if (item.exhausted && options.resetExhausted) {
|
|
@@ -156,6 +163,10 @@ class OfflineMeasurementQueue {
|
|
|
156
163
|
}
|
|
157
164
|
continue;
|
|
158
165
|
}
|
|
166
|
+
if (this.getOwnerKey && (!ownerKey || item.ownerKey !== ownerKey)) {
|
|
167
|
+
result.queued++;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
159
170
|
result.attempted++;
|
|
160
171
|
const attempt = item.attempt + 1;
|
|
161
172
|
try {
|
|
@@ -172,7 +183,7 @@ class OfflineMeasurementQueue {
|
|
|
172
183
|
result.responses[item.id] = response;
|
|
173
184
|
changed = true;
|
|
174
185
|
}
|
|
175
|
-
catch (
|
|
186
|
+
catch (_b) {
|
|
176
187
|
item.attempt = attempt;
|
|
177
188
|
item.exhausted = attempt >= this.maxRetries;
|
|
178
189
|
item.nextAttemptAt = item.exhausted
|
|
@@ -193,10 +204,12 @@ class OfflineMeasurementQueue {
|
|
|
193
204
|
}
|
|
194
205
|
return result;
|
|
195
206
|
};
|
|
196
|
-
this.storageKey =
|
|
207
|
+
this.storageKey =
|
|
208
|
+
(_a = options.storageKey) !== null && _a !== void 0 ? _a : exports.OFFLINE_MEASUREMENT_QUEUE_STORAGE_KEY;
|
|
197
209
|
this.maxRetries = Math.max(1, (_b = options.maxRetries) !== null && _b !== void 0 ? _b : DEFAULT_MAX_RETRIES);
|
|
198
210
|
this.retryBackoffMs = Math.max(1, (_c = options.retryBackoffMs) !== null && _c !== void 0 ? _c : DEFAULT_RETRY_BACKOFF_MS);
|
|
199
211
|
this.maxRetryBackoffMs = Math.max(this.retryBackoffMs, (_d = options.maxRetryBackoffMs) !== null && _d !== void 0 ? _d : DEFAULT_MAX_RETRY_BACKOFF_MS);
|
|
212
|
+
this.getOwnerKey = options.getOwnerKey;
|
|
200
213
|
}
|
|
201
214
|
}
|
|
202
215
|
exports.OfflineMeasurementQueue = OfflineMeasurementQueue;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { IClientStorage, MedplumClient, MedplumClientOptions, SubscriptionManager } from "@medplum/core";
|
|
1
|
+
import { IClientStorage, LoginState, MedplumClient, MedplumClientOptions, 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";
|
|
5
5
|
import * as authMethods from "./auth/methods";
|
|
6
|
+
import { OvokSavedAccount } from "./auth/types/Account";
|
|
6
7
|
import * as botMethods from "./bot/methods";
|
|
7
8
|
import * as changeHistoryMethods from "./change-history/methods";
|
|
8
9
|
import * as aiMethods from "./chat/ai/methods";
|
|
@@ -34,6 +35,7 @@ export type OvokFhirVersion = "R4" | "R5";
|
|
|
34
35
|
export declare class OvokClient extends MedplumClient {
|
|
35
36
|
protected socialLoginClientId: string;
|
|
36
37
|
clientStorage: IClientStorage | undefined;
|
|
38
|
+
private readonly hasExplicitStorageAdapter;
|
|
37
39
|
private readonly offlineQueueOptions;
|
|
38
40
|
private offlineMeasurementQueue;
|
|
39
41
|
/**
|
|
@@ -44,6 +46,19 @@ export declare class OvokClient extends MedplumClient {
|
|
|
44
46
|
socialLoginClientId?: string;
|
|
45
47
|
offlineQueue?: OfflineMeasurementQueueOptions;
|
|
46
48
|
});
|
|
49
|
+
/** Lists saved accounts without exposing their access or refresh tokens. */
|
|
50
|
+
getSavedAccounts(): OvokSavedAccount[];
|
|
51
|
+
/** Activates a previously saved account without asking for its password again. */
|
|
52
|
+
switchAccount(accountId: string): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Ends the selected account's current server session and removes its saved login.
|
|
55
|
+
* The account is retained locally if the server cannot confirm the logout.
|
|
56
|
+
*/
|
|
57
|
+
removeAccount(accountId: string): Promise<void>;
|
|
58
|
+
/** Removes every saved account and expiry marker from client storage. */
|
|
59
|
+
clearAllAccounts(): void;
|
|
60
|
+
/** Reauthentication clears the expired marker for the account that signed in. */
|
|
61
|
+
setActiveLogin(login: LoginState): Promise<void>;
|
|
47
62
|
/** Saves a measurement immediately, or durably queues it when the opt-in queue is enabled. */
|
|
48
63
|
saveMeasurement(params: GenerateObservationBodyParams): Promise<SaveObservationsResult>;
|
|
49
64
|
/** Reads Ovok's composed FHIR and public-route capability statement. */
|
|
@@ -55,6 +70,16 @@ export declare class OvokClient extends MedplumClient {
|
|
|
55
70
|
/** Flushes measurements queued while offline. Call this on connectivity/app-resume events. */
|
|
56
71
|
flushOfflineMeasurementQueue(options?: OfflineMeasurementFlushOptions): Promise<OfflineMeasurementFlushResult>;
|
|
57
72
|
private getOfflineMeasurementQueue;
|
|
73
|
+
/**
|
|
74
|
+
* Medplum clears its entire client storage after an unrecoverable 401. Keep
|
|
75
|
+
* saved accounts (marking only the active one expired) and queued measurements.
|
|
76
|
+
* Use clearAllAccounts() when the caller intends to remove all saved accounts.
|
|
77
|
+
*/
|
|
78
|
+
clear(): void;
|
|
79
|
+
private getLogin;
|
|
80
|
+
private getExpiredAccountIds;
|
|
81
|
+
private setAccountExpired;
|
|
82
|
+
private restoreActiveLogin;
|
|
58
83
|
private executeConditionalObservationCreates;
|
|
59
84
|
private executeObservationBundle;
|
|
60
85
|
private bindMethods;
|
|
@@ -63,16 +63,20 @@ const slimMethods = __importStar(require("./slim/methods"));
|
|
|
63
63
|
exports.MAX_CONDITIONAL_OBSERVATION_ENTRIES = 8;
|
|
64
64
|
var observation_bundle_utils_2 = require("./observation/observation-bundle-utils");
|
|
65
65
|
Object.defineProperty(exports, "MAX_OBSERVATION_BUNDLE_BYTES", { enumerable: true, get: function () { return observation_bundle_utils_2.MAX_OBSERVATION_BUNDLE_BYTES; } });
|
|
66
|
+
const LOGINS_STORAGE_KEY = "logins";
|
|
67
|
+
const EXPIRED_ACCOUNTS_STORAGE_KEY = "ovok.core.expired-accounts";
|
|
66
68
|
class OvokClient extends core_1.MedplumClient {
|
|
67
69
|
/**
|
|
68
70
|
* @param config - The configuration for the client.
|
|
69
71
|
* @param config.socialLoginClientId - The social login client id to use for the client.
|
|
70
72
|
*/
|
|
71
73
|
constructor(config) {
|
|
72
|
-
var _a, _b;
|
|
73
|
-
|
|
74
|
+
var _a, _b, _c;
|
|
75
|
+
const storage = (_a = config.storage) !== null && _a !== void 0 ? _a : new core_1.ClientStorage();
|
|
76
|
+
super({ ...config, storage });
|
|
74
77
|
this.socialLoginClientId = "";
|
|
75
|
-
this.
|
|
78
|
+
this.hasExplicitStorageAdapter = config.storage !== undefined;
|
|
79
|
+
this.socialLoginClientId = (_b = config.socialLoginClientId) !== null && _b !== void 0 ? _b : "";
|
|
76
80
|
this.bindMethods(authMethods);
|
|
77
81
|
this.bindMethods(observationMethods);
|
|
78
82
|
this.bindMethods(questionnaireResponseMethods);
|
|
@@ -96,8 +100,88 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
96
100
|
});
|
|
97
101
|
return (0, errors_1.isSignalsError)(mapped) ? mapped : (0, ovok_error_1.mapOvokApiError)(mapped);
|
|
98
102
|
});
|
|
99
|
-
this.clientStorage =
|
|
100
|
-
this.offlineQueueOptions = (
|
|
103
|
+
this.clientStorage = storage;
|
|
104
|
+
this.offlineQueueOptions = (_c = config.offlineQueue) !== null && _c !== void 0 ? _c : {};
|
|
105
|
+
}
|
|
106
|
+
/** Lists saved accounts without exposing their access or refresh tokens. */
|
|
107
|
+
getSavedAccounts() {
|
|
108
|
+
var _a, _b;
|
|
109
|
+
const activeAccountId = (_b = (_a = this.getActiveLogin()) === null || _a === void 0 ? void 0 : _a.profile) === null || _b === void 0 ? void 0 : _b.reference;
|
|
110
|
+
const expiredAccountIds = new Set(this.getExpiredAccountIds());
|
|
111
|
+
return this.getLogins().flatMap((login) => {
|
|
112
|
+
var _a;
|
|
113
|
+
const id = (_a = login.profile) === null || _a === void 0 ? void 0 : _a.reference;
|
|
114
|
+
return id
|
|
115
|
+
? [{
|
|
116
|
+
id,
|
|
117
|
+
profile: login.profile,
|
|
118
|
+
project: login.project,
|
|
119
|
+
active: id === activeAccountId,
|
|
120
|
+
expired: expiredAccountIds.has(id),
|
|
121
|
+
}]
|
|
122
|
+
: [];
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/** Activates a previously saved account without asking for its password again. */
|
|
126
|
+
async switchAccount(accountId) {
|
|
127
|
+
const login = this.getLogin(accountId);
|
|
128
|
+
if (!login) {
|
|
129
|
+
throw new Error(`No saved account found for ${accountId}.`);
|
|
130
|
+
}
|
|
131
|
+
if (this.getExpiredAccountIds().includes(accountId)) {
|
|
132
|
+
throw new Error("This account's session has expired. Sign in again.");
|
|
133
|
+
}
|
|
134
|
+
await this.setActiveLogin(login);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Ends the selected account's current server session and removes its saved login.
|
|
138
|
+
* The account is retained locally if the server cannot confirm the logout.
|
|
139
|
+
*/
|
|
140
|
+
async removeAccount(accountId) {
|
|
141
|
+
var _a, _b;
|
|
142
|
+
const login = this.getLogin(accountId);
|
|
143
|
+
if (!login) {
|
|
144
|
+
throw new Error(`No saved account found for ${accountId}.`);
|
|
145
|
+
}
|
|
146
|
+
const previousLogin = this.getActiveLogin();
|
|
147
|
+
try {
|
|
148
|
+
await this.setActiveLogin(login);
|
|
149
|
+
await this.delete("auth/session/current");
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (previousLogin && previousLogin.profile.reference !== accountId) {
|
|
153
|
+
await this.restoreActiveLogin(previousLogin);
|
|
154
|
+
}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
this.clearActiveLogin();
|
|
158
|
+
const remainingLogins = this.getLogins().filter((savedLogin) => savedLogin.profile.reference !== accountId);
|
|
159
|
+
(_a = this.clientStorage) === null || _a === void 0 ? void 0 : _a.setObject(LOGINS_STORAGE_KEY, remainingLogins);
|
|
160
|
+
this.setAccountExpired(accountId, false);
|
|
161
|
+
const nextLogin = (_b = ((previousLogin === null || previousLogin === void 0 ? void 0 : previousLogin.profile.reference) !== accountId ? previousLogin : undefined)) !== null && _b !== void 0 ? _b : remainingLogins[0];
|
|
162
|
+
if (nextLogin) {
|
|
163
|
+
await this.restoreActiveLogin(nextLogin);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/** Removes every saved account and expiry marker from client storage. */
|
|
167
|
+
clearAllAccounts() {
|
|
168
|
+
var _a;
|
|
169
|
+
const storage = this.clientStorage;
|
|
170
|
+
const queueKey = (_a = this.offlineQueueOptions.storageKey) !== null && _a !== void 0 ? _a : offline_1.OFFLINE_MEASUREMENT_QUEUE_STORAGE_KEY;
|
|
171
|
+
const queuedMeasurements = storage === null || storage === void 0 ? void 0 : storage.getObject(queueKey);
|
|
172
|
+
super.clear();
|
|
173
|
+
if (Array.isArray(queuedMeasurements)) {
|
|
174
|
+
storage === null || storage === void 0 ? void 0 : storage.setObject(queueKey, queuedMeasurements);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Reauthentication clears the expired marker for the account that signed in. */
|
|
178
|
+
async setActiveLogin(login) {
|
|
179
|
+
var _a;
|
|
180
|
+
await super.setActiveLogin(login);
|
|
181
|
+
const accountId = (_a = login.profile) === null || _a === void 0 ? void 0 : _a.reference;
|
|
182
|
+
if (accountId) {
|
|
183
|
+
this.setAccountExpired(accountId, false);
|
|
184
|
+
}
|
|
101
185
|
}
|
|
102
186
|
/** Saves a measurement immediately, or durably queues it when the opt-in queue is enabled. */
|
|
103
187
|
async saveMeasurement(params) {
|
|
@@ -145,12 +229,85 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
145
229
|
if (this.offlineQueueOptions.enabled !== true) {
|
|
146
230
|
return undefined;
|
|
147
231
|
}
|
|
148
|
-
if (!this.clientStorage) {
|
|
232
|
+
if (!this.clientStorage || !this.hasExplicitStorageAdapter) {
|
|
149
233
|
throw new Error("Offline measurement queue requires a durable client storage adapter.");
|
|
150
234
|
}
|
|
151
|
-
(_a = this.offlineMeasurementQueue) !== null && _a !== void 0 ? _a : (this.offlineMeasurementQueue = new offline_1.OfflineMeasurementQueue(this.clientStorage, (bundle) => this.executeObservationBundle(bundle),
|
|
235
|
+
(_a = this.offlineMeasurementQueue) !== null && _a !== void 0 ? _a : (this.offlineMeasurementQueue = new offline_1.OfflineMeasurementQueue(this.clientStorage, (bundle) => this.executeObservationBundle(bundle), {
|
|
236
|
+
...this.offlineQueueOptions,
|
|
237
|
+
getOwnerKey: () => {
|
|
238
|
+
var _a, _b, _c;
|
|
239
|
+
const login = this.getActiveLogin();
|
|
240
|
+
const profileReference = (_a = login === null || login === void 0 ? void 0 : login.profile) === null || _a === void 0 ? void 0 : _a.reference;
|
|
241
|
+
if (!profileReference) {
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
244
|
+
return [
|
|
245
|
+
this.getBaseUrl(),
|
|
246
|
+
(_c = (_b = login === null || login === void 0 ? void 0 : login.project) === null || _b === void 0 ? void 0 : _b.reference) !== null && _c !== void 0 ? _c : "",
|
|
247
|
+
profileReference,
|
|
248
|
+
].join("|");
|
|
249
|
+
},
|
|
250
|
+
}));
|
|
152
251
|
return this.offlineMeasurementQueue;
|
|
153
252
|
}
|
|
253
|
+
/**
|
|
254
|
+
* Medplum clears its entire client storage after an unrecoverable 401. Keep
|
|
255
|
+
* saved accounts (marking only the active one expired) and queued measurements.
|
|
256
|
+
* Use clearAllAccounts() when the caller intends to remove all saved accounts.
|
|
257
|
+
*/
|
|
258
|
+
clear() {
|
|
259
|
+
var _a, _b, _c;
|
|
260
|
+
const storage = this.clientStorage;
|
|
261
|
+
const logins = this.getLogins();
|
|
262
|
+
const activeAccountId = (_b = (_a = this.getActiveLogin()) === null || _a === void 0 ? void 0 : _a.profile) === null || _b === void 0 ? void 0 : _b.reference;
|
|
263
|
+
const expiredAccountIds = new Set(this.getExpiredAccountIds());
|
|
264
|
+
if (activeAccountId) {
|
|
265
|
+
expiredAccountIds.add(activeAccountId);
|
|
266
|
+
}
|
|
267
|
+
const queueKey = (_c = this.offlineQueueOptions.storageKey) !== null && _c !== void 0 ? _c : offline_1.OFFLINE_MEASUREMENT_QUEUE_STORAGE_KEY;
|
|
268
|
+
const queuedMeasurements = storage === null || storage === void 0 ? void 0 : storage.getObject(queueKey);
|
|
269
|
+
super.clear();
|
|
270
|
+
if (logins.length > 0) {
|
|
271
|
+
storage === null || storage === void 0 ? void 0 : storage.setObject(LOGINS_STORAGE_KEY, logins);
|
|
272
|
+
}
|
|
273
|
+
if (expiredAccountIds.size > 0) {
|
|
274
|
+
storage === null || storage === void 0 ? void 0 : storage.setObject(EXPIRED_ACCOUNTS_STORAGE_KEY, Array.from(expiredAccountIds));
|
|
275
|
+
}
|
|
276
|
+
if (Array.isArray(queuedMeasurements)) {
|
|
277
|
+
storage === null || storage === void 0 ? void 0 : storage.setObject(queueKey, queuedMeasurements);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
getLogin(accountId) {
|
|
281
|
+
return this.getLogins().find((login) => { var _a; return ((_a = login.profile) === null || _a === void 0 ? void 0 : _a.reference) === accountId; });
|
|
282
|
+
}
|
|
283
|
+
getExpiredAccountIds() {
|
|
284
|
+
var _a, _b;
|
|
285
|
+
return ((_b = (_a = this.clientStorage) === null || _a === void 0 ? void 0 : _a.getObject(EXPIRED_ACCOUNTS_STORAGE_KEY)) !== null && _b !== void 0 ? _b : []);
|
|
286
|
+
}
|
|
287
|
+
setAccountExpired(accountId, expired) {
|
|
288
|
+
var _a, _b;
|
|
289
|
+
const expiredAccountIds = new Set(this.getExpiredAccountIds());
|
|
290
|
+
if (expired) {
|
|
291
|
+
expiredAccountIds.add(accountId);
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
expiredAccountIds.delete(accountId);
|
|
295
|
+
}
|
|
296
|
+
if (expiredAccountIds.size > 0) {
|
|
297
|
+
(_a = this.clientStorage) === null || _a === void 0 ? void 0 : _a.setObject(EXPIRED_ACCOUNTS_STORAGE_KEY, Array.from(expiredAccountIds));
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
(_b = this.clientStorage) === null || _b === void 0 ? void 0 : _b.setString(EXPIRED_ACCOUNTS_STORAGE_KEY, undefined);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
async restoreActiveLogin(login) {
|
|
304
|
+
try {
|
|
305
|
+
await this.setActiveLogin(login);
|
|
306
|
+
}
|
|
307
|
+
catch (_a) {
|
|
308
|
+
// Keep the saved login available for a later retry if restoration is offline.
|
|
309
|
+
}
|
|
310
|
+
}
|
|
154
311
|
async executeConditionalObservationCreates(observations) {
|
|
155
312
|
const entries = observations.map(offline_1.entryForObservation);
|
|
156
313
|
return this.executeObservationBundle({
|
|
@@ -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.23",
|
|
52
52
|
},
|
|
53
53
|
fhirVersion: "4.0.1",
|
|
54
54
|
format: ["json"],
|
package/dist/index.d.ts
CHANGED
|
@@ -929,6 +929,7 @@ export * from "./client/errors/ovok-error";
|
|
|
929
929
|
export * from "./client/auth/errors";
|
|
930
930
|
export type { RegisterBody } from "./client/auth/types/RegisterBody";
|
|
931
931
|
export type { RegisterPractitionerBody } from "./client/auth/types/RegisterPractitionerBody";
|
|
932
|
+
export type { OvokSavedAccount } from "./client/auth/types/Account";
|
|
932
933
|
export { MAX_CONDITIONAL_OBSERVATION_ENTRIES, MAX_OBSERVATION_BUNDLE_BYTES, } from "./client/ovok-client";
|
|
933
934
|
export type { SaveObservationsResult } from "./client/ovok-client";
|
|
934
935
|
export * from "./client/offline";
|