@medplum/core 0.3.0 → 0.5.0

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.
Files changed (50) hide show
  1. package/README.md +5 -3
  2. package/dist/cjs/index.js +1842 -0
  3. package/dist/cjs/index.js.map +1 -0
  4. package/dist/cjs/index.min.js +16 -0
  5. package/dist/cjs/index.min.js.map +1 -0
  6. package/dist/esm/index.js +1792 -0
  7. package/dist/esm/index.js.map +1 -0
  8. package/dist/esm/index.min.js +16 -0
  9. package/dist/esm/index.min.js.map +1 -0
  10. package/dist/{cache.d.ts → types/cache.d.ts} +1 -3
  11. package/dist/{client.d.ts → types/client.d.ts} +54 -69
  12. package/dist/{crypto.d.ts → types/crypto.d.ts} +0 -0
  13. package/dist/{eventtarget.d.ts → types/eventtarget.d.ts} +3 -3
  14. package/dist/{format.d.ts → types/format.d.ts} +0 -0
  15. package/dist/{index.d.ts → types/index.d.ts} +0 -0
  16. package/dist/types/jwt.d.ts +5 -0
  17. package/dist/{outcomes.d.ts → types/outcomes.d.ts} +6 -1
  18. package/dist/{search.d.ts → types/search.d.ts} +4 -0
  19. package/dist/{searchparams.d.ts → types/searchparams.d.ts} +2 -1
  20. package/dist/{storage.d.ts → types/storage.d.ts} +2 -2
  21. package/dist/{types.d.ts → types/types.d.ts} +18 -3
  22. package/dist/{utils.d.ts → types/utils.d.ts} +6 -0
  23. package/package.json +11 -5
  24. package/dist/cache.js +0 -39
  25. package/dist/cache.js.map +0 -1
  26. package/dist/client.js +0 -572
  27. package/dist/client.js.map +0 -1
  28. package/dist/crypto.js +0 -33
  29. package/dist/crypto.js.map +0 -1
  30. package/dist/eventtarget.js +0 -38
  31. package/dist/eventtarget.js.map +0 -1
  32. package/dist/format.js +0 -56
  33. package/dist/format.js.map +0 -1
  34. package/dist/index.js +0 -20
  35. package/dist/index.js.map +0 -1
  36. package/dist/jwt.d.ts +0 -5
  37. package/dist/jwt.js +0 -28
  38. package/dist/jwt.js.map +0 -1
  39. package/dist/outcomes.js +0 -154
  40. package/dist/outcomes.js.map +0 -1
  41. package/dist/search.js +0 -120
  42. package/dist/search.js.map +0 -1
  43. package/dist/searchparams.js +0 -128
  44. package/dist/searchparams.js.map +0 -1
  45. package/dist/storage.js +0 -90
  46. package/dist/storage.js.map +0 -1
  47. package/dist/types.js +0 -171
  48. package/dist/types.js.map +0 -1
  49. package/dist/utils.js +0 -239
  50. package/dist/utils.js.map +0 -1
