@medplum/core 0.9.1 → 0.9.2
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 +158 -29
- package/dist/cjs/index.js +54 -26
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -1
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/esm/index.js +54 -27
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/types/search.d.ts +2 -1
- package/dist/types/utils.d.ts +2 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
# Medplum
|
|
2
|
-
|
|
3
|
-
Medplum is a healthcare platform that helps you quickly develop high-quality compliant applications. Medplum includes a FHIR server, React component library, and developer app.
|
|
4
|
-
|
|
5
1
|
# Medplum JS Client Library
|
|
6
2
|
|
|
7
3
|
The Medplum JS Client Library is a pure TypeScript library for calling a FHIR server from the browser.
|
|
@@ -16,13 +12,25 @@ The Medplum JS Client Library is a pure TypeScript library for calling a FHIR se
|
|
|
16
12
|
|
|
17
13
|
## Installation
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
Add as a dependency:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @medplum/core
|
|
21
19
|
```
|
|
22
20
|
|
|
23
21
|
## Basic Usage
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
Create a new `MedplumClient`:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { MedplumClient } from '@medplum/core';
|
|
27
|
+
|
|
28
|
+
const medplum = new MedplumClient();
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Create a `MedplumClient` with additional configuration options:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
26
34
|
import { MedplumClient } from '@medplum/core';
|
|
27
35
|
|
|
28
36
|
const medplum = new MedplumClient({
|
|
@@ -31,12 +39,11 @@ const medplum = new MedplumClient({
|
|
|
31
39
|
});
|
|
32
40
|
```
|
|
33
41
|
|
|
34
|
-
##
|
|
35
|
-
|
|
36
|
-
Authenticate with a FHIR server via OAuth2 redirect:
|
|
42
|
+
## Authenticate with client credenials
|
|
37
43
|
|
|
38
|
-
```
|
|
39
|
-
medplum
|
|
44
|
+
```ts
|
|
45
|
+
const medplum = new MedplumClient();
|
|
46
|
+
medplum.clientCredentials(MY_CLIENT_ID, MY_CLIENT_SECRET);
|
|
40
47
|
```
|
|
41
48
|
|
|
42
49
|
## Authenticating with Medplum
|
|
@@ -50,25 +57,39 @@ Before you begin
|
|
|
50
57
|
|
|
51
58
|
After that, you can use the `startLogin()` method:
|
|
52
59
|
|
|
53
|
-
```
|
|
60
|
+
```ts
|
|
54
61
|
const loginResult = await medplum.startLogin(email, password, remember);
|
|
55
62
|
const profile = await medplum.processCode(loginResult.code);
|
|
56
63
|
console.log(profile);
|
|
57
64
|
```
|
|
58
65
|
|
|
66
|
+
## Authenticating with OAuth
|
|
67
|
+
|
|
68
|
+
Authenticate with a FHIR server via OAuth2 redirect:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
medplum.signInWithRedirect().then((user) => console.log(user));
|
|
72
|
+
```
|
|
73
|
+
|
|
59
74
|
## Search
|
|
60
75
|
|
|
61
76
|
Search for any resource using a [FHIR search](https://www.hl7.org/fhir/search.html) string:
|
|
62
77
|
|
|
63
|
-
```
|
|
78
|
+
```ts
|
|
79
|
+
search<T extends Resource>(query: string | SearchRequest, options: RequestInit = {}): Promise<Bundle<T>>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Example:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
64
85
|
medplum.search('Patient?given=eve').then((bundle) => {
|
|
65
86
|
bundle.entry.forEach((entry) => console.log(entry.resource));
|
|
66
87
|
});
|
|
67
88
|
```
|
|
68
89
|
|
|
69
|
-
|
|
90
|
+
Example using a structured object:
|
|
70
91
|
|
|
71
|
-
```
|
|
92
|
+
```ts
|
|
72
93
|
medplum
|
|
73
94
|
.search({
|
|
74
95
|
resourceType: 'Patient',
|
|
@@ -87,10 +108,16 @@ medplum
|
|
|
87
108
|
|
|
88
109
|
## Create
|
|
89
110
|
|
|
90
|
-
Create
|
|
111
|
+
[Create resource](https://www.hl7.org/fhir/http.html#create):
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
createResource<T extends Resource>(resource: T): Promise<T>
|
|
115
|
+
```
|
|
91
116
|
|
|
92
|
-
|
|
93
|
-
|
|
117
|
+
Example:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
medplum.createResource({
|
|
94
121
|
resourceType: 'Observation',
|
|
95
122
|
subject: {
|
|
96
123
|
reference: 'Patient/123',
|
|
@@ -102,26 +129,128 @@ medplum.create({
|
|
|
102
129
|
});
|
|
103
130
|
```
|
|
104
131
|
|
|
105
|
-
## Read
|
|
132
|
+
## Read a resource
|
|
133
|
+
|
|
134
|
+
[Read a resource by ID](https://www.hl7.org/fhir/http.html#read):
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
readResource<T extends Resource>(resourceType: string, id: string): Promise<T>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Example:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const patient = await medplum.readResource('Patient', '123');
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Read resource history
|
|
147
|
+
|
|
148
|
+
[Read resource history](https://www.hl7.org/fhir/http.html#history):
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
readHistory<T extends Resource>(resourceType: string, id: string): Promise<Bundle<T>>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Example:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
const historyBundle = await medplum.readHistory('Patient', '123');
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Read resource version
|
|
161
|
+
|
|
162
|
+
[Read a specific version](https://www.hl7.org/fhir/http.html#vread):
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
readVersion<T extends Resource>(resourceType: string, id: string, vid: string): Promise<T>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Example:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
const version = await medplum.readVersion('Patient', '123', '456');
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Update a resource
|
|
175
|
+
|
|
176
|
+
[Update a resource](https://www.hl7.org/fhir/http.html#update):
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
updateResource<T extends Resource>(resource: T): Promise<T>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Example:
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
const result = await medplum.updateResource({
|
|
186
|
+
resourceType: 'Patient',
|
|
187
|
+
id: '123',
|
|
188
|
+
name: [{
|
|
189
|
+
family: 'Smith',
|
|
190
|
+
given: ['John']
|
|
191
|
+
}]
|
|
192
|
+
});
|
|
193
|
+
console.log(result.meta.versionId);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Delete a resource
|
|
106
197
|
|
|
107
|
-
|
|
198
|
+
[Delete a resource](https://www.hl7.org/fhir/http.html#delete):
|
|
108
199
|
|
|
109
|
-
```
|
|
110
|
-
|
|
200
|
+
```ts
|
|
201
|
+
deleteResource(resourceType: string, id: string): Promise<any>
|
|
111
202
|
```
|
|
112
203
|
|
|
113
|
-
|
|
204
|
+
Example:
|
|
114
205
|
|
|
115
|
-
```
|
|
116
|
-
medplum.
|
|
206
|
+
```ts
|
|
207
|
+
await medplum.deleteResource('Patient', '123');
|
|
117
208
|
```
|
|
118
209
|
|
|
119
|
-
|
|
210
|
+
## Patch a resource
|
|
211
|
+
|
|
212
|
+
[Patch a resource](https://www.hl7.org/fhir/http.html#patch):
|
|
120
213
|
|
|
121
|
-
```
|
|
122
|
-
|
|
214
|
+
```ts
|
|
215
|
+
patchResource<T extends Resource>(resourceType: string, id: string, operations: Operation[]): Promise<T>
|
|
123
216
|
```
|
|
124
217
|
|
|
218
|
+
Example:
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
const result = await medplum.patchResource('Patient', '123', [
|
|
222
|
+
{op: 'replace', path: '/name/0/family', value: 'Smith'},
|
|
223
|
+
]);
|
|
224
|
+
console.log(result.meta.versionId);
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## GraphQL
|
|
228
|
+
|
|
229
|
+
[Execute a GraphQL query](https://www.hl7.org/fhir/graphql.html):
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
graphql(query: string, options?: RequestInit): Promise<any>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Example:
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
const result = await graphql(`
|
|
239
|
+
{
|
|
240
|
+
PatientList(name: "Alice") {
|
|
241
|
+
name {
|
|
242
|
+
given,
|
|
243
|
+
family
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
`);
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## About Medplum
|
|
251
|
+
|
|
252
|
+
Medplum is a healthcare platform that helps you quickly develop high-quality compliant applications. Medplum includes a FHIR server, React component library, and developer app.
|
|
253
|
+
|
|
125
254
|
## License
|
|
126
255
|
|
|
127
256
|
Apache 2.0. Copyright © Medplum 2022
|
package/dist/cjs/index.js
CHANGED
|
@@ -401,33 +401,59 @@
|
|
|
401
401
|
/**
|
|
402
402
|
* Resource equality.
|
|
403
403
|
* Ignores meta.versionId and meta.lastUpdated.
|
|
404
|
-
* See: https://dmitripavlutin.com/how-to-compare-objects-in-javascript/#4-deep-equality
|
|
405
404
|
* @param object1 The first object.
|
|
406
405
|
* @param object2 The second object.
|
|
407
406
|
* @returns True if the objects are equal.
|
|
408
407
|
*/
|
|
409
408
|
function deepEquals(object1, object2, path) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
409
|
+
if (object1 === object2) {
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
if (isEmpty(object1) && isEmpty(object2)) {
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
if (isEmpty(object1) || isEmpty(object2)) {
|
|
416
|
+
return false;
|
|
415
417
|
}
|
|
416
|
-
if (
|
|
418
|
+
if (Array.isArray(object1) && Array.isArray(object2)) {
|
|
419
|
+
return deepEqualsArray(object1, object2);
|
|
420
|
+
}
|
|
421
|
+
if (Array.isArray(object1) || Array.isArray(object2)) {
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
if (isObject(object1) && isObject(object2)) {
|
|
425
|
+
return deepEqualsObject(object1, object2, path);
|
|
426
|
+
}
|
|
427
|
+
if (isObject(object1) || isObject(object2)) {
|
|
417
428
|
return false;
|
|
418
429
|
}
|
|
419
|
-
|
|
430
|
+
return false;
|
|
431
|
+
}
|
|
432
|
+
function deepEqualsArray(array1, array2) {
|
|
433
|
+
if (array1.length !== array2.length) {
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
for (let i = 0; i < array1.length; i++) {
|
|
437
|
+
if (!deepEquals(array1[i], array2[i])) {
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return true;
|
|
442
|
+
}
|
|
443
|
+
function deepEqualsObject(object1, object2, path) {
|
|
444
|
+
const keySet = new Set();
|
|
445
|
+
Object.keys(object1).forEach((k) => keySet.add(k));
|
|
446
|
+
Object.keys(object2).forEach((k) => keySet.add(k));
|
|
447
|
+
if (path === 'meta') {
|
|
448
|
+
keySet.delete('versionId');
|
|
449
|
+
keySet.delete('lastUpdated');
|
|
450
|
+
keySet.delete('author');
|
|
451
|
+
}
|
|
452
|
+
for (const key of keySet) {
|
|
420
453
|
const val1 = object1[key];
|
|
421
454
|
const val2 = object2[key];
|
|
422
|
-
if (
|
|
423
|
-
|
|
424
|
-
return false;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
else {
|
|
428
|
-
if (val1 !== val2) {
|
|
429
|
-
return false;
|
|
430
|
-
}
|
|
455
|
+
if (!deepEquals(val1, val2, key)) {
|
|
456
|
+
return false;
|
|
431
457
|
}
|
|
432
458
|
}
|
|
433
459
|
return true;
|
|
@@ -725,6 +751,7 @@
|
|
|
725
751
|
}
|
|
726
752
|
}
|
|
727
753
|
|
|
754
|
+
const DEFAULT_SEARCH_COUNT = 20;
|
|
728
755
|
/**
|
|
729
756
|
* Search operators.
|
|
730
757
|
* These operators represent "modifiers" and "prefixes" in FHIR search.
|
|
@@ -792,15 +819,15 @@
|
|
|
792
819
|
let filters = undefined;
|
|
793
820
|
let sortRules = undefined;
|
|
794
821
|
let fields = undefined;
|
|
795
|
-
let
|
|
822
|
+
let offset = undefined;
|
|
796
823
|
let count = undefined;
|
|
797
824
|
let total = undefined;
|
|
798
825
|
params.forEach((value, key) => {
|
|
799
826
|
if (key === '_fields') {
|
|
800
827
|
fields = value.split(',');
|
|
801
828
|
}
|
|
802
|
-
else if (key === '
|
|
803
|
-
|
|
829
|
+
else if (key === '_offset') {
|
|
830
|
+
offset = parseInt(value);
|
|
804
831
|
}
|
|
805
832
|
else if (key === '_count') {
|
|
806
833
|
count = parseInt(value);
|
|
@@ -821,7 +848,7 @@
|
|
|
821
848
|
resourceType,
|
|
822
849
|
filters,
|
|
823
850
|
fields,
|
|
824
|
-
|
|
851
|
+
offset,
|
|
825
852
|
count,
|
|
826
853
|
total,
|
|
827
854
|
sortRules,
|
|
@@ -897,13 +924,13 @@
|
|
|
897
924
|
if (definition.sortRules && definition.sortRules.length > 0) {
|
|
898
925
|
params.push(formatSortRules(definition.sortRules));
|
|
899
926
|
}
|
|
900
|
-
if (definition.
|
|
901
|
-
params.push('
|
|
927
|
+
if (definition.offset !== undefined) {
|
|
928
|
+
params.push('_offset=' + definition.offset);
|
|
902
929
|
}
|
|
903
|
-
if (definition.count
|
|
930
|
+
if (definition.count !== undefined) {
|
|
904
931
|
params.push('_count=' + definition.count);
|
|
905
932
|
}
|
|
906
|
-
if (definition.total) {
|
|
933
|
+
if (definition.total !== undefined) {
|
|
907
934
|
params.push('_total=' + encodeURIComponent(definition.total));
|
|
908
935
|
}
|
|
909
936
|
if (params.length === 0) {
|
|
@@ -2120,7 +2147,7 @@
|
|
|
2120
2147
|
return undefined;
|
|
2121
2148
|
}
|
|
2122
2149
|
const obj = yield response.json();
|
|
2123
|
-
if (obj.resourceType === 'OperationOutcome' && !isOk(obj)) {
|
|
2150
|
+
if ((obj === null || obj === void 0 ? void 0 : obj.resourceType) === 'OperationOutcome' && !isOk(obj)) {
|
|
2124
2151
|
return Promise.reject(obj);
|
|
2125
2152
|
}
|
|
2126
2153
|
return obj;
|
|
@@ -2712,6 +2739,7 @@
|
|
|
2712
2739
|
}
|
|
2713
2740
|
|
|
2714
2741
|
exports.COMPONENT_SEPARATOR = COMPONENT_SEPARATOR;
|
|
2742
|
+
exports.DEFAULT_SEARCH_COUNT = DEFAULT_SEARCH_COUNT;
|
|
2715
2743
|
exports.FIELD_SEPARATOR = FIELD_SEPARATOR;
|
|
2716
2744
|
exports.Hl7Field = Hl7Field;
|
|
2717
2745
|
exports.Hl7Message = Hl7Message;
|