@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 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
- npm install medplum
15
+ Add as a dependency:
16
+
17
+ ```bash
18
+ npm install @medplum/core
21
19
  ```
22
20
 
23
21
  ## Basic Usage
24
22
 
25
- ```typescript
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
- ## Authenticating with OAuth
35
-
36
- Authenticate with a FHIR server via OAuth2 redirect:
42
+ ## Authenticate with client credenials
37
43
 
38
- ```typescript
39
- medplum.signInWithRedirect().then((user) => console.log(user));
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
- ```typescript
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
- ```typescript
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
- Search using a structured object:
90
+ Example using a structured object:
70
91
 
71
- ```typescript
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 a new resource:
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
- ```typescript
93
- medplum.create({
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
- Read a resource by ID:
198
+ [Delete a resource](https://www.hl7.org/fhir/http.html#delete):
108
199
 
109
- ```typescript
110
- medplum.read('Patient', '123');
200
+ ```ts
201
+ deleteResource(resourceType: string, id: string): Promise<any>
111
202
  ```
112
203
 
113
- Read resource history:
204
+ Example:
114
205
 
115
- ```typescript
116
- medplum.readHistory('Patient', '123');
206
+ ```ts
207
+ await medplum.deleteResource('Patient', '123');
117
208
  ```
118
209
 
119
- Read a specific version:
210
+ ## Patch a resource
211
+
212
+ [Patch a resource](https://www.hl7.org/fhir/http.html#patch):
120
213
 
121
- ```typescript
122
- medplum.readVersion('Patient', '123', '456');
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 &copy; 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
- let keys1 = Object.keys(object1);
411
- let keys2 = Object.keys(object2);
412
- if (path === 'meta') {
413
- keys1 = keys1.filter((k) => k !== 'versionId' && k !== 'lastUpdated' && k !== 'author');
414
- keys2 = keys2.filter((k) => k !== 'versionId' && k !== 'lastUpdated' && k !== 'author');
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 (keys1.length !== keys2.length) {
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
- for (const key of keys1) {
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 (isObject(val1) && isObject(val2)) {
423
- if (!deepEquals(val1, val2, key)) {
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 page = undefined;
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 === '_page') {
803
- page = parseInt(value);
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
- page,
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.page && definition.page > 0) {
901
- params.push('_page=' + definition.page);
927
+ if (definition.offset !== undefined) {
928
+ params.push('_offset=' + definition.offset);
902
929
  }
903
- if (definition.count && definition.count > 0) {
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;