@openmrs/esm-api 4.3.2-pre.660 → 4.3.2-pre.662
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/.turbo/turbo-build.log +9 -8
- package/dist/openmrs-esm-api.js +1 -1
- package/dist/openmrs-esm-api.js.map +1 -1
- package/jest.config.js +1 -0
- package/package.json +7 -6
- package/src/index.ts +0 -1
- package/src/openmrs-fetch.ts +24 -5
- package/src/public.ts +0 -1
- package/src/shared-api-objects/current-patient.test.ts +25 -25
- package/src/shared-api-objects/current-patient.ts +42 -11
- package/src/types/fhir.ts +0 -72
- package/src/fhir.ts +0 -74
package/jest.config.js
CHANGED
|
@@ -8,6 +8,7 @@ module.exports = {
|
|
|
8
8
|
"<rootDir>/__mocks__/openmrs-esm-error-handling.mock.ts",
|
|
9
9
|
"@openmrs/esm-config": "<rootDir>/__mocks__/openmrs-esm-config.mock.ts",
|
|
10
10
|
"single-spa": "<rootDir>/__mocks__/single-spa.mock.ts",
|
|
11
|
+
dexie: require.resolve("dexie"),
|
|
11
12
|
},
|
|
12
13
|
testEnvironment: "jsdom",
|
|
13
14
|
testEnvironmentOptions: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-api",
|
|
3
|
-
"version": "4.3.2-pre.
|
|
3
|
+
"version": "4.3.2-pre.662",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"description": "The javascript module for interacting with the OpenMRS API",
|
|
6
6
|
"browser": "dist/openmrs-esm-api.js",
|
|
@@ -41,13 +41,14 @@
|
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"@openmrs/esm-config": "4.x",
|
|
44
|
-
"@openmrs/esm-error-handling": "4.x"
|
|
44
|
+
"@openmrs/esm-error-handling": "4.x",
|
|
45
|
+
"@openmrs/esm-offline": "4.x"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"@openmrs/esm-config": "^4.3.2-pre.
|
|
48
|
-
"@openmrs/esm-error-handling": "^4.3.2-pre.
|
|
49
|
-
"@openmrs/esm-state": "^4.3.2-pre.
|
|
48
|
+
"@openmrs/esm-config": "^4.3.2-pre.662",
|
|
49
|
+
"@openmrs/esm-error-handling": "^4.3.2-pre.662",
|
|
50
|
+
"@openmrs/esm-state": "^4.3.2-pre.662",
|
|
50
51
|
"rxjs": "^6.5.3"
|
|
51
52
|
},
|
|
52
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "1e1ab6761ff3726c7e0eee55373b1bf4a0d97b99"
|
|
53
54
|
}
|
package/src/index.ts
CHANGED
package/src/openmrs-fetch.ts
CHANGED
|
@@ -4,7 +4,11 @@ import isPlainObject from "lodash-es/isPlainObject";
|
|
|
4
4
|
import { getConfig, navigate } from "@openmrs/esm-config";
|
|
5
5
|
import { FetchResponse } from "./types";
|
|
6
6
|
|
|
7
|
-
export const
|
|
7
|
+
export const restBaseUrl = "/ws/rest/v1/";
|
|
8
|
+
|
|
9
|
+
export const fhirBaseUrl = "/ws/fhir2/R4";
|
|
10
|
+
|
|
11
|
+
export const sessionEndpoint = `${restBaseUrl}session`;
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* Append `path` to the OpenMRS SPA base.
|
|
@@ -92,9 +96,13 @@ export function openmrsFetch<T = any>(
|
|
|
92
96
|
);
|
|
93
97
|
}
|
|
94
98
|
|
|
99
|
+
// ensure path starts with /
|
|
100
|
+
if (path[0] !== "/") {
|
|
101
|
+
path = "/" + path;
|
|
102
|
+
}
|
|
103
|
+
|
|
95
104
|
// Prefix the url with the openmrs spa base
|
|
96
|
-
|
|
97
|
-
const url = makeUrl(path);
|
|
105
|
+
let url: string = makeUrl(path);
|
|
98
106
|
|
|
99
107
|
// We're going to need some headers
|
|
100
108
|
if (!fetchInit.headers) {
|
|
@@ -126,10 +134,21 @@ export function openmrsFetch<T = any>(
|
|
|
126
134
|
* header. Returning that header is useful when using the API, but
|
|
127
135
|
* not from a UI.
|
|
128
136
|
*/
|
|
129
|
-
if (
|
|
137
|
+
if (
|
|
138
|
+
path.startsWith(restBaseUrl) &&
|
|
139
|
+
typeof fetchInit.headers["Disable-WWW-Authenticate"] === "undefined"
|
|
140
|
+
) {
|
|
130
141
|
fetchInit.headers["Disable-WWW-Authenticate"] = "true";
|
|
131
142
|
}
|
|
132
143
|
|
|
144
|
+
if (path.startsWith(fhirBaseUrl)) {
|
|
145
|
+
const urlUrl = new URL(url, window.location.toString());
|
|
146
|
+
if (!urlUrl.searchParams.has("_summary")) {
|
|
147
|
+
urlUrl.searchParams.set("_summary", "data");
|
|
148
|
+
url = urlUrl.toString();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
133
152
|
/* We capture the stacktrace before making the request, so that if an error occurs we can
|
|
134
153
|
* log a full stacktrace that includes the code that made the request and handled the response
|
|
135
154
|
* Otherwise, we could run into situations where the stacktrace doesn't even show which code
|
|
@@ -303,7 +322,7 @@ export class OpenmrsFetchError extends Error {
|
|
|
303
322
|
responseBody: string | FetchResponseJson | null;
|
|
304
323
|
}
|
|
305
324
|
|
|
306
|
-
interface FetchConfig extends Omit<
|
|
325
|
+
export interface FetchConfig extends Omit<RequestInit, "body" | "headers"> {
|
|
307
326
|
headers?: FetchHeaders;
|
|
308
327
|
body?: FetchBody | string;
|
|
309
328
|
}
|
package/src/public.ts
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
+
import { fhirBaseUrl, openmrsFetch } from "../openmrs-fetch";
|
|
1
2
|
import { fetchCurrentPatient } from "./current-patient";
|
|
2
|
-
import { fhir } from "../fhir";
|
|
3
3
|
|
|
4
|
-
jest.mock("../
|
|
5
|
-
|
|
6
|
-
read: jest.fn(),
|
|
7
|
-
},
|
|
4
|
+
jest.mock("../openmrs-fetch", () => ({
|
|
5
|
+
openmrsFetch: jest.fn(),
|
|
8
6
|
}));
|
|
9
7
|
|
|
10
8
|
describe("current patient", () => {
|
|
11
9
|
beforeEach(() => {
|
|
12
|
-
(
|
|
10
|
+
(openmrsFetch as jest.MockedFunction<any>).mockReset();
|
|
13
11
|
});
|
|
14
12
|
|
|
15
13
|
it("fetches the correct patient from a patient chart URL", () => {
|
|
16
|
-
(
|
|
14
|
+
(openmrsFetch as jest.MockedFunction<any>).mockReturnValueOnce(
|
|
17
15
|
Promise.resolve({
|
|
18
16
|
data: {},
|
|
19
17
|
})
|
|
20
18
|
);
|
|
21
19
|
|
|
22
|
-
return fetchCurrentPatient("12").then(() => {
|
|
23
|
-
expect(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
return fetchCurrentPatient("12", undefined, false).then(() => {
|
|
21
|
+
expect(openmrsFetch as jest.MockedFunction<any>).toHaveBeenCalledWith(
|
|
22
|
+
`${fhirBaseUrl}/Patient/12`,
|
|
23
|
+
undefined
|
|
24
|
+
);
|
|
27
25
|
});
|
|
28
26
|
});
|
|
29
27
|
|
|
30
28
|
it("fetches the correct patient from the patient home URL", () => {
|
|
31
|
-
(
|
|
29
|
+
(openmrsFetch as jest.MockedFunction<any>).mockReturnValueOnce(
|
|
32
30
|
Promise.resolve({
|
|
33
31
|
data: {},
|
|
34
32
|
})
|
|
35
33
|
);
|
|
36
34
|
|
|
37
|
-
return fetchCurrentPatient("34").then(() => {
|
|
38
|
-
expect(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
return fetchCurrentPatient("34", undefined, false).then(() => {
|
|
36
|
+
expect(openmrsFetch as jest.MockedFunction<any>).toHaveBeenCalledWith(
|
|
37
|
+
`${fhirBaseUrl}/Patient/34`,
|
|
38
|
+
undefined
|
|
39
|
+
);
|
|
42
40
|
});
|
|
43
41
|
});
|
|
44
42
|
|
|
45
43
|
it("can handle dashes and alphanumeric characters in the patient uuid", () => {
|
|
46
|
-
(
|
|
44
|
+
(openmrsFetch as jest.MockedFunction<any>).mockReturnValueOnce(
|
|
47
45
|
Promise.resolve({
|
|
48
46
|
data: {},
|
|
49
47
|
})
|
|
50
48
|
);
|
|
51
49
|
|
|
52
|
-
return fetchCurrentPatient("34-asdsd-234243h342").then(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
return fetchCurrentPatient("34-asdsd-234243h342", undefined, false).then(
|
|
51
|
+
() => {
|
|
52
|
+
expect(openmrsFetch as jest.MockedFunction<any>).toHaveBeenCalledWith(
|
|
53
|
+
`${fhirBaseUrl}/Patient/34-asdsd-234243h342`,
|
|
54
|
+
undefined
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
58
|
});
|
|
59
59
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** @module @category API */
|
|
2
|
-
import {
|
|
2
|
+
import { getSynchronizationItems } from "@openmrs/esm-offline";
|
|
3
|
+
import { FetchConfig, fhirBaseUrl, openmrsFetch } from "../openmrs-fetch";
|
|
3
4
|
import { FetchResponse } from "../types";
|
|
4
5
|
|
|
5
6
|
export type CurrentPatient = fhir.Patient | FetchResponse<fhir.Patient>;
|
|
6
|
-
|
|
7
7
|
export interface CurrentPatientOptions {
|
|
8
8
|
includeConfig?: boolean;
|
|
9
9
|
}
|
|
@@ -18,17 +18,48 @@ export interface OnlyThePatient extends CurrentPatientOptions {
|
|
|
18
18
|
|
|
19
19
|
export type PatientUuid = string | null;
|
|
20
20
|
|
|
21
|
-
export function fetchCurrentPatient(
|
|
21
|
+
export async function fetchCurrentPatient(
|
|
22
22
|
patientUuid: PatientUuid,
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
fetchInit?: FetchConfig,
|
|
24
|
+
includeOfflinePatients: boolean = true
|
|
25
|
+
): Promise<fhir.Patient | null> {
|
|
25
26
|
if (patientUuid) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
let err: Error | null = null;
|
|
28
|
+
const [onlinePatient, offlinePatient] = await Promise.all([
|
|
29
|
+
openmrsFetch<fhir.Patient>(
|
|
30
|
+
`${fhirBaseUrl}/Patient/${patientUuid}`,
|
|
31
|
+
fetchInit
|
|
32
|
+
).catch<FetchResponse<fhir.Patient>>((e) => (err = e)),
|
|
33
|
+
includeOfflinePatients
|
|
34
|
+
? getOfflineRegisteredPatientAsFhirPatient(patientUuid)
|
|
35
|
+
: Promise.resolve(null),
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
if (onlinePatient.ok) {
|
|
39
|
+
return onlinePatient.data;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (offlinePatient) {
|
|
43
|
+
return offlinePatient;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (err) {
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
31
49
|
}
|
|
32
50
|
|
|
33
|
-
return
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function getOfflineRegisteredPatientAsFhirPatient(
|
|
55
|
+
patientUuid: string
|
|
56
|
+
): Promise<fhir.Patient | null> {
|
|
57
|
+
const patientRegistrationSyncItems = await getSynchronizationItems<{
|
|
58
|
+
fhirPatient: fhir.Patient;
|
|
59
|
+
}>("patient-registration");
|
|
60
|
+
const patientSyncItem = patientRegistrationSyncItems.find(
|
|
61
|
+
(item) => item.fhirPatient.id === patientUuid
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
return patientSyncItem?.fhirPatient ?? null;
|
|
34
65
|
}
|
package/src/types/fhir.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import { FetchHeaders } from "../openmrs-fetch";
|
|
2
|
-
|
|
3
1
|
/*
|
|
4
2
|
Originally taken from https://github.com/FHIR/fhir.js/blob/ec82ccfc125e05dbb645f47c100fe60f2c34bb73/src/fhir.d.ts
|
|
5
3
|
Has been adapted to be even better - if we can get fhir.js to publish a good version to npm with better typedefs,
|
|
6
4
|
we can remove this file in favor of the one they maintain
|
|
7
5
|
*/
|
|
8
6
|
|
|
9
|
-
type ClientFn = (...args: any[]) => Promise<{ data: any }>;
|
|
10
7
|
export type ResourceName =
|
|
11
8
|
| "DomainResource"
|
|
12
9
|
| "Organization"
|
|
@@ -103,72 +100,3 @@ export type ResourceName =
|
|
|
103
100
|
| "Binary"
|
|
104
101
|
| "Bundle"
|
|
105
102
|
| "Parameters";
|
|
106
|
-
interface QueryOptions {
|
|
107
|
-
$include?: { [key: string]: string | string[] };
|
|
108
|
-
[key: string]: any;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
declare function Create<T extends fhir.DomainResource>(content: {
|
|
112
|
-
resource: T;
|
|
113
|
-
}): Promise<{ data: T }>;
|
|
114
|
-
declare function Create(content: {
|
|
115
|
-
type: "Binary";
|
|
116
|
-
data: Buffer;
|
|
117
|
-
}): Promise<{ data: fhir.Binary }>;
|
|
118
|
-
declare function Create<T extends fhir.DomainResource>(content: {
|
|
119
|
-
type: ResourceName;
|
|
120
|
-
data: T;
|
|
121
|
-
}): Promise<{ data: T }>;
|
|
122
|
-
|
|
123
|
-
declare function Read<T extends fhir.DomainResource>(content: {
|
|
124
|
-
type: ResourceName;
|
|
125
|
-
id?: string;
|
|
126
|
-
patient?: string;
|
|
127
|
-
headers?: FetchHeaders;
|
|
128
|
-
}): Promise<{ data: T }>;
|
|
129
|
-
|
|
130
|
-
declare function Patch(content: {
|
|
131
|
-
type: ResourceName;
|
|
132
|
-
id: string;
|
|
133
|
-
data: Array<{
|
|
134
|
-
op: "replace" | "add" | "remove";
|
|
135
|
-
path: string;
|
|
136
|
-
value: string | object;
|
|
137
|
-
}>;
|
|
138
|
-
}): Promise<{ data: fhir.OperationOutcome }>;
|
|
139
|
-
|
|
140
|
-
declare function Update<T extends fhir.DomainResource>(content: {
|
|
141
|
-
resource: T;
|
|
142
|
-
}): Promise<{ data: T }>;
|
|
143
|
-
|
|
144
|
-
declare function Search(content: {
|
|
145
|
-
type: ResourceName;
|
|
146
|
-
count?: number;
|
|
147
|
-
query?: QueryOptions;
|
|
148
|
-
}): Promise<{ data: fhir.Bundle }>;
|
|
149
|
-
|
|
150
|
-
declare function NextPage(content: {
|
|
151
|
-
type: ResourceName;
|
|
152
|
-
bundle: fhir.Bundle;
|
|
153
|
-
}): Promise<{ data: fhir.Bundle }>;
|
|
154
|
-
|
|
155
|
-
export interface FhirClient {
|
|
156
|
-
conformance: ClientFn;
|
|
157
|
-
document: ClientFn;
|
|
158
|
-
profile: ClientFn;
|
|
159
|
-
transaction: ClientFn;
|
|
160
|
-
history: ClientFn;
|
|
161
|
-
typeHistory: ClientFn;
|
|
162
|
-
resourceHistory: ClientFn;
|
|
163
|
-
read: typeof Read;
|
|
164
|
-
vread: ClientFn;
|
|
165
|
-
delete: ClientFn;
|
|
166
|
-
create: typeof Create;
|
|
167
|
-
validate: ClientFn;
|
|
168
|
-
search: typeof Search;
|
|
169
|
-
update: typeof Update;
|
|
170
|
-
nextPage: typeof NextPage;
|
|
171
|
-
prevPage: ClientFn;
|
|
172
|
-
resolve: ClientFn;
|
|
173
|
-
patch: typeof Patch;
|
|
174
|
-
}
|
package/src/fhir.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/** @module @category API */
|
|
2
|
-
import { openmrsFetch, FetchHeaders, OpenmrsFetchError } from "./openmrs-fetch";
|
|
3
|
-
import type { ResourceName } from "./types/fhir";
|
|
4
|
-
|
|
5
|
-
export const fhirBaseUrl = `/ws/fhir2/R4`;
|
|
6
|
-
|
|
7
|
-
const openmrsFhirAdapter = {
|
|
8
|
-
http(requestObj: FHIRRequestObj) {
|
|
9
|
-
return openmrsFetch(requestObj.url, {
|
|
10
|
-
method: requestObj.method,
|
|
11
|
-
headers: requestObj.headers,
|
|
12
|
-
}).then(
|
|
13
|
-
(response) => {
|
|
14
|
-
return {
|
|
15
|
-
status: response.status,
|
|
16
|
-
headers: response.headers,
|
|
17
|
-
data: response.data,
|
|
18
|
-
config: requestObj,
|
|
19
|
-
};
|
|
20
|
-
},
|
|
21
|
-
(err: OpenmrsFetchError) => {
|
|
22
|
-
return {
|
|
23
|
-
status: err.response.status,
|
|
24
|
-
headers: err.response.headers,
|
|
25
|
-
data: err.responseBody as any,
|
|
26
|
-
config: requestObj,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
);
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* The `fhir` object is replicates the API from [fhir.js](https://github.com/FHIR/fhir.js)
|
|
35
|
-
* that can be used to call FHIR-compliant OpenMRS APIs. See
|
|
36
|
-
* [the docs for fhir.js](https://github.com/FHIR/fhir.js) for more info
|
|
37
|
-
* and example usage.
|
|
38
|
-
*
|
|
39
|
-
* This object should be considered deprecated and may be removed from a future version
|
|
40
|
-
* of the framework.
|
|
41
|
-
*
|
|
42
|
-
* @category API
|
|
43
|
-
* @deprecated
|
|
44
|
-
*/
|
|
45
|
-
export const fhir = {
|
|
46
|
-
read: <T>(
|
|
47
|
-
options: FHIRRequestOptions
|
|
48
|
-
): Promise<{
|
|
49
|
-
status: number;
|
|
50
|
-
headers: Headers;
|
|
51
|
-
data: T;
|
|
52
|
-
config: FHIRRequestObj;
|
|
53
|
-
}> => {
|
|
54
|
-
return openmrsFhirAdapter.http({
|
|
55
|
-
url: `${fhirBaseUrl}/${options.type}/${options.patient}`,
|
|
56
|
-
method: "GET",
|
|
57
|
-
headers: options.headers ?? {},
|
|
58
|
-
});
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
/** @deprecated */
|
|
63
|
-
export interface FHIRRequestOptions {
|
|
64
|
-
type: ResourceName;
|
|
65
|
-
patient: string;
|
|
66
|
-
headers?: FetchHeaders;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** @deprecated */
|
|
70
|
-
export interface FHIRRequestObj {
|
|
71
|
-
url: string;
|
|
72
|
-
method: string;
|
|
73
|
-
headers: FetchHeaders;
|
|
74
|
-
}
|