package/dist/utils.js DELETED
@@ -1,239 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isLowerCase = exports.capitalize = exports.arrayBufferToBase64 = exports.arrayBufferToHex = exports.deepEquals = exports.stringify = exports.getDateProperty = exports.getImageSrc = exports.getDisplayString = exports.isProfileResource = exports.getReferenceString = exports.createReference = void 0;
4
- const format_1 = require("./format");
5
- /**
6
- * Creates a reference resource.
7
- * @param resource The FHIR reesource.
8
- * @returns A reference resource.
9
- */
10
- function createReference(resource) {
11
- const reference = getReferenceString(resource);
12
- const display = getDisplayString(resource);
13
- return display === reference ? { reference } : { reference, display };
14
- }
15
- exports.createReference = createReference;
16
- /**
17
- * Returns a reference string for a resource.
18
- * @param resource The FHIR resource.
19
- * @returns A reference string of the form resourceType/id.
20
- */
21
- function getReferenceString(resource) {
22
- return resource.resourceType + '/' + resource.id;
23
- }
24
- exports.getReferenceString = getReferenceString;
25
- /**
26
- * Returns true if the resource is a "ProfileResource".
27
- * @param resource The FHIR resource.
28
- * @returns True if the resource is a "ProfileResource".
29
- */
30
- function isProfileResource(resource) {
31
- return (resource.resourceType === 'Patient' ||
32
- resource.resourceType === 'Practitioner' ||
33
- resource.resourceType === 'RelatedPerson');
34
- }
35
- exports.isProfileResource = isProfileResource;
36
- /**
37
- * Returns a display string for the resource.
38
- * @param resource The input resource.
39
- * @return Human friendly display string.
40
- */
41
- function getDisplayString(resource) {
42
- if (isProfileResource(resource)) {
43
- const profileName = getProfileResourceDisplayString(resource);
44
- if (profileName) {
45
- return profileName;
46
- }
47
- }
48
- if (resource.resourceType === 'Device') {
49
- const deviceName = getDeviceDisplayString(resource);
50
- if (deviceName) {
51
- return deviceName;
52
- }
53
- }
54
- if (resource.resourceType === 'User') {
55
- if (resource.email) {
56
- return resource.email;
57
- }
58
- }
59
- const simpleName = resource.name;
60
- if (simpleName && typeof simpleName === 'string') {
61
- return simpleName;
62
- }
63
- return getReferenceString(resource);
64
- }
65
- exports.getDisplayString = getDisplayString;
66
- /**
67
- * Returns a display string for a profile resource if one is found.
68
- * @param resource The profile resource.
69
- * @returns The display name if one is found.
70
- */
71
- function getProfileResourceDisplayString(resource) {
72
- const names = resource.name;
73
- if (names && names.length > 0) {
74
- return (0, format_1.formatHumanName)(names[0]);
75
- }
76
- return undefined;
77
- }
78
- /**
79
- * Returns a display string for a device resource if one is found.
80
- * @param device The device resource.
81
- * @returns The display name if one is found.
82
- */
83
- function getDeviceDisplayString(device) {
84
- const names = device.deviceName;
85
- if (names && names.length > 0) {
86
- return names[0].name;
87
- }
88
- return undefined;
89
- }
90
- /**
91
- * Returns an image URL for the resource, if one is available.
92
- * @param resource The input resource.
93
- * @returns The image URL for the resource or undefined.
94
- */
95
- function getImageSrc(resource) {
96
- if (isProfileResource(resource)) {
97
- const photos = resource.photo;
98
- if (photos) {
99
- for (const photo of photos) {
100
- if (photo.url && photo.contentType && photo.contentType.startsWith('image/')) {
101
- return photo.url;
102
- }
103
- }
104
- }
105
- }
106
- return undefined;
107
- }
108
- exports.getImageSrc = getImageSrc;
109
- /**
110
- * Returns a Date property as a Date.
111
- * When working with JSON objects, Dates are often serialized as ISO-8601 strings.
112
- * When that happens, we need to safely convert to a proper Date object.
113
- * @param date The date property value, which could be a string or a Date object.
114
- * @returns A Date object.
115
- */
116
- function getDateProperty(date) {
117
- return date ? new Date(date) : undefined;
118
- }
119
- exports.getDateProperty = getDateProperty;
120
- /**
121
- * FHIR JSON stringify.
122
- * Removes properties with empty string values.
123
- * Removes objects with zero properties.
124
- * See: https://www.hl7.org/fhir/json.html
125
- * @param value The input value.
126
- * @param pretty Optional flag to pretty-print the JSON.
127
- * @returns The resulting JSON string.
128
- */
129
- function stringify(value, pretty) {
130
- return JSON.stringify(value, stringifyReplacer, pretty ? 2 : undefined);
131
- }
132
- exports.stringify = stringify;
133
- /**
134
- * Evaluates JSON key/value pairs for FHIR JSON stringify.
135
- * Removes properties with empty string values.
136
- * Removes objects with zero properties.
137
- * Replaces any key/value pair of key "__key" with value undefined.
138
- * This function can be used as the 2nd argument to stringify to remove __key properties.
139
- * We add __key properties to array elements to improve React render performance.
140
- * @param {string} k Property key.
141
- * @param {*} v Property value.
142
- */
143
- function stringifyReplacer(k, v) {
144
- return k === '__key' || isEmpty(v) ? undefined : v;
145
- }
146
- /**
147
- * Returns true if the value is empty (null, undefined, empty string, or empty object).
148
- * @param v Any value.
149
- * @returns True if the value is an empty string or an empty object.
150
- */
151
- function isEmpty(v) {
152
- if (v === null || v === undefined) {
153
- return true;
154
- }
155
- const t = typeof v;
156
- return (t === 'string' && v === '') || (t === 'object' && Object.keys(v).length === 0);
157
- }
158
- /**
159
- * Resource equality.
160
- * Ignores meta.versionId and meta.lastUpdated.
161
- * See: https://dmitripavlutin.com/how-to-compare-objects-in-javascript/#4-deep-equality
162
- * @param object1 The first object.
163
- * @param object2 The second object.
164
- * @returns True if the objects are equal.
165
- */
166
- function deepEquals(object1, object2, path) {
167
- let keys1 = Object.keys(object1);
168
- let keys2 = Object.keys(object2);
169
- if (path === 'meta') {
170
- keys1 = keys1.filter((k) => k !== 'versionId' && k !== 'lastUpdated' && k !== 'author');
171
- keys2 = keys2.filter((k) => k !== 'versionId' && k !== 'lastUpdated' && k !== 'author');
172
- }
173
- if (keys1.length !== keys2.length) {
174
- return false;
175
- }
176
- for (const key of keys1) {
177
- const val1 = object1[key];
178
- const val2 = object2[key];
179
- if (isObject(val1) && isObject(val2)) {
180
- if (!deepEquals(val1, val2, key)) {
181
- return false;
182
- }
183
- }
184
- else {
185
- if (val1 !== val2) {
186
- return false;
187
- }
188
- }
189
- }
190
- return true;
191
- }
192
- exports.deepEquals = deepEquals;
193
- function isObject(object) {
194
- return object !== null && typeof object === 'object';
195
- }
196
- // Precompute hex octets
197
- // See: https://stackoverflow.com/a/55200387
198
- const byteToHex = [];
199
- for (let n = 0; n < 256; n++) {
200
- byteToHex.push(n.toString(16).padStart(2, '0'));
201
- }
202
- /**
203
- * Converts an ArrayBuffer to hex string.
204
- * See: https://stackoverflow.com/a/55200387
205
- * @param arrayBuffer The input array buffer.
206
- * @returns The resulting hex string.
207
- */
208
- function arrayBufferToHex(arrayBuffer) {
209
- const bytes = new Uint8Array(arrayBuffer);
210
- const result = new Array(bytes.length);
211
- for (let i = 0; i < bytes.length; i++) {
212
- result[i] = byteToHex[bytes[i]];
213
- }
214
- return result.join('');
215
- }
216
- exports.arrayBufferToHex = arrayBufferToHex;
217
- /**
218
- * Converts an ArrayBuffer to a base-64 encoded string.
219
- * @param arrayBuffer The input array buffer.
220
- * @returns The base-64 encoded string.
221
- */
222
- function arrayBufferToBase64(arrayBuffer) {
223
- const bytes = new Uint8Array(arrayBuffer);
224
- const result = [];
225
- for (let i = 0; i < bytes.length; i++) {
226
- result[i] = String.fromCharCode(bytes[i]);
227
- }
228
- return window.btoa(result.join(''));
229
- }
230
- exports.arrayBufferToBase64 = arrayBufferToBase64;
231
- function capitalize(word) {
232
- return word.charAt(0).toUpperCase() + word.substr(1);
233
- }
234
- exports.capitalize = capitalize;
235
- function isLowerCase(c) {
236
- return c === c.toLowerCase();
237
- }
238
- exports.isLowerCase = isLowerCase;
239
- //# sourceMappingURL=utils.js.map
package/dist/utils.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { Device, Patient, Practitioner, Reference, RelatedPerson, Resource } from '@medplum/fhirtypes';\nimport { formatHumanName } from './format';\n\nexport type ProfileResource = Patient | Practitioner | RelatedPerson;\n\n/**\n * Creates a reference resource.\n * @param resource The FHIR reesource.\n * @returns A reference resource.\n */\nexport function createReference<T extends Resource>(resource: T): Reference<T> {\n const reference = getReferenceString(resource);\n const display = getDisplayString(resource);\n return display === reference ? { reference } : { reference, display };\n}\n\n/**\n * Returns a reference string for a resource.\n * @param resource The FHIR resource.\n * @returns A reference string of the form resourceType/id.\n */\nexport function getReferenceString(resource: Resource): string {\n return resource.resourceType + '/' + resource.id;\n}\n\n/**\n * Returns true if the resource is a \"ProfileResource\".\n * @param resource The FHIR resource.\n * @returns True if the resource is a \"ProfileResource\".\n */\nexport function isProfileResource(resource: Resource): boolean {\n return (\n resource.resourceType === 'Patient' ||\n resource.resourceType === 'Practitioner' ||\n resource.resourceType === 'RelatedPerson'\n );\n}\n\n/**\n * Returns a display string for the resource.\n * @param resource The input resource.\n * @return Human friendly display string.\n */\nexport function getDisplayString(resource: Resource): string {\n if (isProfileResource(resource)) {\n const profileName = getProfileResourceDisplayString(resource as ProfileResource);\n if (profileName) {\n return profileName;\n }\n }\n if (resource.resourceType === 'Device') {\n const deviceName = getDeviceDisplayString(resource);\n if (deviceName) {\n return deviceName;\n }\n }\n if (resource.resourceType === 'User') {\n if (resource.email) {\n return resource.email;\n }\n }\n const simpleName = (resource as any).name;\n if (simpleName && typeof simpleName === 'string') {\n return simpleName;\n }\n return getReferenceString(resource);\n}\n\n/**\n * Returns a display string for a profile resource if one is found.\n * @param resource The profile resource.\n * @returns The display name if one is found.\n */\nfunction getProfileResourceDisplayString(resource: ProfileResource): string | undefined {\n const names = resource.name;\n if (names && names.length > 0) {\n return formatHumanName(names[0]);\n }\n return undefined;\n}\n\n/**\n * Returns a display string for a device resource if one is found.\n * @param device The device resource.\n * @returns The display name if one is found.\n */\nfunction getDeviceDisplayString(device: Device): string | undefined {\n const names = device.deviceName;\n if (names && names.length > 0) {\n return names[0].name;\n }\n return undefined;\n}\n\n/**\n * Returns an image URL for the resource, if one is available.\n * @param resource The input resource.\n * @returns The image URL for the resource or undefined.\n */\nexport function getImageSrc(resource: Resource): string | undefined {\n if (isProfileResource(resource)) {\n const photos = (resource as ProfileResource).photo;\n if (photos) {\n for (const photo of photos) {\n if (photo.url && photo.contentType && photo.contentType.startsWith('image/')) {\n return photo.url;\n }\n }\n }\n }\n return undefined;\n}\n\n/**\n * Returns a Date property as a Date.\n * When working with JSON objects, Dates are often serialized as ISO-8601 strings.\n * When that happens, we need to safely convert to a proper Date object.\n * @param date The date property value, which could be a string or a Date object.\n * @returns A Date object.\n */\nexport function getDateProperty(date: string | undefined): Date | undefined {\n return date ? new Date(date) : undefined;\n}\n\n/**\n * FHIR JSON stringify.\n * Removes properties with empty string values.\n * Removes objects with zero properties.\n * See: https://www.hl7.org/fhir/json.html\n * @param value The input value.\n * @param pretty Optional flag to pretty-print the JSON.\n * @returns The resulting JSON string.\n */\nexport function stringify(value: any, pretty?: boolean): string {\n return JSON.stringify(value, stringifyReplacer, pretty ? 2 : undefined);\n}\n\n/**\n * Evaluates JSON key/value pairs for FHIR JSON stringify.\n * Removes properties with empty string values.\n * Removes objects with zero properties.\n * Replaces any key/value pair of key \"__key\" with value undefined.\n * This function can be used as the 2nd argument to stringify to remove __key properties.\n * We add __key properties to array elements to improve React render performance.\n * @param {string} k Property key.\n * @param {*} v Property value.\n */\nfunction stringifyReplacer(k: string, v: any): any {\n return k === '__key' || isEmpty(v) ? undefined : v;\n}\n\n/**\n * Returns true if the value is empty (null, undefined, empty string, or empty object).\n * @param v Any value.\n * @returns True if the value is an empty string or an empty object.\n */\nfunction isEmpty(v: any): boolean {\n if (v === null || v === undefined) {\n return true;\n }\n const t = typeof v;\n return (t === 'string' && v === '') || (t === 'object' && Object.keys(v).length === 0);\n}\n\n/**\n * Resource equality.\n * Ignores meta.versionId and meta.lastUpdated.\n * See: https://dmitripavlutin.com/how-to-compare-objects-in-javascript/#4-deep-equality\n * @param object1 The first object.\n * @param object2 The second object.\n * @returns True if the objects are equal.\n */\nexport function deepEquals(object1: any, object2: any, path?: string): boolean {\n let keys1 = Object.keys(object1);\n let keys2 = Object.keys(object2);\n if (path === 'meta') {\n keys1 = keys1.filter((k) => k !== 'versionId' && k !== 'lastUpdated' && k !== 'author');\n keys2 = keys2.filter((k) => k !== 'versionId' && k !== 'lastUpdated' && k !== 'author');\n }\n if (keys1.length !== keys2.length) {\n return false;\n }\n for (const key of keys1) {\n const val1 = object1[key];\n const val2 = object2[key];\n if (isObject(val1) && isObject(val2)) {\n if (!deepEquals(val1, val2, key)) {\n return false;\n }\n } else {\n if (val1 !== val2) {\n return false;\n }\n }\n }\n return true;\n}\n\nfunction isObject(object: any): boolean {\n return object !== null && typeof object === 'object';\n}\n\n// Precompute hex octets\n// See: https://stackoverflow.com/a/55200387\nconst byteToHex: string[] = [];\nfor (let n = 0; n < 256; n++) {\n byteToHex.push(n.toString(16).padStart(2, '0'));\n}\n\n/**\n * Converts an ArrayBuffer to hex string.\n * See: https://stackoverflow.com/a/55200387\n * @param arrayBuffer The input array buffer.\n * @returns The resulting hex string.\n */\nexport function arrayBufferToHex(arrayBuffer: ArrayBuffer): string {\n const bytes = new Uint8Array(arrayBuffer);\n const result: string[] = new Array(bytes.length);\n for (let i = 0; i < bytes.length; i++) {\n result[i] = byteToHex[bytes[i]];\n }\n return result.join('');\n}\n\n/**\n * Converts an ArrayBuffer to a base-64 encoded string.\n * @param arrayBuffer The input array buffer.\n * @returns The base-64 encoded string.\n */\nexport function arrayBufferToBase64(arrayBuffer: ArrayBuffer): string {\n const bytes = new Uint8Array(arrayBuffer);\n const result: string[] = [];\n for (let i = 0; i < bytes.length; i++) {\n result[i] = String.fromCharCode(bytes[i]);\n }\n return window.btoa(result.join(''));\n}\n\nexport function capitalize(word: string): string {\n return word.charAt(0).toUpperCase() + word.substr(1);\n}\n\nexport function isLowerCase(c: string): boolean {\n return c === c.toLowerCase();\n}\n"]}