@medplum/core 0.5.2 → 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 +1047 -89
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -15
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/esm/index.js +1034 -90
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +1 -15
- package/dist/esm/index.min.js.map +1 -1
- package/dist/types/client.d.ts +427 -13
- package/dist/types/fix-ro-iddentifiers.d.ts +0 -0
- package/dist/types/hl7.d.ts +43 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/repo.d.ts +116 -0
- package/dist/types/search.d.ts +10 -12
- package/dist/types/utils.d.ts +48 -3
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.min.js","sources":["../../../../node_modules/tslib/tslib.es6.js","../../../src/cache.ts","../../../src/format.ts","../../../src/utils.ts","../../../src/crypto.ts","../../../src/jwt.ts","../../../src/outcomes.ts","../../../src/search.ts","../../../src/types.ts","../../../src/storage.ts","../../../src/client.ts","../../../src/eventtarget.ts","../../../src/searchparams.ts"],"sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n","/**\n * LRU cache (least recently used)\n * Source: https://stackoverflow.com/a/46432113\n */\nexport class LRUCache<T> {\n readonly #max: number;\n readonly #cache: Map<string, T>;\n\n constructor(max = 10) {\n this.#max = max;\n this.#cache = new Map();\n }\n\n clear(): void {\n this.#cache.clear();\n }\n\n get(key: string): T | undefined {\n const item = this.#cache.get(key);\n if (item) {\n this.#cache.delete(key);\n this.#cache.set(key, item);\n }\n return item;\n }\n\n set(key: string, val: T): void {\n if (this.#cache.has(key)) {\n this.#cache.delete(key);\n } else if (this.#cache.size >= this.#max) {\n this.#cache.delete(this.#first());\n }\n this.#cache.set(key, val);\n }\n\n #first(): string {\n // This works because the Map class maintains ordered keys.\n return this.#cache.keys().next().value;\n }\n}\n","import { Address, HumanName } from '@medplum/fhirtypes';\n\nexport interface AddressFormatOptions {\n all?: boolean;\n use?: boolean;\n}\n\nexport interface HumanNameFormatOptions {\n all?: boolean;\n prefix?: boolean;\n suffix?: boolean;\n use?: boolean;\n}\n\nexport function formatAddress(address: Address, options?: AddressFormatOptions): string {\n const builder = [];\n\n if (address.line) {\n builder.push(...address.line);\n }\n\n if (address.city) {\n builder.push(address.city);\n }\n\n if (address.state) {\n builder.push(address.state);\n }\n\n if (address.postalCode) {\n builder.push(address.postalCode);\n }\n\n if (address.use && (options?.all || options?.use)) {\n builder.push('[' + address.use + ']');\n }\n\n return builder.join(', ').trim();\n}\n\nexport function formatHumanName(name: HumanName, options?: HumanNameFormatOptions): string {\n const builder = [];\n\n if (name.prefix && (options?.all || options?.prefix)) {\n builder.push(...name.prefix);\n }\n\n if (name.given) {\n builder.push(...name.given);\n }\n\n if (name.family) {\n builder.push(name.family);\n }\n\n if (name.suffix && (options?.all || options?.suffix)) {\n builder.push(...name.suffix);\n }\n\n if (name.use && (options?.all || options?.use)) {\n builder.push('[' + name.use + ']');\n }\n\n return builder.join(' ').trim();\n}\n\nexport function formatGivenName(name: HumanName): string {\n const builder: string[] = [];\n if (name.given) {\n builder.push(...name.given);\n }\n return builder.join(' ').trim();\n}\n\nexport function formatFamilyName(name: HumanName): string {\n return name.family || '';\n}\n","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 the ID portion of a reference.\n * @param reference A FHIR reference.\n * @returns The ID portion of a reference.\n */\nexport function resolveId(reference: Reference | undefined): string | undefined {\n return reference?.reference?.split('/')[1];\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 if ('name' in resource && resource.name && typeof resource.name === 'string') {\n return resource.name;\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 * @param {string} k Property key.\n * @param {*} v Property value.\n */\nfunction stringifyReplacer(k: string, v: any): any {\n return 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","import { arrayBufferToHex } from './utils';\n\n/**\n * Returns a cryptographically secure random string.\n */\nexport function getRandomString(): string {\n const randomItems = new Uint32Array(28);\n crypto.getRandomValues(randomItems);\n return arrayBufferToHex(randomItems.buffer);\n}\n\n/**\n * Encrypts a string with SHA256 encryption.\n * @param str\n */\nexport async function encryptSHA256(str: string): Promise<ArrayBuffer> {\n return crypto.subtle.digest('SHA-256', new TextEncoder().encode(str));\n}\n","/**\n * Decodes a section of a JWT.\n * See: https://tools.ietf.org/html/rfc7519\n * @param payload\n */\nfunction decodePayload(payload: string): Record<string, number | string> {\n const cleanedPayload = payload.replace(/-/g, '+').replace(/_/g, '/');\n const decodedPayload = window.atob(cleanedPayload);\n const uriEncodedPayload = Array.from(decodedPayload).reduce((acc, char) => {\n const uriEncodedChar = ('00' + char.charCodeAt(0).toString(16)).slice(-2);\n return `${acc}%${uriEncodedChar}`;\n }, '');\n const jsonPayload = decodeURIComponent(uriEncodedPayload);\n return JSON.parse(jsonPayload);\n}\n\n/**\n * Parses the JWT payload.\n * @param token JWT token\n */\nexport function parseJWTPayload(token: string): Record<string, number | string> {\n const [_header, payload, _signature] = token.split('.');\n return decodePayload(payload);\n}\n","import { OperationOutcome } from '@medplum/fhirtypes';\n\nconst OK_ID = 'ok';\nconst CREATED_ID = 'created';\nconst GONE_ID = 'gone';\nconst NOT_MODIFIED_ID = 'not-modified';\nconst NOT_FOUND_ID = 'not-found';\nconst ACCESS_DENIED = 'access-denied';\n\nexport const allOk: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: OK_ID,\n issue: [\n {\n severity: 'information',\n code: 'information',\n details: {\n text: 'All OK',\n },\n },\n ],\n};\n\nexport const created: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: CREATED_ID,\n issue: [\n {\n severity: 'information',\n code: 'information',\n details: {\n text: 'Created',\n },\n },\n ],\n};\n\nexport const notModified: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: NOT_MODIFIED_ID,\n issue: [\n {\n severity: 'information',\n code: 'information',\n details: {\n text: 'Not Modified',\n },\n },\n ],\n};\n\nexport const notFound: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: NOT_FOUND_ID,\n issue: [\n {\n severity: 'error',\n code: 'not-found',\n details: {\n text: 'Not found',\n },\n },\n ],\n};\n\nexport const gone: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: GONE_ID,\n issue: [\n {\n severity: 'error',\n code: 'gone',\n details: {\n text: 'Gone',\n },\n },\n ],\n};\n\nexport const accessDenied: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: ACCESS_DENIED,\n issue: [\n {\n severity: 'error',\n code: 'access-denied',\n details: {\n text: 'Access Denied',\n },\n },\n ],\n};\n\nexport function badRequest(details: string, expression?: string): OperationOutcome {\n return {\n resourceType: 'OperationOutcome',\n issue: [\n {\n severity: 'error',\n code: 'invalid',\n details: {\n text: details,\n },\n expression: expression ? [expression] : undefined,\n },\n ],\n };\n}\n\nexport function isOk(outcome: OperationOutcome): boolean {\n return outcome.id === OK_ID || outcome.id === CREATED_ID || outcome.id === NOT_MODIFIED_ID;\n}\n\nexport function isNotFound(outcome: OperationOutcome): boolean {\n return outcome.id === NOT_FOUND_ID;\n}\n\nexport function isGone(outcome: OperationOutcome): boolean {\n return outcome.id === GONE_ID;\n}\n\nexport function getStatus(outcome: OperationOutcome): number {\n if (outcome.id === OK_ID) {\n return 200;\n } else if (outcome.id === CREATED_ID) {\n return 201;\n } else if (outcome.id === NOT_MODIFIED_ID) {\n return 304;\n } else if (outcome.id === ACCESS_DENIED) {\n return 403;\n } else if (outcome.id === NOT_FOUND_ID) {\n return 404;\n } else if (outcome.id === GONE_ID) {\n return 410;\n } else {\n return 400;\n }\n}\n\n/**\n * Asserts that the operation completed successfully and that the resource is defined.\n * @param outcome The operation outcome.\n * @param resource The resource that may or may not have been returned.\n */\nexport function assertOk<T>(outcome: OperationOutcome, resource: T | undefined): asserts resource is T {\n if (!isOk(outcome) || resource === undefined) {\n throw new OperationOutcomeError(outcome);\n }\n}\n\nexport class OperationOutcomeError extends Error {\n readonly outcome: OperationOutcome;\n\n constructor(outcome: OperationOutcome) {\n super(outcome?.issue?.[0].details?.text);\n this.outcome = outcome;\n }\n}\n","export interface SearchRequest {\n readonly resourceType: string;\n readonly filters?: Filter[];\n readonly sortRules?: SortRule[];\n readonly page?: number;\n readonly count?: number;\n readonly fields?: string[];\n readonly name?: string;\n readonly total?: 'none' | 'estimate' | 'accurate';\n}\n\nexport interface Filter {\n code: string;\n operator: Operator;\n value: string;\n unitSystem?: string;\n unitCode?: string;\n}\n\nexport interface SortRule {\n code: string;\n descending?: boolean;\n}\n\n/**\n * Search operators.\n * These operators represent \"modifiers\" and \"prefixes\" in FHIR search.\n * See: https://www.hl7.org/fhir/search.html\n */\nexport enum Operator {\n EQUALS = 'eq',\n NOT_EQUALS = 'ne',\n\n // Numbers\n GREATER_THAN = 'gt',\n LESS_THAN = 'lt',\n GREATER_THAN_OR_EQUALS = 'ge',\n LESS_THAN_OR_EQUALS = 'le',\n\n // Dates\n STARTS_AFTER = 'sa',\n ENDS_BEFORE = 'eb',\n APPROXIMATELY = 'ap',\n\n // String\n CONTAINS = 'contains',\n EXACT = 'exact',\n\n // Token\n TEXT = 'text',\n ABOVE = 'above',\n BELOW = 'below',\n IN = 'in',\n NOT_IN = 'not-in',\n OF_TYPE = 'of-type',\n}\n\nconst MODIFIER_OPERATORS: Operator[] = [\n Operator.CONTAINS,\n Operator.EXACT,\n Operator.TEXT,\n Operator.ABOVE,\n Operator.BELOW,\n Operator.IN,\n Operator.NOT_IN,\n Operator.OF_TYPE,\n];\n\nconst PREFIX_OPERATORS: Operator[] = [\n Operator.NOT_EQUALS,\n Operator.GREATER_THAN,\n Operator.LESS_THAN,\n Operator.GREATER_THAN_OR_EQUALS,\n Operator.LESS_THAN_OR_EQUALS,\n Operator.STARTS_AFTER,\n Operator.ENDS_BEFORE,\n Operator.APPROXIMATELY,\n];\n\n/**\n * Parses a URL into a SearchRequest.\n *\n * See the FHIR search spec: http://hl7.org/fhir/r4/search.html\n *\n * @param location The URL to parse.\n * @returns Parsed search definition.\n */\nexport function parseSearchDefinition(location: { pathname: string; search?: string }): SearchRequest {\n const resourceType = location.pathname\n .replace(/(^\\/)|(\\/$)/g, '') // Remove leading and trailing slashes\n .split('/')\n .pop() as string;\n const params = new URLSearchParams(location.search);\n let filters: Filter[] | undefined = undefined;\n let sortRules: SortRule[] | undefined = undefined;\n let fields: string[] | undefined = undefined;\n let page = undefined;\n let count = undefined;\n let total = undefined;\n\n params.forEach((value, key) => {\n if (key === '_fields') {\n fields = value.split(',');\n } else if (key === '_page') {\n page = parseInt(value);\n } else if (key === '_count') {\n count = parseInt(value);\n } else if (key === '_total') {\n total = value;\n } else if (key === '_sort') {\n sortRules = sortRules || [];\n sortRules.push(parseSortRule(value));\n } else {\n filters = filters || [];\n filters.push(parseSearchFilter(key, value));\n }\n });\n\n return {\n resourceType,\n filters,\n fields,\n page,\n count,\n total,\n sortRules,\n };\n}\n\n/**\n * Parses a URL query parameter into a sort rule.\n *\n * By default, the sort rule is the field name.\n *\n * Sort rules can be reversed into descending order by prefixing the field name with a minus sign.\n *\n * See sorting: http://hl7.org/fhir/r4/search.html#_sort\n *\n * @param value The URL parameter value.\n * @returns The parsed sort rule.\n */\nfunction parseSortRule(value: string): SortRule {\n if (value.startsWith('-')) {\n return { code: value.substring(1), descending: true };\n } else {\n return { code: value };\n }\n}\n\n/**\n * Parses a URL query parameter into a search filter.\n *\n * FHIR search filters can be specified as modifiers or prefixes.\n *\n * For string properties, modifiers are appended to the key, e.g. \"name:contains=eve\".\n *\n * For date and numeric properties, prefixes are prepended to the value, e.g. \"birthdate=gt2000\".\n *\n * See the FHIR search spec: http://hl7.org/fhir/r4/search.html\n *\n * @param key The URL parameter key.\n * @param value The URL parameter value.\n * @returns The parsed search filter.\n */\nfunction parseSearchFilter(key: string, value: string): Filter {\n let code = key;\n let operator = Operator.EQUALS;\n\n for (const modifier of MODIFIER_OPERATORS) {\n const modifierIndex = code.indexOf(':' + modifier);\n if (modifierIndex !== -1) {\n operator = modifier;\n code = code.substring(0, modifierIndex);\n }\n }\n\n for (const prefix of PREFIX_OPERATORS) {\n if (value.match(new RegExp('^' + prefix + '\\\\d'))) {\n operator = prefix;\n value = value.substring(prefix.length);\n }\n }\n\n return { code, operator, value };\n}\n\n/**\n * Formats a search definition object into a query string.\n * Note: The return value does not include the resource type.\n * @param {!SearchRequest} definition The search definition.\n * @returns Formatted URL.\n */\nexport function formatSearchQuery(definition: SearchRequest): string {\n const params: string[] = [];\n\n if (definition.fields) {\n params.push('_fields=' + definition.fields.join(','));\n }\n\n if (definition.filters) {\n definition.filters.forEach((filter) => params.push(formatFilter(filter)));\n }\n\n if (definition.sortRules && definition.sortRules.length > 0) {\n params.push(formatSortRules(definition.sortRules));\n }\n\n if (definition.page && definition.page > 0) {\n params.push('_page=' + definition.page);\n }\n\n if (definition.count && definition.count > 0) {\n params.push('_count=' + definition.count);\n }\n\n if (definition.total) {\n params.push('_total=' + encodeURIComponent(definition.total));\n }\n\n if (params.length === 0) {\n return '';\n }\n\n params.sort();\n return '?' + params.join('&');\n}\n\nfunction formatFilter(filter: Filter): string {\n const modifier = MODIFIER_OPERATORS.includes(filter.operator) ? ':' + filter.operator : '';\n const prefix = PREFIX_OPERATORS.includes(filter.operator) ? filter.operator : '';\n return `${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`;\n}\n\nfunction formatSortRules(sortRules: SortRule[] | undefined): string {\n if (!sortRules || sortRules.length === 0) {\n return '';\n }\n return '_sort=' + sortRules.map((sr) => (sr.descending ? '-' + sr.code : sr.code)).join(',');\n}\n","import { ElementDefinition, SearchParameter, StructureDefinition } from '@medplum/fhirtypes';\nimport { capitalize } from './utils';\n\n/**\n * List of property types.\n * http://www.hl7.org/fhir/valueset-defined-types.html\n * The list here includes additions found from StructureDefinition resources.\n */\nexport enum PropertyType {\n Address = 'Address',\n Age = 'Age',\n Annotation = 'Annotation',\n Attachment = 'Attachment',\n BackboneElement = 'BackboneElement',\n CodeableConcept = 'CodeableConcept',\n Coding = 'Coding',\n ContactDetail = 'ContactDetail',\n ContactPoint = 'ContactPoint',\n Contributor = 'Contributor',\n Count = 'Count',\n DataRequirement = 'DataRequirement',\n Distance = 'Distance',\n Dosage = 'Dosage',\n Duration = 'Duration',\n Expression = 'Expression',\n Extension = 'Extension',\n HumanName = 'HumanName',\n Identifier = 'Identifier',\n MarketingStatus = 'MarketingStatus',\n Meta = 'Meta',\n Money = 'Money',\n Narrative = 'Narrative',\n ParameterDefinition = 'ParameterDefinition',\n Period = 'Period',\n Population = 'Population',\n ProdCharacteristic = 'ProdCharacteristic',\n ProductShelfLife = 'ProductShelfLife',\n Quantity = 'Quantity',\n Range = 'Range',\n Ratio = 'Ratio',\n Reference = 'Reference',\n RelatedArtifact = 'RelatedArtifact',\n Resource = 'Resource',\n SampledData = 'SampledData',\n Signature = 'Signature',\n SubstanceAmount = 'SubstanceAmount',\n SystemString = 'http://hl7.org/fhirpath/System.String',\n Timing = 'Timing',\n TriggerDefinition = 'TriggerDefinition',\n UsageContext = 'UsageContext',\n base64Binary = 'base64Binary',\n boolean = 'boolean',\n canonical = 'canonical',\n code = 'code',\n date = 'date',\n dateTime = 'dateTime',\n decimal = 'decimal',\n id = 'id',\n instant = 'instant',\n integer = 'integer',\n markdown = 'markdown',\n oid = 'oid',\n positiveInt = 'positiveInt',\n string = 'string',\n time = 'time',\n unsignedInt = 'unsignedInt',\n uri = 'uri',\n url = 'url',\n uuid = 'uuid',\n}\n\n/**\n * An IndexedStructureDefinition is a lookup-optimized version of a StructureDefinition.\n *\n * StructureDefinition resources contain schema information for other resource types.\n * These schemas can be used to automatically generate user interface elements for\n * resources.\n *\n * However, a StructureDefinition resource is not optimized for realtime lookups. All\n * resource types, sub types, and property definitions are stored in a flat array of\n * ElementDefinition objects. Therefore, to lookup the schema for a property (i.e., \"Patient.name\")\n * requires a linear scan of all ElementDefinition objects\n *\n * A StructureDefinition resource contains information about one or more types.\n * For example, the \"Patient\" StructureDefinition includes \"Patient\", \"Patient_Contact\",\n * \"Patient_Communication\", and \"Patient_Link\". This is inefficient.\n *\n * Instead, we create an indexed version of the StructureDefinition, called IndexedStructureDefinition.\n * In an IndexedStructureDefinition, retrieving a property definition is a hashtable lookup.\n *\n * The hierarchy is:\n * IndexedStructureDefinition - top level for one resource type\n * TypeSchema - one per resource type and all contained BackboneElements\n * PropertySchema - one per property/field\n */\nexport interface IndexedStructureDefinition {\n types: { [resourceType: string]: TypeSchema };\n}\n\n/**\n * An indexed TypeSchema.\n *\n * Example: The IndexedStructureDefinition for \"Patient\" would include the following TypeSchemas:\n * 1) Patient\n * 2) Patient_Contact\n * 3) Patient_Communication\n * 4) Patient_Link\n */\nexport interface TypeSchema {\n display: string;\n properties: { [name: string]: ElementDefinition };\n searchParams?: { [code: string]: SearchParameter };\n description?: string;\n parentType?: string;\n}\n\n/**\n * Creates a new empty IndexedStructureDefinition.\n * @returns The empty IndexedStructureDefinition.\n */\nexport function createSchema(): IndexedStructureDefinition {\n return { types: {} };\n}\n\nexport function createTypeSchema(typeName: string, description: string | undefined): TypeSchema {\n return {\n display: typeName,\n description,\n properties: {},\n searchParams: {\n _lastUpdated: {\n base: [typeName],\n code: '_lastUpdated',\n type: 'date',\n expression: typeName + '.meta.lastUpdated',\n } as SearchParameter,\n },\n };\n}\n\n/**\n * Indexes a StructureDefinition for fast lookup.\n * See comments on IndexedStructureDefinition for more details.\n * @param schema The output IndexedStructureDefinition.\n * @param structureDefinition The original StructureDefinition.\n */\nexport function indexStructureDefinition(\n schema: IndexedStructureDefinition,\n structureDefinition: StructureDefinition\n): void {\n const typeName = structureDefinition.name;\n if (!typeName) {\n return;\n }\n\n schema.types[typeName] = createTypeSchema(typeName, structureDefinition.description);\n\n const elements = structureDefinition.snapshot?.element;\n if (elements) {\n // Filter out any elements missing path or type\n const filtered = elements.filter((e) => e.path !== typeName && e.path);\n\n // First pass, build types\n filtered.forEach((element) => indexType(schema, element));\n\n // Second pass, build properties\n filtered.forEach((element) => indexProperty(schema, element));\n }\n}\n\n/**\n * Indexes TypeSchema from an ElementDefinition.\n * In the common case, there will be many ElementDefinition instances per TypeSchema.\n * Only the first occurrence is saved.\n * @param schema The output IndexedStructureDefinition.\n * @param element The input ElementDefinition.\n */\nfunction indexType(schema: IndexedStructureDefinition, element: ElementDefinition): void {\n const path = element.path as string;\n const typeCode = element.type?.[0]?.code;\n if (typeCode !== 'Element' && typeCode !== 'BackboneElement') {\n return;\n }\n const parts = path.split('.');\n const typeName = buildTypeName(parts);\n if (!(typeName in schema.types)) {\n schema.types[typeName] = createTypeSchema(typeName, element.definition);\n schema.types[typeName].parentType = buildTypeName(parts.slice(0, parts.length - 1));\n }\n}\n\n/**\n * Indexes PropertySchema from an ElementDefinition.\n * @param schema The output IndexedStructureDefinition.\n * @param element The input ElementDefinition.\n */\nfunction indexProperty(schema: IndexedStructureDefinition, element: ElementDefinition): void {\n const path = element.path as string;\n const parts = path.split('.');\n if (parts.length === 1) {\n return;\n }\n const typeName = buildTypeName(parts.slice(0, parts.length - 1));\n const typeSchema = schema.types[typeName];\n const key = parts[parts.length - 1];\n typeSchema.properties[key] = element;\n}\n\n/**\n * Indexes a SearchParameter resource for fast lookup.\n * Indexes by SearchParameter.code, which is the query string parameter name.\n * @param schema The output IndexedStructureDefinition.\n * @param searchParam The SearchParameter resource.\n */\nexport function indexSearchParameter(schema: IndexedStructureDefinition, searchParam: SearchParameter): void {\n if (!searchParam.base) {\n return;\n }\n\n for (const resourceType of searchParam.base) {\n const typeSchema = schema.types[resourceType];\n if (!typeSchema) {\n continue;\n }\n\n if (!typeSchema.searchParams) {\n typeSchema.searchParams = {};\n }\n\n typeSchema.searchParams[searchParam.code as string] = searchParam;\n }\n}\n\nexport function buildTypeName(components: string[]): string {\n return components.map(capitalize).join('');\n}\n\nexport function getPropertyDisplayName(property: ElementDefinition): string {\n // Get the property name, which is the remainder after the last period\n // For example, for path \"Patient.birthDate\"\n // the property name is \"birthDate\"\n const propertyName = (property.path as string).replaceAll('[x]', '').split('.').pop() as string;\n\n // Special case for ID\n if (propertyName === 'id') {\n return 'ID';\n }\n\n // Split by capital letters\n // Capitalize the first letter of each word\n // Join together with spaces in between\n // Then normalize whitespace to single space character\n // For example, for property name \"birthDate\",\n // the display name is \"Birth Date\".\n return propertyName\n .split(/(?=[A-Z])/)\n .map(capitalize)\n .join(' ')\n .replace('_', ' ')\n .replace(/\\s+/g, ' ');\n}\n","import { stringify } from './utils';\n\n/**\n * The ClientStorage class is a utility class for storing strings and objects.\n *\n * When using MedplumClient in the browser, it will be backed by browser localStorage.\n *\n * When Using MedplumClient in the server, it will be backed by the MemoryStorage class.\n */\nexport class ClientStorage {\n readonly #storage: Storage;\n\n constructor() {\n this.#storage = typeof localStorage !== 'undefined' ? localStorage : new MemoryStorage();\n }\n\n clear(): void {\n this.#storage.clear();\n }\n\n getString(key: string): string | undefined {\n return this.#storage.getItem(key) || undefined;\n }\n\n setString(key: string, value: string | undefined): void {\n if (value) {\n this.#storage.setItem(key, value);\n } else {\n this.#storage.removeItem(key);\n }\n }\n\n getObject<T>(key: string): T | undefined {\n const str = this.getString(key);\n return str ? (JSON.parse(str) as T) : undefined;\n }\n\n setObject<T>(key: string, value: T): void {\n this.setString(key, value ? stringify(value) : undefined);\n }\n}\n\n/**\n * The MemoryStorage class is a minimal in-memory implementation of the Storage interface.\n */\nexport class MemoryStorage implements Storage {\n #data: Map<string, string>;\n\n constructor() {\n this.#data = new Map<string, string>();\n }\n\n /**\n * Returns the number of key/value pairs.\n */\n get length(): number {\n return this.#data.size;\n }\n\n /**\n * Removes all key/value pairs, if there are any.\n */\n clear(): void {\n this.#data.clear();\n }\n\n /**\n * Returns the current value associated with the given key, or null if the given key does not exist.\n */\n getItem(key: string): string | null {\n return this.#data.get(key) ?? null;\n }\n\n /**\n * Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.\n */\n setItem(key: string, value: string | null): void {\n if (value) {\n this.#data.set(key, value);\n } else {\n this.#data.delete(key);\n }\n }\n\n /**\n * Removes the key/value pair with the given key, if a key/value pair with the given key exists.\n */\n removeItem(key: string): void {\n this.#data.delete(key);\n }\n\n /**\n * Returns the name of the nth key, or null if n is greater than or equal to the number of key/value pairs.\n */\n key(index: number): string | null {\n return Array.from(this.#data.keys())[index];\n }\n}\n","// PKCE auth ased on:\n// https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/\n\nimport {\n Binary,\n Bundle,\n Project,\n ProjectMembership,\n Reference,\n Resource,\n SearchParameter,\n StructureDefinition,\n UserConfiguration,\n ValueSet,\n} from '@medplum/fhirtypes';\nimport { LRUCache } from './cache';\nimport { encryptSHA256, getRandomString } from './crypto';\nimport { EventTarget } from './eventtarget';\nimport { parseJWTPayload } from './jwt';\nimport { isOk } from './outcomes';\nimport { formatSearchQuery, SearchRequest } from './search';\nimport { ClientStorage } from './storage';\nimport { createSchema, IndexedStructureDefinition, indexSearchParameter, indexStructureDefinition } from './types';\nimport { arrayBufferToBase64, ProfileResource, stringify } from './utils';\n\nconst DEFAULT_BASE_URL = 'https://api.medplum.com/';\nconst DEFAULT_SCOPE = 'launch/patient openid fhirUser offline_access user/*.*';\nconst DEFAULT_RESOURCE_CACHE_SIZE = 1000;\nconst JSON_CONTENT_TYPE = 'application/json';\nconst FHIR_CONTENT_TYPE = 'application/fhir+json';\nconst PATCH_CONTENT_TYPE = 'application/json-patch+json';\n\nexport interface MedplumClientOptions {\n /**\n * The client ID.\n * Optional. Default is to defer to the server to use the default client.\n * Use this to use a specific client for SMART-on-FHIR.\n */\n clientId?: string;\n\n /**\n * Base server URL.\n * Optional. Default value is \"https://api.medplum.com/\".\n * Use this to point to a custom Medplum deployment.\n */\n baseUrl?: string;\n\n /**\n * OAuth2 authorize URL.\n * Optional. Default value is baseUrl + \"/oauth2/authorize\".\n * Use this if you want to use a separate OAuth server.\n */\n authorizeUrl?: string;\n\n /**\n * OAuth2 token URL.\n * Optional. Default value is baseUrl + \"/oauth2/token\".\n * Use this if you want to use a separate OAuth server.\n */\n tokenUrl?: string;\n\n /**\n * OAuth2 logout URL.\n * Optional. Default value is baseUrl + \"/oauth2/logout\".\n * Use this if you want to use a separate OAuth server.\n */\n logoutUrl?: string;\n\n /**\n * Number of resources to store in the cache.\n * Optional. Default value is 1000.\n * Consider using this for performance of displaying Patient or Practitioner resources.\n */\n resourceCacheSize?: number;\n\n /**\n * Optional fetch implementation.\n * Optional. Default is window.fetch.\n * For nodejs applications, consider the 'node-fetch' package.\n */\n fetch?: FetchLike;\n\n /**\n * Optional callback for when the client is unauthenticated.\n * Default is do nothing.\n * For client side applications, consider redirecting to a sign in page.\n */\n onUnauthenticated?: () => void;\n}\n\nexport interface FetchLike {\n (url: string, options?: any): Promise<any>;\n}\n\nexport interface RegisterRequest {\n readonly firstName: string;\n readonly lastName: string;\n readonly projectName: string;\n readonly email: string;\n readonly password: string;\n readonly remember?: boolean;\n readonly recaptchaToken: string;\n}\n\nexport interface GoogleCredentialResponse {\n readonly clientId: string;\n readonly credential: string;\n}\n\nexport interface LoginAuthenticationResponse {\n readonly login: string;\n readonly code?: string;\n readonly memberships?: ProjectMembership[];\n}\n\nexport interface LoginProfileResponse {\n readonly login: string;\n readonly scope: string;\n}\n\nexport interface LoginScopeResponse {\n readonly login: string;\n readonly code: string;\n}\n\nexport interface LoginState {\n readonly project: Reference<Project>;\n readonly profile: Reference<ProfileResource>;\n readonly accessToken: string;\n readonly refreshToken: string;\n}\n\nexport interface TokenResponse {\n readonly token_type: string;\n readonly id_token: string;\n readonly access_token: string;\n readonly refresh_token: string;\n readonly expires_in: number;\n readonly project: Reference<Project>;\n readonly profile: Reference<ProfileResource>;\n}\n\ninterface SchemaGraphQLResponse {\n readonly data: {\n readonly StructureDefinitionList: StructureDefinition[];\n readonly SearchParameterList: SearchParameter[];\n };\n}\n\nexport class MedplumClient extends EventTarget {\n readonly #fetch: FetchLike;\n readonly #storage: ClientStorage;\n readonly #schema: IndexedStructureDefinition;\n readonly #resourceCache: LRUCache<Resource | Promise<Resource>>;\n readonly #baseUrl: string;\n readonly #clientId: string;\n readonly #authorizeUrl: string;\n readonly #tokenUrl: string;\n readonly #logoutUrl: string;\n readonly #onUnauthenticated?: () => void;\n #accessToken?: string;\n #refreshToken?: string;\n #refreshPromise?: Promise<any>;\n #profilePromise?: Promise<any>;\n #profile?: ProfileResource;\n #config?: UserConfiguration;\n\n constructor(options?: MedplumClientOptions) {\n super();\n\n if (options?.baseUrl) {\n if (!options.baseUrl.startsWith('http')) {\n throw new Error('Base URL must start with http or https');\n }\n if (!options.baseUrl.endsWith('/')) {\n throw new Error('Base URL must end with a trailing slash');\n }\n }\n\n this.#fetch = options?.fetch || window.fetch.bind(window);\n this.#storage = new ClientStorage();\n this.#schema = createSchema();\n this.#resourceCache = new LRUCache(options?.resourceCacheSize ?? DEFAULT_RESOURCE_CACHE_SIZE);\n this.#baseUrl = options?.baseUrl || DEFAULT_BASE_URL;\n this.#clientId = options?.clientId || '';\n this.#authorizeUrl = options?.authorizeUrl || this.#baseUrl + 'oauth2/authorize';\n this.#tokenUrl = options?.tokenUrl || this.#baseUrl + 'oauth2/token';\n this.#logoutUrl = options?.logoutUrl || this.#baseUrl + 'oauth2/logout';\n this.#onUnauthenticated = options?.onUnauthenticated;\n\n const activeLogin = this.getActiveLogin();\n if (activeLogin) {\n this.#accessToken = activeLogin.accessToken;\n this.#refreshToken = activeLogin.refreshToken;\n this.#refreshProfile().catch(console.log);\n }\n\n this.#setupStorageListener();\n }\n\n /**\n * Clears all auth state including local storage and session storage.\n */\n clear(): void {\n this.#storage.clear();\n this.#resourceCache.clear();\n this.#accessToken = undefined;\n this.#refreshToken = undefined;\n this.#profile = undefined;\n this.#config = undefined;\n this.dispatchEvent({ type: 'change' });\n }\n\n get(url: string): Promise<any> {\n return this.#request('GET', url);\n }\n\n post(url: string, body: any, contentType?: string): Promise<any> {\n return this.#request('POST', url, contentType, body);\n }\n\n put(url: string, body: any, contentType?: string): Promise<any> {\n return this.#request('PUT', url, contentType, body);\n }\n\n delete(url: string): Promise<any> {\n return this.#request('DELETE', url);\n }\n\n /**\n * Tries to register a new user.\n * @param request The registration request.\n * @returns Promise to the authentication response.\n */\n async register(request: RegisterRequest): Promise<void> {\n const response = await this.post('auth/register', request);\n await this.setActiveLogin(response as LoginState);\n }\n\n /**\n * Initiates a user login flow.\n * @param email The email address of the user.\n * @param password The password of the user.\n * @param remember Optional flag to remember the user.\n * @returns Promise to the authentication response.\n */\n async startLogin(email: string, password: string, remember?: boolean): Promise<LoginAuthenticationResponse> {\n await this.#startPkce();\n return this.post('auth/login', {\n clientId: this.#clientId,\n scope: DEFAULT_SCOPE,\n codeChallengeMethod: 'S256',\n codeChallenge: this.#storage.getString('codeChallenge') as string,\n email,\n password,\n remember: !!remember,\n }) as Promise<LoginAuthenticationResponse>;\n }\n\n /**\n * Tries to sign in with Google authentication.\n * The response parameter is the result of a Google authentication.\n * See: https://developers.google.com/identity/gsi/web/guides/handle-credential-responses-js-functions\n * @param googleResponse The Google credential response.\n * @returns Promise to the authentication response.\n */\n async startGoogleLogin(googleResponse: GoogleCredentialResponse): Promise<LoginAuthenticationResponse> {\n await this.#startPkce();\n return this.post('auth/google', googleResponse) as Promise<LoginAuthenticationResponse>;\n }\n\n /**\n * Signs out locally.\n * Does not invalidate tokens with the server.\n */\n signOut(): Promise<void> {\n this.clear();\n return Promise.resolve();\n }\n\n /**\n * Tries to sign in the user.\n * Returns true if the user is signed in.\n * This may result in navigating away to the sign in page.\n */\n signInWithRedirect(): Promise<ProfileResource | void> | undefined {\n const urlParams = new URLSearchParams(window.location.search);\n const code = urlParams.get('code');\n if (!code) {\n this.#requestAuthorization();\n return undefined;\n } else {\n return this.processCode(code);\n }\n }\n\n /**\n * Tries to sign out the user.\n * See: https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html\n */\n signOutWithRedirect(): void {\n window.location.assign(this.#logoutUrl);\n }\n\n /**\n * Builds a FHIR URL from a collection of URL path components.\n * For example, `buildUrl('/Patient', '123')` returns `fhir/R4/Patient/123`.\n * @param path The path component of the URL.\n * @returns The well-formed FHIR URL.\n */\n fhirUrl(...path: string[]): string {\n const builder = [this.#baseUrl, 'fhir/R4'];\n path.forEach((p) => builder.push('/', encodeURIComponent(p)));\n return builder.join('');\n }\n\n /**\n * Sends a FHIR search request.\n * @param search The search query.\n * @returns Promise to the search result bundle.\n */\n search<T extends Resource>(search: SearchRequest): Promise<Bundle<T>> {\n return this.get(this.fhirUrl(search.resourceType) + formatSearchQuery(search));\n }\n\n /**\n * Searches a ValueSet resource using the \"expand\" operation.\n * See: https://www.hl7.org/fhir/operation-valueset-expand.html\n * @param system The ValueSet system url.\n * @param filter The search string.\n * @returns Promise to expanded ValueSet.\n */\n searchValueSet(system: string, filter: string): Promise<ValueSet> {\n return this.get(\n this.fhirUrl('ValueSet', '$expand') +\n `?url=${encodeURIComponent(system)}` +\n `&filter=${encodeURIComponent(filter)}`\n );\n }\n\n /**\n * Returns a cached resource if it is available.\n * @param resourceType The FHIR resource type.\n * @param id The FHIR resource ID.\n * @returns The resource if it is available in the cache; undefined otherwise.\n */\n getCached<T extends Resource>(resourceType: string, id: string): T | undefined {\n const cached = this.#resourceCache.get(resourceType + '/' + id) as T | undefined;\n if (cached && !('then' in cached)) {\n return cached;\n }\n return undefined;\n }\n\n /**\n * Returns a cached resource if it is available.\n * @param resourceType The FHIR resource type.\n * @param id The FHIR resource ID.\n * @returns The resource if it is available in the cache; undefined otherwise.\n */\n getCachedReference<T extends Resource>(reference: Reference<T>): T | undefined {\n const cached = this.#resourceCache.get(reference.reference as string) as T | undefined;\n if (cached && !('then' in cached)) {\n return cached;\n }\n return undefined;\n }\n\n read<T extends Resource>(resourceType: string, id: string): Promise<T> {\n const cacheKey = resourceType + '/' + id;\n const promise = this.get(this.fhirUrl(resourceType, id)).then((resource: T) => {\n this.#resourceCache.set(cacheKey, resource);\n return resource;\n });\n this.#resourceCache.set(cacheKey, promise);\n return promise;\n }\n\n readCached<T extends Resource>(resourceType: string, id: string): Promise<T> {\n const cached = this.#resourceCache.get(resourceType + '/' + id) as T | Promise<T> | undefined;\n return cached ? Promise.resolve(cached) : this.read(resourceType, id);\n }\n\n readReference<T extends Resource>(reference: Reference<T>): Promise<T> {\n const refString = reference?.reference;\n if (!refString) {\n return Promise.reject('Missing reference');\n }\n const [resourceType, id] = refString.split('/');\n return this.read(resourceType, id);\n }\n\n readCachedReference<T extends Resource>(reference: Reference<T>): Promise<T> {\n const refString = reference?.reference;\n if (!refString) {\n return Promise.reject('Missing reference');\n }\n const [resourceType, id] = refString.split('/');\n return this.readCached(resourceType, id);\n }\n\n /**\n * Returns a cached schema for a resource type.\n * If the schema is not cached, returns undefined.\n * It is assumed that a client will call requestSchema before using this method.\n * @param resourceType The FHIR resource type.\n * @returns The schema if immediately available, undefined otherwise.\n */\n getSchema(): IndexedStructureDefinition {\n return this.#schema;\n }\n\n /**\n * Requests the schema for a resource type.\n * If the schema is already cached, the promise is resolved immediately.\n * @param resourceType The FHIR resource type.\n * @returns Promise to a schema with the requested resource type.\n */\n async requestSchema(resourceType: string): Promise<IndexedStructureDefinition> {\n if (resourceType in this.#schema.types) {\n return Promise.resolve(this.#schema);\n }\n\n const query = `{\n StructureDefinitionList(name: \"${encodeURIComponent(resourceType)}\") {\n name,\n description,\n snapshot {\n element {\n id,\n path,\n min,\n max,\n type {\n code,\n targetProfile\n },\n binding {\n valueSet\n },\n definition\n }\n }\n }\n SearchParameterList(base: \"${encodeURIComponent(resourceType)}\") {\n base,\n code,\n type,\n expression,\n target\n }\n }`.replace(/\\s+/g, ' ');\n\n const response = (await this.graphql(query)) as SchemaGraphQLResponse;\n\n for (const structureDefinition of response.data.StructureDefinitionList) {\n indexStructureDefinition(this.#schema, structureDefinition);\n }\n\n for (const searchParameter of response.data.SearchParameterList) {\n indexSearchParameter(this.#schema, searchParameter);\n }\n\n return this.#schema;\n }\n\n readHistory<T extends Resource>(resourceType: string, id: string): Promise<Bundle<T>> {\n return this.get(this.fhirUrl(resourceType, id, '_history'));\n }\n\n readPatientEverything(id: string): Promise<Bundle> {\n return this.get(this.fhirUrl('Patient', id, '$everything'));\n }\n\n create<T extends Resource>(resource: T): Promise<T> {\n if (!resource.resourceType) {\n throw new Error('Missing resourceType');\n }\n return this.post(this.fhirUrl(resource.resourceType), resource);\n }\n\n createBinary(data: any, filename: string, contentType: string): Promise<Binary> {\n return this.post(this.fhirUrl('Binary') + '?_filename=' + encodeURIComponent(filename), data, contentType);\n }\n\n update<T extends Resource>(resource: T): Promise<T> {\n if (!resource.resourceType) {\n throw new Error('Missing resourceType');\n }\n if (!resource.id) {\n throw new Error('Missing id');\n }\n return this.put(this.fhirUrl(resource.resourceType, resource.id), resource);\n }\n\n patch(resourceType: string, id: string, operations: any): Promise<any> {\n return this.#request('PATCH', this.fhirUrl(resourceType, id), PATCH_CONTENT_TYPE, operations);\n }\n\n deleteResource(resourceType: string, id: string): Promise<any> {\n return this.delete(this.fhirUrl(resourceType, id));\n }\n\n graphql(query: string): Promise<any> {\n return this.post(this.fhirUrl('$graphql'), { query }, JSON_CONTENT_TYPE);\n }\n\n getActiveLogin(): LoginState | undefined {\n return this.#storage.getObject('activeLogin');\n }\n\n async setActiveLogin(login: LoginState): Promise<void> {\n this.#accessToken = login.accessToken;\n this.#refreshToken = login.refreshToken;\n this.#profile = undefined;\n this.#config = undefined;\n this.#storage.setObject('activeLogin', login);\n this.#addLogin(login);\n this.#resourceCache.clear();\n this.#refreshPromise = undefined;\n await this.#refreshProfile();\n }\n\n getLogins(): LoginState[] {\n return this.#storage.getObject<LoginState[]>('logins') ?? [];\n }\n\n #addLogin(newLogin: LoginState): void {\n const logins = this.getLogins().filter((login) => login.profile?.reference !== newLogin.profile?.reference);\n logins.push(newLogin);\n this.#storage.setObject('logins', logins);\n }\n\n async #refreshProfile(): Promise<ProfileResource | undefined> {\n this.#profilePromise = new Promise((resolve, reject) => {\n this.get('auth/me')\n .then((result) => {\n this.#profilePromise = undefined;\n this.#profile = result.profile;\n this.#config = result.config;\n this.dispatchEvent({ type: 'change' });\n resolve(this.#profile);\n })\n .catch(reject);\n });\n\n return this.#profilePromise;\n }\n\n isLoading(): boolean {\n return !!this.#profilePromise;\n }\n\n getProfile(): ProfileResource | undefined {\n return this.#profile;\n }\n\n async getProfileAsync(): Promise<ProfileResource | undefined> {\n if (this.#profilePromise) {\n await this.#profilePromise;\n }\n return this.getProfile();\n }\n\n getUserConfiguration(): UserConfiguration | undefined {\n return this.#config;\n }\n\n /**\n * Downloads the URL as a blob.\n * @param url The URL to request.\n * @returns Promise to the response body as a blob.\n */\n async download(url: string): Promise<Blob> {\n if (this.#refreshPromise) {\n await this.#refreshPromise;\n }\n\n const options = this.#buildFetchOptions('GET');\n const response = await this.#fetch(url, options);\n return response.blob();\n }\n\n /**\n * Makes an HTTP request.\n * @param {string} method\n * @param {string} url\n * @param {string=} contentType\n * @param {Object=} body\n */\n async #request(method: string, url: string, contentType?: string, body?: any): Promise<any> {\n if (this.#refreshPromise) {\n await this.#refreshPromise;\n }\n\n if (!url.startsWith('http')) {\n url = this.#baseUrl + url;\n }\n\n const options = this.#buildFetchOptions(method, contentType, body);\n const response = await this.#fetch(url, options);\n if (response.status === 401) {\n // Refresh and try again\n return this.#handleUnauthenticated(method, url, contentType, body);\n }\n\n if (response.status === 204 || response.status === 304) {\n // No content or change\n return undefined;\n }\n\n const obj = await response.json();\n if (obj.resourceType === 'OperationOutcome' && !isOk(obj)) {\n return Promise.reject(obj);\n }\n return obj;\n }\n\n #buildFetchOptions(method: string, contentType?: string, body?: any): RequestInit {\n const headers: Record<string, string> = {\n 'Content-Type': contentType || FHIR_CONTENT_TYPE,\n };\n\n if (this.#accessToken) {\n headers['Authorization'] = 'Bearer ' + this.#accessToken;\n }\n\n const options: RequestInit = {\n method: method,\n cache: 'no-cache',\n credentials: 'include',\n headers,\n };\n\n if (body) {\n if (typeof body === 'string' || (typeof File !== 'undefined' && body instanceof File)) {\n options.body = body;\n } else {\n options.body = stringify(body);\n }\n }\n\n return options;\n }\n\n /**\n * Handles an unauthenticated response from the server.\n * First, tries to refresh the access token and retry the request.\n * Otherwise, calls unauthenticated callbacks and rejects.\n * @param method The HTTP method of the original request.\n * @param url The URL of the original request.\n * @param contentType The content type of the original request.\n * @param body The body of the original request.\n */\n async #handleUnauthenticated(method: string, url: string, contentType?: string, body?: any): Promise<any> {\n return this.#refresh()\n .then(() => this.#request(method, url, contentType, body))\n .catch((error) => {\n this.clear();\n if (this.#onUnauthenticated) {\n this.#onUnauthenticated();\n }\n return Promise.reject(error);\n });\n }\n\n /**\n * Starts a new PKCE flow.\n * These PKCE values are stateful, and must survive redirects and page refreshes.\n */\n async #startPkce(): Promise<void> {\n const pkceState = getRandomString();\n this.#storage.setString('pkceState', pkceState);\n\n const codeVerifier = getRandomString();\n this.#storage.setString('codeVerifier', codeVerifier);\n\n const arrayHash = await encryptSHA256(codeVerifier);\n const codeChallenge = arrayBufferToBase64(arrayHash).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n this.#storage.setString('codeChallenge', codeChallenge);\n }\n\n /**\n * Redirects the user to the login screen for authorization.\n * Clears all auth state including local storage and session storage.\n * See: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint\n */\n async #requestAuthorization(): Promise<void> {\n if (!this.#authorizeUrl) {\n throw new Error('Missing authorize URL');\n }\n\n this.#startPkce();\n\n window.location.assign(\n this.#authorizeUrl +\n '?response_type=code' +\n '&state=' +\n encodeURIComponent(this.#storage.getString('pkceState') as string) +\n '&client_id=' +\n encodeURIComponent(this.#clientId) +\n '&redirect_uri=' +\n encodeURIComponent(getBaseUrl()) +\n '&scope=' +\n encodeURIComponent(DEFAULT_SCOPE) +\n '&code_challenge_method=S256' +\n '&code_challenge=' +\n encodeURIComponent(this.#storage.getString('codeChallenge') as string)\n );\n }\n\n /**\n * Processes an OAuth authorization code.\n * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest\n * @param code The authorization code received by URL parameter.\n */\n processCode(code: string): Promise<ProfileResource> {\n const pkceState = this.#storage.getString('pkceState');\n if (!pkceState) {\n this.clear();\n throw new Error('Invalid PCKE state');\n }\n\n const codeVerifier = this.#storage.getString('codeVerifier');\n if (!codeVerifier) {\n this.clear();\n throw new Error('Invalid PCKE code verifier');\n }\n\n return this.#fetchTokens(\n 'grant_type=authorization_code' +\n (this.#clientId ? '&client_id=' + encodeURIComponent(this.#clientId) : '') +\n '&code_verifier=' +\n encodeURIComponent(codeVerifier) +\n '&redirect_uri=' +\n encodeURIComponent(getBaseUrl()) +\n '&code=' +\n encodeURIComponent(code)\n );\n }\n\n /**\n * Tries to refresh the auth tokens.\n * See: https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens\n */\n async #refresh(): Promise<void> {\n if (this.#refreshPromise) {\n return this.#refreshPromise;\n }\n\n if (!this.#refreshToken) {\n this.clear();\n return Promise.reject('Invalid refresh token');\n }\n\n this.#refreshPromise = this.#fetchTokens(\n 'grant_type=refresh_token' +\n '&client_id=' +\n encodeURIComponent(this.#clientId) +\n '&refresh_token=' +\n encodeURIComponent(this.#refreshToken)\n );\n\n await this.#refreshPromise;\n }\n\n /**\n * Makes a POST request to the tokens endpoint.\n * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint\n * @param formBody Token parameters in URL encoded format.\n */\n async #fetchTokens(formBody: string): Promise<ProfileResource> {\n if (!this.#tokenUrl) {\n return Promise.reject('Missing token URL');\n }\n\n return this.#fetch(this.#tokenUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: formBody,\n })\n .then((response) => {\n if (!response.ok) {\n return Promise.reject('Failed to fetch tokens');\n }\n return response.json();\n })\n .then((tokens) => this.#verifyTokens(tokens))\n .then(() => this.getProfile() as ProfileResource);\n }\n\n /**\n * Verifies the tokens received from the auth server.\n * Validates the JWT against the JWKS.\n * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint\n * @param tokens\n */\n async #verifyTokens(tokens: TokenResponse): Promise<void> {\n const token = tokens.access_token;\n\n // Verify token has not expired\n const tokenPayload = parseJWTPayload(token);\n if (Date.now() >= (tokenPayload.exp as number) * 1000) {\n this.clear();\n return Promise.reject('Token expired');\n }\n\n // Verify app_client_id\n if (this.#clientId && tokenPayload.client_id !== this.#clientId) {\n this.clear();\n return Promise.reject('Token was not issued for this audience');\n }\n\n await this.setActiveLogin({\n accessToken: token,\n refreshToken: tokens.refresh_token,\n project: tokens.project,\n profile: tokens.profile,\n });\n }\n\n /**\n * Sets up a listener for window storage events.\n * This synchronizes state across browser windows and browser tabs.\n */\n #setupStorageListener(): void {\n try {\n window.addEventListener('storage', (e: StorageEvent) => {\n if (e.key === null || e.key === 'activeLogin') {\n // Storage events fire when different tabs make changes.\n // On storage clear (key === null) or activeLogin change (key === 'activeLogin')\n // Refresh the page to ensure the active login is up to date.\n window.location.reload();\n }\n });\n } catch (err) {\n // Silently ignore if this environment does not support storage events\n }\n }\n}\n\n/**\n * Returns the base URL for the current page.\n */\nfunction getBaseUrl(): string {\n return window.location.protocol + '//' + window.location.host + '/';\n}\n","/*\n * Based on: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\n */\n\ninterface Event {\n readonly type: string;\n readonly defaultPrevented?: boolean;\n}\n\ntype EventListener = (e: Event) => void;\n\nexport class EventTarget {\n readonly #listeners: Record<string, EventListener[]>;\n\n constructor() {\n this.#listeners = {};\n }\n\n addEventListener(type: string, callback: EventListener): void {\n if (!this.#listeners[type]) {\n this.#listeners[type] = [];\n }\n this.#listeners[type].push(callback);\n }\n\n removeEventListeneer(type: string, callback: EventListener): void {\n const array = this.#listeners[type];\n if (!array) {\n return;\n }\n for (let i = 0; i < array.length; i++) {\n if (array[i] === callback) {\n array.splice(i, 1);\n return;\n }\n }\n }\n\n dispatchEvent(event: Event): boolean {\n const array = this.#listeners[event.type];\n if (array) {\n array.forEach((listener) => listener.call(this, event));\n }\n return !event.defaultPrevented;\n }\n}\n","import { ElementDefinition, SearchParameter } from '@medplum/fhirtypes';\nimport { IndexedStructureDefinition } from './types';\nimport { capitalize } from './utils';\n\nexport enum SearchParameterType {\n BOOLEAN = 'BOOLEAN',\n NUMBER = 'NUMBER',\n QUANTITY = 'QUANTITY',\n TEXT = 'TEXT',\n REFERENCE = 'REFERENCE',\n DATE = 'DATE',\n DATETIME = 'DATETIME',\n PERIOD = 'PERIOD',\n}\n\nexport interface SearchParameterDetails {\n readonly columnName: string;\n readonly type: SearchParameterType;\n readonly elementDefinition?: ElementDefinition;\n readonly array?: boolean;\n}\n\n/**\n * Returns the type details of a SearchParameter.\n *\n * The SearchParameter resource has a \"type\" parameter, but that is missing some critical information.\n *\n * For example:\n * 1) The \"date\" type includes \"date\", \"datetime\", and \"period\".\n * 2) The \"token\" type includes enums and booleans.\n * 3) Arrays/multiple values are not reflected at all.\n *\n * @param structureDefinitions Collection of StructureDefinition resources indexed by name.\n * @param resourceType The root resource type.\n * @param searchParam The search parameter.\n * @returns The search parameter type details.\n */\nexport function getSearchParameterDetails(\n structureDefinitions: IndexedStructureDefinition,\n resourceType: string,\n searchParam: SearchParameter\n): SearchParameterDetails {\n if (searchParam.code === '_lastUpdated') {\n return { columnName: 'lastUpdated', type: SearchParameterType.DATETIME };\n }\n\n const columnName = convertCodeToColumnName(searchParam.code as string);\n const expression = getExpressionForResourceType(resourceType, searchParam.expression as string)?.split('.');\n if (!expression) {\n // This happens on compound types\n // In the future, explore returning multiple column definitions\n return { columnName, type: SearchParameterType.TEXT };\n }\n\n let baseType = resourceType;\n let elementDefinition = undefined;\n let propertyType = undefined;\n let array = false;\n\n for (let i = 1; i < expression.length; i++) {\n const propertyName = expression[i];\n elementDefinition = structureDefinitions.types[baseType]?.properties?.[propertyName];\n if (!elementDefinition) {\n // This happens on complex properties such as \"collected[x]\"/\"collectedDateTime\"/\"collectedPeriod\"\n // In the future, explore returning multiple column definitions\n return { columnName, type: SearchParameterType.TEXT, array };\n }\n\n if (elementDefinition.max === '*') {\n array = true;\n }\n\n propertyType = elementDefinition.type?.[0].code;\n if (!propertyType) {\n // This happens when one of parent properties uses contentReference\n // In the future, explore following the reference\n return { columnName, type: SearchParameterType.TEXT, array };\n }\n\n if (i < expression.length - 1) {\n if (propertyType === 'Element' || propertyType === 'BackboneElement') {\n baseType = baseType + capitalize(propertyName);\n } else {\n baseType = propertyType;\n }\n }\n }\n\n const type = getSearchParameterType(searchParam, propertyType as string);\n return { columnName, type, elementDefinition, array };\n}\n\n/**\n * Converts a hyphen-delimited code to camelCase string.\n * @param code The search parameter code.\n * @returns The SQL column name.\n */\nfunction convertCodeToColumnName(code: string): string {\n return code.split('-').reduce((result, word, index) => result + (index ? capitalize(word) : word), '');\n}\n\nfunction getSearchParameterType(searchParam: SearchParameter, propertyType: string): SearchParameterType {\n let type = SearchParameterType.TEXT;\n switch (searchParam.type) {\n case 'date':\n type = SearchParameterType.DATE;\n break;\n case 'number':\n type = SearchParameterType.NUMBER;\n break;\n case 'quantity':\n type = SearchParameterType.QUANTITY;\n break;\n case 'reference':\n type = SearchParameterType.REFERENCE;\n break;\n case 'token':\n if (propertyType === 'boolean') {\n type = SearchParameterType.BOOLEAN;\n }\n break;\n }\n return type;\n}\n\nexport function getExpressionForResourceType(resourceType: string, expression: string): string | undefined {\n const expressions = expression.split(' | ');\n for (const e of expressions) {\n const simplified = simplifyExpression(e);\n if (simplified.startsWith(resourceType + '.')) {\n return simplified;\n }\n }\n return undefined;\n}\n\nfunction simplifyExpression(input: string): string {\n let result = input.trim();\n\n if (result.startsWith('(') && result.endsWith(')')) {\n result = result.substring(1, result.length - 1);\n }\n\n if (result.includes(' as ')) {\n result = result.substring(0, result.indexOf(' as '));\n }\n\n if (result.includes('.where(')) {\n result = result.substring(0, result.indexOf('.where('));\n }\n\n return result;\n}\n"],"names":["__awaiter","thisArg","_arguments","P","generator","Promise","resolve","reject","fulfilled","value","step","next","e","rejected","result","done","then","apply","__classPrivateFieldGet","receiver","state","kind","f","TypeError","has","call","get","__classPrivateFieldSet","set","LRUCache","constructor","max","_LRUCache_max","this","_LRUCache_cache","Map","clear","key","item","delete","val","size","_LRUCache_instances","_LRUCache_first","formatAddress","address","options","builder","line","push","city","postalCode","use","all","join","trim","formatHumanName","name","prefix","given","family","suffix","formatGivenName","formatFamilyName","createReference","resource","reference","getReferenceString","display","getDisplayString","resourceType","id","resolveId","_a","split","isProfileResource","profileName","names","length","getProfileResourceDisplayString","deviceName","device","getDeviceDisplayString","email","getImageSrc","photos","photo","url","contentType","startsWith","getDateProperty","date","Date","undefined","stringify","pretty","JSON","stringifyReplacer","k","v","t","Object","keys","isEmpty","deepEquals","object1","object2","path","keys1","keys2","filter","val1","val2","isObject","object","byteToHex","n","toString","padStart","arrayBufferToHex","arrayBuffer","bytes","Uint8Array","Array","i","arrayBufferToBase64","String","fromCharCode","window","btoa","capitalize","word","charAt","toUpperCase","substr","isLowerCase","c","toLowerCase","getRandomString","randomItems","Uint32Array","crypto","getRandomValues","buffer","parseJWTPayload","token","_header","payload","_signature","cleanedPayload","replace","decodedPayload","atob","uriEncodedPayload","from","reduce","acc","char","charCodeAt","slice","jsonPayload","decodeURIComponent","parse","decodePayload","allOk","issue","severity","code","details","text","created","notModified","notFound","gone","accessDenied","badRequest","expression","isOk","outcome","isNotFound","isGone","getStatus","assertOk","OperationOutcomeError","Error","super","_b","Operator","MODIFIER_OPERATORS","CONTAINS","EXACT","TEXT","ABOVE","BELOW","IN","NOT_IN","OF_TYPE","PREFIX_OPERATORS","NOT_EQUALS","GREATER_THAN","LESS_THAN","GREATER_THAN_OR_EQUALS","LESS_THAN_OR_EQUALS","STARTS_AFTER","ENDS_BEFORE","APPROXIMATELY","parseSearchDefinition","location","pathname","pop","filters","sortRules","fields","page","count","total","URLSearchParams","search","forEach","parseInt","substring","descending","parseSortRule","operator","EQUALS","modifier","modifierIndex","indexOf","match","RegExp","parseSearchFilter","formatSearchQuery","definition","params","includes","encodeURIComponent","formatFilter","map","sr","formatSortRules","sort","PropertyType","ClientStorage","_ClientStorage_storage","localStorage","MemoryStorage","getString","getItem","setString","setItem","removeItem","getObject","str","setObject","_MemoryStorage_data","index","createSchema","types","createTypeSchema","typeName","description","properties","searchParams","_lastUpdated","base","type","indexStructureDefinition","schema","structureDefinition","elements","snapshot","element","filtered","typeCode","parts","buildTypeName","parentType","indexType","typeSchema","indexProperty","indexSearchParameter","searchParam","components","getPropertyDisplayName","property","propertyName","replaceAll","DEFAULT_SCOPE","MedplumClient","_EventTarget_listeners","addEventListener","callback","removeEventListeneer","array","splice","dispatchEvent","event","listener","defaultPrevented","_MedplumClient_fetch","_MedplumClient_storage","_MedplumClient_schema","_MedplumClient_resourceCache","_MedplumClient_baseUrl","_MedplumClient_clientId","_MedplumClient_authorizeUrl","_MedplumClient_tokenUrl","_MedplumClient_logoutUrl","_MedplumClient_onUnauthenticated","_MedplumClient_accessToken","_MedplumClient_refreshToken","_MedplumClient_refreshPromise","_MedplumClient_profilePromise","_MedplumClient_profile","_MedplumClient_config","baseUrl","endsWith","fetch","bind","resourceCacheSize","clientId","authorizeUrl","tokenUrl","logoutUrl","onUnauthenticated","activeLogin","getActiveLogin","accessToken","refreshToken","_MedplumClient_instances","_MedplumClient_refreshProfile","catch","console","log","_MedplumClient_setupStorageListener","_MedplumClient_request","post","body","put","register","request","response","setActiveLogin","startLogin","password","remember","_MedplumClient_startPkce","scope","codeChallengeMethod","codeChallenge","startGoogleLogin","googleResponse","signOut","signInWithRedirect","processCode","_MedplumClient_requestAuthorization","signOutWithRedirect","assign","fhirUrl","p","searchValueSet","system","getCached","cached","getCachedReference","read","cacheKey","promise","readCached","readReference","refString","readCachedReference","getSchema","requestSchema","query","graphql","data","StructureDefinitionList","searchParameter","SearchParameterList","readHistory","readPatientEverything","create","createBinary","filename","update","patch","operations","deleteResource","login","_MedplumClient_addLogin","getLogins","isLoading","getProfile","getProfileAsync","getUserConfiguration","download","_MedplumClient_buildFetchOptions","blob","codeVerifier","_MedplumClient_fetchTokens","getBaseUrl","protocol","host","SearchParameterType","getSearchParameterDetails","structureDefinitions","columnName","DATETIME","getExpressionForResourceType","elementDefinition","propertyType","baseType","_c","_d","DATE","NUMBER","QUANTITY","REFERENCE","BOOLEAN","getSearchParameterType","expressions","simplified","simplifyExpression","input","newLogin","logins","profile","config","method","status","_MedplumClient_handleUnauthenticated","obj","json","headers","cache","credentials","File","_MedplumClient_refresh","error","pkceState","subtle","digest","TextEncoder","encode","encryptSHA256","formBody","ok","tokens","_MedplumClient_verifyTokens","access_token","tokenPayload","now","exp","client_id","refresh_token","project","reload","err"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.min.js","sources":["../../../../node_modules/tslib/tslib.es6.js","../../../src/cache.ts","../../../src/format.ts","../../../src/utils.ts","../../../src/crypto.ts","../../../src/jwt.ts","../../../src/outcomes.ts","../../../src/search.ts","../../../src/types.ts","../../../src/storage.ts","../../../src/client.ts","../../../src/eventtarget.ts","../../../src/hl7.ts","../../../src/searchparams.ts","../../../src/repo.ts"],"sourcesContent":["/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\nexport function __classPrivateFieldIn(state, receiver) {\r\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\r\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\r\n}\r\n","/**\n * LRU cache (least recently used)\n * Source: https://stackoverflow.com/a/46432113\n */\nexport class LRUCache<T> {\n readonly #max: number;\n readonly #cache: Map<string, T>;\n\n constructor(max = 10) {\n this.#max = max;\n this.#cache = new Map();\n }\n\n clear(): void {\n this.#cache.clear();\n }\n\n get(key: string): T | undefined {\n const item = this.#cache.get(key);\n if (item) {\n this.#cache.delete(key);\n this.#cache.set(key, item);\n }\n return item;\n }\n\n set(key: string, val: T): void {\n if (this.#cache.has(key)) {\n this.#cache.delete(key);\n } else if (this.#cache.size >= this.#max) {\n this.#cache.delete(this.#first());\n }\n this.#cache.set(key, val);\n }\n\n #first(): string {\n // This works because the Map class maintains ordered keys.\n return this.#cache.keys().next().value;\n }\n}\n","import { Address, HumanName } from '@medplum/fhirtypes';\n\nexport interface AddressFormatOptions {\n all?: boolean;\n use?: boolean;\n}\n\nexport interface HumanNameFormatOptions {\n all?: boolean;\n prefix?: boolean;\n suffix?: boolean;\n use?: boolean;\n}\n\nexport function formatAddress(address: Address, options?: AddressFormatOptions): string {\n const builder = [];\n\n if (address.line) {\n builder.push(...address.line);\n }\n\n if (address.city) {\n builder.push(address.city);\n }\n\n if (address.state) {\n builder.push(address.state);\n }\n\n if (address.postalCode) {\n builder.push(address.postalCode);\n }\n\n if (address.use && (options?.all || options?.use)) {\n builder.push('[' + address.use + ']');\n }\n\n return builder.join(', ').trim();\n}\n\nexport function formatHumanName(name: HumanName, options?: HumanNameFormatOptions): string {\n const builder = [];\n\n if (name.prefix && (options?.all || options?.prefix)) {\n builder.push(...name.prefix);\n }\n\n if (name.given) {\n builder.push(...name.given);\n }\n\n if (name.family) {\n builder.push(name.family);\n }\n\n if (name.suffix && (options?.all || options?.suffix)) {\n builder.push(...name.suffix);\n }\n\n if (name.use && (options?.all || options?.use)) {\n builder.push('[' + name.use + ']');\n }\n\n return builder.join(' ').trim();\n}\n\nexport function formatGivenName(name: HumanName): string {\n const builder: string[] = [];\n if (name.given) {\n builder.push(...name.given);\n }\n return builder.join(' ').trim();\n}\n\nexport function formatFamilyName(name: HumanName): string {\n return name.family || '';\n}\n","import {\n Attachment,\n Device,\n Extension,\n Patient,\n Practitioner,\n QuestionnaireResponse,\n QuestionnaireResponseItem,\n QuestionnaireResponseItemAnswer,\n Reference,\n RelatedPerson,\n Resource,\n} 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 the ID portion of a reference.\n * @param reference A FHIR reference.\n * @returns The ID portion of a reference.\n */\nexport function resolveId(reference: Reference | undefined): string | undefined {\n return reference?.reference?.split('/')[1];\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 === 'Observation') {\n if ('code' in resource && (resource.code as any)?.text) {\n return (resource.code as any)?.text;\n }\n }\n if (resource.resourceType === 'User') {\n if (resource.email) {\n return resource.email;\n }\n }\n if ('name' in resource && resource.name && typeof resource.name === 'string') {\n return resource.name;\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 const url = getPhotoImageSrc(photo);\n if (url) {\n return url;\n }\n }\n }\n }\n if (resource.resourceType === 'Bot' && resource.photo) {\n const url = getPhotoImageSrc(resource.photo);\n if (url) {\n return url;\n }\n }\n return undefined;\n}\n\nfunction getPhotoImageSrc(photo: Attachment): string | undefined {\n if (photo.url && photo.contentType && photo.contentType.startsWith('image/')) {\n return photo.url;\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 * Calculates the age in years from the birth date.\n * @param birthDateStr The birth date or start date in ISO-8601 format YYYY-MM-DD.\n * @param endDateStr Optional end date in ISO-8601 format YYYY-MM-DD. Default value is today.\n * @returns The age in years, months, and days.\n */\nexport function calculateAge(\n birthDateStr: string,\n endDateStr?: string\n): { years: number; months: number; days: number } {\n const startDate = new Date(birthDateStr);\n startDate.setUTCHours(0, 0, 0, 0);\n\n const endDate = endDateStr ? new Date(endDateStr) : new Date();\n endDate.setUTCHours(0, 0, 0, 0);\n\n const startYear = startDate.getUTCFullYear();\n const startMonth = startDate.getUTCMonth();\n const startDay = startDate.getUTCDate();\n\n const endYear = endDate.getUTCFullYear();\n const endMonth = endDate.getUTCMonth();\n const endDay = endDate.getUTCDate();\n\n let years = endYear - startYear;\n if (endMonth < startMonth || (endMonth === startMonth && endDay < startDay)) {\n years--;\n }\n\n let months = endYear * 12 + endMonth - (startYear * 12 + startMonth);\n if (endDay < startDay) {\n months--;\n }\n\n const days = Math.floor((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24));\n\n return { years, months, days };\n}\n\n/**\n * Calculates the age string for display using the age appropriate units.\n * If the age is greater than or equal to 2 years, then the age is displayed in years.\n * If the age is greater than or equal to 1 month, then the age is displayed in months.\n * Otherwise, the age is displayed in days.\n * @param birthDateStr The birth date or start date in ISO-8601 format YYYY-MM-DD.\n * @param endDateStr Optional end date in ISO-8601 format YYYY-MM-DD. Default value is today.\n * @returns The age string.\n */\nexport function calculateAgeString(birthDateStr: string, endDateStr?: string): string | undefined {\n const { years, months, days } = calculateAge(birthDateStr, endDateStr);\n if (years >= 2) {\n return years.toString().padStart(3, '0') + 'Y';\n } else if (months >= 1) {\n return months.toString().padStart(3, '0') + 'M';\n } else {\n return days.toString().padStart(3, '0') + 'D';\n }\n}\n\n/**\n * Returns all questionnaire answers as a map by link ID.\n * @param response The questionnaire response resource.\n * @returns Questionnaire answers mapped by link ID.\n */\nexport function getQuestionnaireAnswers(\n response: QuestionnaireResponse\n): Record<string, QuestionnaireResponseItemAnswer> {\n const result: Record<string, QuestionnaireResponseItemAnswer> = {};\n buildQuestionnaireAnswerItems(response.item, result);\n return result;\n}\n\n/**\n * Recursively builds the questionnaire answer items map.\n * @param item The current questionnaire response item.\n * @param result The cumulative result map.\n */\nfunction buildQuestionnaireAnswerItems(\n items: QuestionnaireResponseItem[] | undefined,\n result: Record<string, QuestionnaireResponseItemAnswer>\n): void {\n if (items) {\n for (const item of items) {\n if (item.linkId && item.answer && item.answer.length > 0) {\n result[item.linkId] = item.answer[0];\n }\n buildQuestionnaireAnswerItems(item.item, result);\n }\n }\n}\n\n/**\n * Returns an extension value by extension URLs.\n * @param resource The base resource.\n * @param urls Array of extension URLs. Each entry represents a nested extension.\n * @returns The extension value if found; undefined otherwise.\n */\nexport function getExtensionValue(resource: Resource, ...urls: string[]): string | undefined {\n // Let curr be the current resource or extension. Extensions can be nested.\n let curr: any = resource;\n\n // For each of the urls, try to find a matching nested extension.\n for (let i = 0; i < urls.length && curr; i++) {\n curr = (curr?.extension as Extension[] | undefined)?.find((e) => e.url === urls[i]);\n }\n\n return curr?.valueString as string | 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 * @param {string} k Property key.\n * @param {*} v Property value.\n */\nfunction stringifyReplacer(k: string, v: any): any {\n return !isArrayKey(k) && isEmpty(v) ? undefined : v;\n}\n\n/**\n * Returns true if the key is an array key.\n * @param k The property key.\n * @returns True if the key is an array key.\n */\nfunction isArrayKey(k: string): boolean {\n return !!k.match(/\\d+$/);\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 * @param object1 The first object.\n * @param object2 The second object.\n * @returns True if the objects are equal.\n */\nexport function deepEquals(object1: unknown, object2: unknown, path?: string): boolean {\n if (object1 === object2) {\n return true;\n }\n if (isEmpty(object1) && isEmpty(object2)) {\n return true;\n }\n if (isEmpty(object1) || isEmpty(object2)) {\n return false;\n }\n if (Array.isArray(object1) && Array.isArray(object2)) {\n return deepEqualsArray(object1, object2);\n }\n if (Array.isArray(object1) || Array.isArray(object2)) {\n return false;\n }\n if (isObject(object1) && isObject(object2)) {\n return deepEqualsObject(object1, object2, path);\n }\n if (isObject(object1) || isObject(object2)) {\n return false;\n }\n return false;\n}\n\nfunction deepEqualsArray(array1: unknown[], array2: unknown[]): boolean {\n if (array1.length !== array2.length) {\n return false;\n }\n for (let i = 0; i < array1.length; i++) {\n if (!deepEquals(array1[i], array2[i])) {\n return false;\n }\n }\n return true;\n}\n\nfunction deepEqualsObject(\n object1: Record<string, unknown>,\n object2: Record<string, unknown>,\n path: string | undefined\n): boolean {\n const keySet = new Set<string>();\n Object.keys(object1).forEach((k) => keySet.add(k));\n Object.keys(object2).forEach((k) => keySet.add(k));\n if (path === 'meta') {\n keySet.delete('versionId');\n keySet.delete('lastUpdated');\n keySet.delete('author');\n }\n for (const key of keySet) {\n const val1 = object1[key];\n const val2 = object2[key];\n if (!deepEquals(val1, val2, key)) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Returns true if the input is an object.\n * @param object The candidate object.\n * @returns True if the input is a non-null non-undefined object.\n */\nexport function isObject(obj: unknown): obj is Record<string, unknown> {\n return obj !== null && typeof obj === 'object';\n}\n\n/**\n * Returns true if the input array is an array of strings.\n * @param arr Input array.\n * @returns True if the input array is an array of strings.\n */\nexport function isStringArray(arr: any[]): arr is string[] {\n return arr.every((e) => typeof e === 'string');\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","import { arrayBufferToHex } from './utils';\n\n/**\n * Returns a cryptographically secure random string.\n */\nexport function getRandomString(): string {\n const randomItems = new Uint32Array(28);\n crypto.getRandomValues(randomItems);\n return arrayBufferToHex(randomItems.buffer);\n}\n\n/**\n * Encrypts a string with SHA256 encryption.\n * @param str\n */\nexport async function encryptSHA256(str: string): Promise<ArrayBuffer> {\n return crypto.subtle.digest('SHA-256', new TextEncoder().encode(str));\n}\n","/**\n * Decodes a section of a JWT.\n * See: https://tools.ietf.org/html/rfc7519\n * @param payload\n */\nfunction decodePayload(payload: string): Record<string, number | string> {\n const cleanedPayload = payload.replace(/-/g, '+').replace(/_/g, '/');\n const decodedPayload = decodeBase64(cleanedPayload);\n const uriEncodedPayload = Array.from(decodedPayload).reduce((acc, char) => {\n const uriEncodedChar = ('00' + char.charCodeAt(0).toString(16)).slice(-2);\n return `${acc}%${uriEncodedChar}`;\n }, '');\n const jsonPayload = decodeURIComponent(uriEncodedPayload);\n return JSON.parse(jsonPayload);\n}\n\nfunction decodeBase64(data: string): string {\n if (typeof window !== 'undefined') {\n return window.atob(data);\n }\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(data, 'base64').toString('binary');\n }\n throw new Error('Unable to decode base64');\n}\n\n/**\n * Parses the JWT payload.\n * @param token JWT token\n */\nexport function parseJWTPayload(token: string): Record<string, number | string> {\n const [_header, payload, _signature] = token.split('.');\n return decodePayload(payload);\n}\n","import { OperationOutcome } from '@medplum/fhirtypes';\n\nconst OK_ID = 'ok';\nconst CREATED_ID = 'created';\nconst GONE_ID = 'gone';\nconst NOT_MODIFIED_ID = 'not-modified';\nconst NOT_FOUND_ID = 'not-found';\nconst ACCESS_DENIED = 'access-denied';\n\nexport const allOk: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: OK_ID,\n issue: [\n {\n severity: 'information',\n code: 'information',\n details: {\n text: 'All OK',\n },\n },\n ],\n};\n\nexport const created: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: CREATED_ID,\n issue: [\n {\n severity: 'information',\n code: 'information',\n details: {\n text: 'Created',\n },\n },\n ],\n};\n\nexport const notModified: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: NOT_MODIFIED_ID,\n issue: [\n {\n severity: 'information',\n code: 'information',\n details: {\n text: 'Not Modified',\n },\n },\n ],\n};\n\nexport const notFound: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: NOT_FOUND_ID,\n issue: [\n {\n severity: 'error',\n code: 'not-found',\n details: {\n text: 'Not found',\n },\n },\n ],\n};\n\nexport const gone: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: GONE_ID,\n issue: [\n {\n severity: 'error',\n code: 'gone',\n details: {\n text: 'Gone',\n },\n },\n ],\n};\n\nexport const accessDenied: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: ACCESS_DENIED,\n issue: [\n {\n severity: 'error',\n code: 'access-denied',\n details: {\n text: 'Access Denied',\n },\n },\n ],\n};\n\nexport function badRequest(details: string, expression?: string): OperationOutcome {\n return {\n resourceType: 'OperationOutcome',\n issue: [\n {\n severity: 'error',\n code: 'invalid',\n details: {\n text: details,\n },\n expression: expression ? [expression] : undefined,\n },\n ],\n };\n}\n\nexport function isOk(outcome: OperationOutcome): boolean {\n return outcome.id === OK_ID || outcome.id === CREATED_ID || outcome.id === NOT_MODIFIED_ID;\n}\n\nexport function isNotFound(outcome: OperationOutcome): boolean {\n return outcome.id === NOT_FOUND_ID;\n}\n\nexport function isGone(outcome: OperationOutcome): boolean {\n return outcome.id === GONE_ID;\n}\n\nexport function getStatus(outcome: OperationOutcome): number {\n if (outcome.id === OK_ID) {\n return 200;\n } else if (outcome.id === CREATED_ID) {\n return 201;\n } else if (outcome.id === NOT_MODIFIED_ID) {\n return 304;\n } else if (outcome.id === ACCESS_DENIED) {\n return 403;\n } else if (outcome.id === NOT_FOUND_ID) {\n return 404;\n } else if (outcome.id === GONE_ID) {\n return 410;\n } else {\n return 400;\n }\n}\n\n/**\n * Asserts that the operation completed successfully and that the resource is defined.\n * @param outcome The operation outcome.\n * @param resource The resource that may or may not have been returned.\n */\nexport function assertOk<T>(outcome: OperationOutcome, resource: T | undefined): asserts resource is T {\n if (!isOk(outcome) || resource === undefined) {\n throw new OperationOutcomeError(outcome);\n }\n}\n\nexport class OperationOutcomeError extends Error {\n readonly outcome: OperationOutcome;\n\n constructor(outcome: OperationOutcome) {\n super(outcome?.issue?.[0].details?.text);\n this.outcome = outcome;\n }\n}\n","export const DEFAULT_SEARCH_COUNT = 20;\n\nexport interface SearchRequest {\n readonly resourceType: string;\n filters?: Filter[];\n sortRules?: SortRule[];\n offset?: number;\n count?: number;\n fields?: string[];\n name?: string;\n total?: 'none' | 'estimate' | 'accurate';\n}\n\nexport interface Filter {\n code: string;\n operator: Operator;\n value: string;\n unitSystem?: string;\n unitCode?: string;\n}\n\nexport interface SortRule {\n code: string;\n descending?: boolean;\n}\n\n/**\n * Search operators.\n * These operators represent \"modifiers\" and \"prefixes\" in FHIR search.\n * See: https://www.hl7.org/fhir/search.html\n */\nexport enum Operator {\n EQUALS = 'eq',\n NOT_EQUALS = 'ne',\n\n // Numbers\n GREATER_THAN = 'gt',\n LESS_THAN = 'lt',\n GREATER_THAN_OR_EQUALS = 'ge',\n LESS_THAN_OR_EQUALS = 'le',\n\n // Dates\n STARTS_AFTER = 'sa',\n ENDS_BEFORE = 'eb',\n APPROXIMATELY = 'ap',\n\n // String\n CONTAINS = 'contains',\n EXACT = 'exact',\n\n // Token\n TEXT = 'text',\n ABOVE = 'above',\n BELOW = 'below',\n IN = 'in',\n NOT_IN = 'not-in',\n OF_TYPE = 'of-type',\n}\n\nconst MODIFIER_OPERATORS: Operator[] = [\n Operator.CONTAINS,\n Operator.EXACT,\n Operator.TEXT,\n Operator.ABOVE,\n Operator.BELOW,\n Operator.IN,\n Operator.NOT_IN,\n Operator.OF_TYPE,\n];\n\nconst PREFIX_OPERATORS: Operator[] = [\n Operator.NOT_EQUALS,\n Operator.GREATER_THAN,\n Operator.LESS_THAN,\n Operator.GREATER_THAN_OR_EQUALS,\n Operator.LESS_THAN_OR_EQUALS,\n Operator.STARTS_AFTER,\n Operator.ENDS_BEFORE,\n Operator.APPROXIMATELY,\n];\n\n/**\n * Parses a URL into a SearchRequest.\n *\n * See the FHIR search spec: http://hl7.org/fhir/r4/search.html\n *\n * @param url The URL to parse.\n * @returns Parsed search definition.\n */\nexport function parseSearchDefinition(url: string): SearchRequest {\n const location = new URL(url, 'https://example.com/');\n const resourceType = location.pathname\n .replace(/(^\\/)|(\\/$)/g, '') // Remove leading and trailing slashes\n .split('/')\n .pop() as string;\n const params = new URLSearchParams(location.search);\n let filters: Filter[] | undefined = undefined;\n let sortRules: SortRule[] | undefined = undefined;\n let fields: string[] | undefined = undefined;\n let offset = undefined;\n let count = undefined;\n let total = undefined;\n\n params.forEach((value, key) => {\n if (key === '_fields') {\n fields = value.split(',');\n } else if (key === '_offset') {\n offset = parseInt(value);\n } else if (key === '_count') {\n count = parseInt(value);\n } else if (key === '_total') {\n total = value;\n } else if (key === '_sort') {\n sortRules = sortRules || [];\n sortRules.push(parseSortRule(value));\n } else {\n filters = filters || [];\n filters.push(parseSearchFilter(key, value));\n }\n });\n\n return {\n resourceType,\n filters,\n fields,\n offset,\n count,\n total,\n sortRules,\n };\n}\n\n/**\n * Parses a URL query parameter into a sort rule.\n *\n * By default, the sort rule is the field name.\n *\n * Sort rules can be reversed into descending order by prefixing the field name with a minus sign.\n *\n * See sorting: http://hl7.org/fhir/r4/search.html#_sort\n *\n * @param value The URL parameter value.\n * @returns The parsed sort rule.\n */\nfunction parseSortRule(value: string): SortRule {\n if (value.startsWith('-')) {\n return { code: value.substring(1), descending: true };\n } else {\n return { code: value };\n }\n}\n\n/**\n * Parses a URL query parameter into a search filter.\n *\n * FHIR search filters can be specified as modifiers or prefixes.\n *\n * For string properties, modifiers are appended to the key, e.g. \"name:contains=eve\".\n *\n * For date and numeric properties, prefixes are prepended to the value, e.g. \"birthdate=gt2000\".\n *\n * See the FHIR search spec: http://hl7.org/fhir/r4/search.html\n *\n * @param key The URL parameter key.\n * @param value The URL parameter value.\n * @returns The parsed search filter.\n */\nfunction parseSearchFilter(key: string, value: string): Filter {\n let code = key;\n let operator = Operator.EQUALS;\n\n for (const modifier of MODIFIER_OPERATORS) {\n const modifierIndex = code.indexOf(':' + modifier);\n if (modifierIndex !== -1) {\n operator = modifier;\n code = code.substring(0, modifierIndex);\n }\n }\n\n for (const prefix of PREFIX_OPERATORS) {\n if (value.match(new RegExp('^' + prefix + '\\\\d'))) {\n operator = prefix;\n value = value.substring(prefix.length);\n }\n }\n\n return { code, operator, value };\n}\n\n/**\n * Formats a search definition object into a query string.\n * Note: The return value does not include the resource type.\n * @param {!SearchRequest} definition The search definition.\n * @returns Formatted URL.\n */\nexport function formatSearchQuery(definition: SearchRequest): string {\n const params: string[] = [];\n\n if (definition.fields) {\n params.push('_fields=' + definition.fields.join(','));\n }\n\n if (definition.filters) {\n definition.filters.forEach((filter) => params.push(formatFilter(filter)));\n }\n\n if (definition.sortRules && definition.sortRules.length > 0) {\n params.push(formatSortRules(definition.sortRules));\n }\n\n if (definition.offset !== undefined) {\n params.push('_offset=' + definition.offset);\n }\n\n if (definition.count !== undefined) {\n params.push('_count=' + definition.count);\n }\n\n if (definition.total !== undefined) {\n params.push('_total=' + encodeURIComponent(definition.total));\n }\n\n if (params.length === 0) {\n return '';\n }\n\n params.sort();\n return '?' + params.join('&');\n}\n\nfunction formatFilter(filter: Filter): string {\n const modifier = MODIFIER_OPERATORS.includes(filter.operator) ? ':' + filter.operator : '';\n const prefix = PREFIX_OPERATORS.includes(filter.operator) ? filter.operator : '';\n return `${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`;\n}\n\nfunction formatSortRules(sortRules: SortRule[] | undefined): string {\n if (!sortRules || sortRules.length === 0) {\n return '';\n }\n return '_sort=' + sortRules.map((sr) => (sr.descending ? '-' + sr.code : sr.code)).join(',');\n}\n","import { ElementDefinition, SearchParameter, StructureDefinition } from '@medplum/fhirtypes';\nimport { capitalize } from './utils';\n\n/**\n * List of property types.\n * http://www.hl7.org/fhir/valueset-defined-types.html\n * The list here includes additions found from StructureDefinition resources.\n */\nexport enum PropertyType {\n Address = 'Address',\n Age = 'Age',\n Annotation = 'Annotation',\n Attachment = 'Attachment',\n BackboneElement = 'BackboneElement',\n CodeableConcept = 'CodeableConcept',\n Coding = 'Coding',\n ContactDetail = 'ContactDetail',\n ContactPoint = 'ContactPoint',\n Contributor = 'Contributor',\n Count = 'Count',\n DataRequirement = 'DataRequirement',\n Distance = 'Distance',\n Dosage = 'Dosage',\n Duration = 'Duration',\n Expression = 'Expression',\n Extension = 'Extension',\n HumanName = 'HumanName',\n Identifier = 'Identifier',\n MarketingStatus = 'MarketingStatus',\n Meta = 'Meta',\n Money = 'Money',\n Narrative = 'Narrative',\n ParameterDefinition = 'ParameterDefinition',\n Period = 'Period',\n Population = 'Population',\n ProdCharacteristic = 'ProdCharacteristic',\n ProductShelfLife = 'ProductShelfLife',\n Quantity = 'Quantity',\n Range = 'Range',\n Ratio = 'Ratio',\n Reference = 'Reference',\n RelatedArtifact = 'RelatedArtifact',\n Resource = 'Resource',\n SampledData = 'SampledData',\n Signature = 'Signature',\n SubstanceAmount = 'SubstanceAmount',\n SystemString = 'http://hl7.org/fhirpath/System.String',\n Timing = 'Timing',\n TriggerDefinition = 'TriggerDefinition',\n UsageContext = 'UsageContext',\n base64Binary = 'base64Binary',\n boolean = 'boolean',\n canonical = 'canonical',\n code = 'code',\n date = 'date',\n dateTime = 'dateTime',\n decimal = 'decimal',\n id = 'id',\n instant = 'instant',\n integer = 'integer',\n markdown = 'markdown',\n oid = 'oid',\n positiveInt = 'positiveInt',\n string = 'string',\n time = 'time',\n unsignedInt = 'unsignedInt',\n uri = 'uri',\n url = 'url',\n uuid = 'uuid',\n}\n\n/**\n * An IndexedStructureDefinition is a lookup-optimized version of a StructureDefinition.\n *\n * StructureDefinition resources contain schema information for other resource types.\n * These schemas can be used to automatically generate user interface elements for\n * resources.\n *\n * However, a StructureDefinition resource is not optimized for realtime lookups. All\n * resource types, sub types, and property definitions are stored in a flat array of\n * ElementDefinition objects. Therefore, to lookup the schema for a property (i.e., \"Patient.name\")\n * requires a linear scan of all ElementDefinition objects\n *\n * A StructureDefinition resource contains information about one or more types.\n * For example, the \"Patient\" StructureDefinition includes \"Patient\", \"Patient_Contact\",\n * \"Patient_Communication\", and \"Patient_Link\". This is inefficient.\n *\n * Instead, we create an indexed version of the StructureDefinition, called IndexedStructureDefinition.\n * In an IndexedStructureDefinition, retrieving a property definition is a hashtable lookup.\n *\n * The hierarchy is:\n * IndexedStructureDefinition - top level for one resource type\n * TypeSchema - one per resource type and all contained BackboneElements\n * PropertySchema - one per property/field\n */\nexport interface IndexedStructureDefinition {\n types: { [resourceType: string]: TypeSchema };\n}\n\n/**\n * An indexed TypeSchema.\n *\n * Example: The IndexedStructureDefinition for \"Patient\" would include the following TypeSchemas:\n * 1) Patient\n * 2) Patient_Contact\n * 3) Patient_Communication\n * 4) Patient_Link\n */\nexport interface TypeSchema {\n display: string;\n properties: { [name: string]: ElementDefinition };\n searchParams?: { [code: string]: SearchParameter };\n description?: string;\n parentType?: string;\n}\n\n/**\n * Creates a new empty IndexedStructureDefinition.\n * @returns The empty IndexedStructureDefinition.\n */\nexport function createSchema(): IndexedStructureDefinition {\n return { types: {} };\n}\n\nexport function createTypeSchema(typeName: string, description: string | undefined): TypeSchema {\n return {\n display: typeName,\n description,\n properties: {},\n searchParams: {\n _lastUpdated: {\n base: [typeName],\n code: '_lastUpdated',\n type: 'date',\n expression: typeName + '.meta.lastUpdated',\n } as SearchParameter,\n },\n };\n}\n\n/**\n * Indexes a StructureDefinition for fast lookup.\n * See comments on IndexedStructureDefinition for more details.\n * @param schema The output IndexedStructureDefinition.\n * @param structureDefinition The original StructureDefinition.\n */\nexport function indexStructureDefinition(\n schema: IndexedStructureDefinition,\n structureDefinition: StructureDefinition\n): void {\n const typeName = structureDefinition.name;\n if (!typeName) {\n return;\n }\n\n schema.types[typeName] = createTypeSchema(typeName, structureDefinition.description);\n\n const elements = structureDefinition.snapshot?.element;\n if (elements) {\n // Filter out any elements missing path or type\n const filtered = elements.filter((e) => e.path !== typeName && e.path);\n\n // First pass, build types\n filtered.forEach((element) => indexType(schema, element));\n\n // Second pass, build properties\n filtered.forEach((element) => indexProperty(schema, element));\n }\n}\n\n/**\n * Indexes TypeSchema from an ElementDefinition.\n * In the common case, there will be many ElementDefinition instances per TypeSchema.\n * Only the first occurrence is saved.\n * @param schema The output IndexedStructureDefinition.\n * @param element The input ElementDefinition.\n */\nfunction indexType(schema: IndexedStructureDefinition, element: ElementDefinition): void {\n const path = element.path as string;\n const typeCode = element.type?.[0]?.code;\n if (typeCode !== 'Element' && typeCode !== 'BackboneElement') {\n return;\n }\n const parts = path.split('.');\n const typeName = buildTypeName(parts);\n if (!(typeName in schema.types)) {\n schema.types[typeName] = createTypeSchema(typeName, element.definition);\n schema.types[typeName].parentType = buildTypeName(parts.slice(0, parts.length - 1));\n }\n}\n\n/**\n * Indexes PropertySchema from an ElementDefinition.\n * @param schema The output IndexedStructureDefinition.\n * @param element The input ElementDefinition.\n */\nfunction indexProperty(schema: IndexedStructureDefinition, element: ElementDefinition): void {\n const path = element.path as string;\n const parts = path.split('.');\n if (parts.length === 1) {\n return;\n }\n const typeName = buildTypeName(parts.slice(0, parts.length - 1));\n const typeSchema = schema.types[typeName];\n const key = parts[parts.length - 1];\n typeSchema.properties[key] = element;\n}\n\n/**\n * Indexes a SearchParameter resource for fast lookup.\n * Indexes by SearchParameter.code, which is the query string parameter name.\n * @param schema The output IndexedStructureDefinition.\n * @param searchParam The SearchParameter resource.\n */\nexport function indexSearchParameter(schema: IndexedStructureDefinition, searchParam: SearchParameter): void {\n if (!searchParam.base) {\n return;\n }\n\n for (const resourceType of searchParam.base) {\n const typeSchema = schema.types[resourceType];\n if (!typeSchema) {\n continue;\n }\n\n if (!typeSchema.searchParams) {\n typeSchema.searchParams = {};\n }\n\n typeSchema.searchParams[searchParam.code as string] = searchParam;\n }\n}\n\nexport function buildTypeName(components: string[]): string {\n return components.map(capitalize).join('');\n}\n\nexport function getPropertyDisplayName(property: ElementDefinition): string {\n // Get the property name, which is the remainder after the last period\n // For example, for path \"Patient.birthDate\"\n // the property name is \"birthDate\"\n const propertyName = (property.path as string).replaceAll('[x]', '').split('.').pop() as string;\n\n // Special case for ID\n if (propertyName === 'id') {\n return 'ID';\n }\n\n // Split by capital letters\n // Capitalize the first letter of each word\n // Join together with spaces in between\n // Then normalize whitespace to single space character\n // For example, for property name \"birthDate\",\n // the display name is \"Birth Date\".\n return propertyName\n .split(/(?=[A-Z])/)\n .map(capitalize)\n .join(' ')\n .replace('_', ' ')\n .replace(/\\s+/g, ' ');\n}\n","import { stringify } from './utils';\n\n/**\n * The ClientStorage class is a utility class for storing strings and objects.\n *\n * When using MedplumClient in the browser, it will be backed by browser localStorage.\n *\n * When Using MedplumClient in the server, it will be backed by the MemoryStorage class.\n */\nexport class ClientStorage {\n readonly #storage: Storage;\n\n constructor() {\n this.#storage = typeof localStorage !== 'undefined' ? localStorage : new MemoryStorage();\n }\n\n clear(): void {\n this.#storage.clear();\n }\n\n getString(key: string): string | undefined {\n return this.#storage.getItem(key) || undefined;\n }\n\n setString(key: string, value: string | undefined): void {\n if (value) {\n this.#storage.setItem(key, value);\n } else {\n this.#storage.removeItem(key);\n }\n }\n\n getObject<T>(key: string): T | undefined {\n const str = this.getString(key);\n return str ? (JSON.parse(str) as T) : undefined;\n }\n\n setObject<T>(key: string, value: T): void {\n this.setString(key, value ? stringify(value) : undefined);\n }\n}\n\n/**\n * The MemoryStorage class is a minimal in-memory implementation of the Storage interface.\n */\nexport class MemoryStorage implements Storage {\n #data: Map<string, string>;\n\n constructor() {\n this.#data = new Map<string, string>();\n }\n\n /**\n * Returns the number of key/value pairs.\n */\n get length(): number {\n return this.#data.size;\n }\n\n /**\n * Removes all key/value pairs, if there are any.\n */\n clear(): void {\n this.#data.clear();\n }\n\n /**\n * Returns the current value associated with the given key, or null if the given key does not exist.\n */\n getItem(key: string): string | null {\n return this.#data.get(key) ?? null;\n }\n\n /**\n * Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.\n */\n setItem(key: string, value: string | null): void {\n if (value) {\n this.#data.set(key, value);\n } else {\n this.#data.delete(key);\n }\n }\n\n /**\n * Removes the key/value pair with the given key, if a key/value pair with the given key exists.\n */\n removeItem(key: string): void {\n this.#data.delete(key);\n }\n\n /**\n * Returns the name of the nth key, or null if n is greater than or equal to the number of key/value pairs.\n */\n key(index: number): string | null {\n return Array.from(this.#data.keys())[index];\n }\n}\n","// PKCE auth ased on:\n// https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/\n\nimport {\n Binary,\n Bundle,\n Project,\n ProjectMembership,\n Reference,\n Resource,\n SearchParameter,\n StructureDefinition,\n UserConfiguration,\n ValueSet,\n} from '@medplum/fhirtypes';\nimport type { Operation } from 'fast-json-patch';\nimport { LRUCache } from './cache';\nimport { encryptSHA256, getRandomString } from './crypto';\nimport { EventTarget } from './eventtarget';\nimport { parseJWTPayload } from './jwt';\nimport { isOk } from './outcomes';\nimport { formatSearchQuery, parseSearchDefinition, SearchRequest } from './search';\nimport { ClientStorage } from './storage';\nimport { createSchema, IndexedStructureDefinition, indexSearchParameter, indexStructureDefinition } from './types';\nimport { arrayBufferToBase64, ProfileResource, stringify } from './utils';\n\nconst DEFAULT_BASE_URL = 'https://api.medplum.com/';\nconst DEFAULT_SCOPE = 'launch/patient openid fhirUser offline_access user/*.*';\nconst DEFAULT_RESOURCE_CACHE_SIZE = 1000;\nconst JSON_CONTENT_TYPE = 'application/json';\nconst FHIR_CONTENT_TYPE = 'application/fhir+json';\nconst PATCH_CONTENT_TYPE = 'application/json-patch+json';\n\nexport interface MedplumClientOptions {\n /**\n * The client ID.\n * Optional. Default is to defer to the server to use the default client.\n * Use this to use a specific client for SMART-on-FHIR.\n */\n clientId?: string;\n\n /**\n * Base server URL.\n * Optional. Default value is \"https://api.medplum.com/\".\n * Use this to point to a custom Medplum deployment.\n */\n baseUrl?: string;\n\n /**\n * OAuth2 authorize URL.\n * Optional. Default value is baseUrl + \"/oauth2/authorize\".\n * Use this if you want to use a separate OAuth server.\n */\n authorizeUrl?: string;\n\n /**\n * OAuth2 token URL.\n * Optional. Default value is baseUrl + \"/oauth2/token\".\n * Use this if you want to use a separate OAuth server.\n */\n tokenUrl?: string;\n\n /**\n * OAuth2 logout URL.\n * Optional. Default value is baseUrl + \"/oauth2/logout\".\n * Use this if you want to use a separate OAuth server.\n */\n logoutUrl?: string;\n\n /**\n * Number of resources to store in the cache.\n * Optional. Default value is 1000.\n * Consider using this for performance of displaying Patient or Practitioner resources.\n */\n resourceCacheSize?: number;\n\n /**\n * Optional fetch implementation.\n * Optional. Default is window.fetch.\n * For nodejs applications, consider the 'node-fetch' package.\n */\n fetch?: FetchLike;\n\n /**\n * Optional callback for when the client is unauthenticated.\n * Default is do nothing.\n * For client side applications, consider redirecting to a sign in page.\n */\n onUnauthenticated?: () => void;\n}\n\nexport interface FetchLike {\n (url: string, options?: any): Promise<any>;\n}\n\nexport interface RegisterRequest {\n readonly firstName: string;\n readonly lastName: string;\n readonly projectName: string;\n readonly email: string;\n readonly password: string;\n readonly remember?: boolean;\n readonly recaptchaToken: string;\n}\n\nexport interface GoogleCredentialResponse {\n readonly clientId: string;\n readonly credential: string;\n}\n\nexport interface LoginAuthenticationResponse {\n readonly login: string;\n readonly code?: string;\n readonly memberships?: ProjectMembership[];\n}\n\nexport interface LoginProfileResponse {\n readonly login: string;\n readonly scope: string;\n}\n\nexport interface LoginScopeResponse {\n readonly login: string;\n readonly code: string;\n}\n\nexport interface LoginState {\n readonly project: Reference<Project>;\n readonly profile: Reference<ProfileResource>;\n readonly accessToken: string;\n readonly refreshToken: string;\n}\n\nexport interface TokenResponse {\n readonly token_type: string;\n readonly id_token: string;\n readonly access_token: string;\n readonly refresh_token: string;\n readonly expires_in: number;\n readonly project: Reference<Project>;\n readonly profile: Reference<ProfileResource>;\n}\n\ninterface SchemaGraphQLResponse {\n readonly data: {\n readonly StructureDefinitionList: StructureDefinition[];\n readonly SearchParameterList: SearchParameter[];\n };\n}\n\n/**\n * The MedplumClient class provides a client for the Medplum FHIR server.\n *\n * The client can be used in the browser, in a NodeJS application, or in a Medplum Bot.\n *\n * The client provides helpful methods for common operations such as:\n * 1) Authenticating\n * 2) Creating resources\n * 2) Reading resources\n * 3) Updating resources\n * 5) Deleting resources\n * 6) Searching\n * 7) Making GraphQL queries\n *\n * Here is a quick example of how to use the client:\n *\n * ```typescript\n * import { MedplumClient } from '@medplum/core';\n * const medplum = new MedplumClient();\n * ```\n *\n * Create a `Patient`:\n *\n * ```typescript\n * const patient = await medplum.createResource({\n * resourceType: 'Patient',\n * name: [{\n * given: ['Alice'],\n * family: 'Smith'\n * }]\n * });\n * ```\n *\n * Read a `Patient` by ID:\n *\n * ```typescript\n * const patient = await medplum.readResource('Patient', '123');\n * console.log(patient.name[0].given[0]);\n * ```\n *\n * Search for a `Patient` by name:\n *\n * ```typescript\n * const bundle = await medplum.search('Patient?name=Alice');\n * console.log(bundle.total);\n * ```\n *\n */\nexport class MedplumClient extends EventTarget {\n readonly #fetch: FetchLike;\n readonly #storage: ClientStorage;\n readonly #schema: IndexedStructureDefinition;\n readonly #resourceCache: LRUCache<Resource | Promise<Resource>>;\n readonly #baseUrl: string;\n readonly #clientId: string;\n readonly #authorizeUrl: string;\n readonly #tokenUrl: string;\n readonly #logoutUrl: string;\n readonly #onUnauthenticated?: () => void;\n #accessToken?: string;\n #refreshToken?: string;\n #refreshPromise?: Promise<any>;\n #profilePromise?: Promise<any>;\n #profile?: ProfileResource;\n #config?: UserConfiguration;\n\n constructor(options?: MedplumClientOptions) {\n super();\n\n if (options?.baseUrl) {\n if (!options.baseUrl.startsWith('http')) {\n throw new Error('Base URL must start with http or https');\n }\n if (!options.baseUrl.endsWith('/')) {\n throw new Error('Base URL must end with a trailing slash');\n }\n }\n\n this.#fetch = options?.fetch || window.fetch.bind(window);\n this.#storage = new ClientStorage();\n this.#schema = createSchema();\n this.#resourceCache = new LRUCache(options?.resourceCacheSize ?? DEFAULT_RESOURCE_CACHE_SIZE);\n this.#baseUrl = options?.baseUrl || DEFAULT_BASE_URL;\n this.#clientId = options?.clientId || '';\n this.#authorizeUrl = options?.authorizeUrl || this.#baseUrl + 'oauth2/authorize';\n this.#tokenUrl = options?.tokenUrl || this.#baseUrl + 'oauth2/token';\n this.#logoutUrl = options?.logoutUrl || this.#baseUrl + 'oauth2/logout';\n this.#onUnauthenticated = options?.onUnauthenticated;\n\n const activeLogin = this.getActiveLogin();\n if (activeLogin) {\n this.#accessToken = activeLogin.accessToken;\n this.#refreshToken = activeLogin.refreshToken;\n this.#refreshProfile().catch(console.log);\n }\n\n this.#setupStorageListener();\n }\n\n /**\n * Clears all auth state including local storage and session storage.\n */\n clear(): void {\n this.#storage.clear();\n this.#resourceCache.clear();\n this.#accessToken = undefined;\n this.#refreshToken = undefined;\n this.#profile = undefined;\n this.#config = undefined;\n this.dispatchEvent({ type: 'change' });\n }\n\n /**\n * Makes an HTTP GET request to the specified URL.\n *\n * This is a lower level method for custom requests.\n * For common operations, we recommend using higher level methods\n * such as `readResource()`, `search()`, etc.\n *\n * @param url The target URL.\n * @param options Optional fetch options.\n * @returns Promise to the response content.\n */\n get(url: string, options: RequestInit = {}): Promise<any> {\n return this.#request('GET', url, options);\n }\n\n /**\n * Makes an HTTP POST request to the specified URL.\n *\n * This is a lower level method for custom requests.\n * For common operations, we recommend using higher level methods\n * such as `createResource()`.\n *\n * @param url The target URL.\n * @param body The content body. Strings and `File` objects are passed directly. Other objects are converted to JSON.\n * @param contentType The content type to be included in the \"Content-Type\" header.\n * @param options Optional fetch options.\n * @returns Promise to the response content.\n */\n post(url: string, body: any, contentType?: string, options: RequestInit = {}): Promise<any> {\n if (body) {\n this.#setRequestBody(options, body);\n }\n if (contentType) {\n this.#setRequestContentType(options, contentType);\n }\n return this.#request('POST', url, options);\n }\n\n /**\n * Makes an HTTP PUT request to the specified URL.\n *\n * This is a lower level method for custom requests.\n * For common operations, we recommend using higher level methods\n * such as `updateResource()`.\n *\n * @param url The target URL.\n * @param body The content body. Strings and `File` objects are passed directly. Other objects are converted to JSON.\n * @param contentType The content type to be included in the \"Content-Type\" header.\n * @param options Optional fetch options.\n * @returns Promise to the response content.\n */\n put(url: string, body: any, contentType?: string, options: RequestInit = {}): Promise<any> {\n if (body) {\n this.#setRequestBody(options, body);\n }\n if (contentType) {\n this.#setRequestContentType(options, contentType);\n }\n return this.#request('PUT', url, options);\n }\n\n /**\n * Makes an HTTP PATCH request to the specified URL.\n *\n * This is a lower level method for custom requests.\n * For common operations, we recommend using higher level methods\n * such as `patchResource()`.\n *\n * @param url The target URL.\n * @param operations Array of JSONPatch operations.\n * @param options Optional fetch options.\n * @returns Promise to the response content.\n */\n patch(url: string, operations: Operation[], options: RequestInit = {}): Promise<any> {\n this.#setRequestBody(options, operations);\n this.#setRequestContentType(options, PATCH_CONTENT_TYPE);\n return this.#request('PATCH', url, options);\n }\n\n /**\n * Makes an HTTP DELETE request to the specified URL.\n *\n * This is a lower level method for custom requests.\n * For common operations, we recommend using higher level methods\n * such as `deleteResource()`.\n *\n * @param url The target URL.\n * @param options Optional fetch options.\n * @returns Promise to the response content.\n */\n delete(url: string, options: RequestInit = {}): Promise<any> {\n return this.#request('DELETE', url, options);\n }\n\n /**\n * Tries to register a new user.\n * @param request The registration request.\n * @returns Promise to the authentication response.\n */\n async register(request: RegisterRequest): Promise<void> {\n const response = await this.post('auth/register', request);\n await this.setActiveLogin(response as LoginState);\n }\n\n /**\n * Initiates a user login flow.\n * @param email The email address of the user.\n * @param password The password of the user.\n * @param remember Optional flag to remember the user.\n * @returns Promise to the authentication response.\n */\n async startLogin(email: string, password: string, remember?: boolean): Promise<LoginAuthenticationResponse> {\n await this.#startPkce();\n return this.post('auth/login', {\n clientId: this.#clientId,\n scope: DEFAULT_SCOPE,\n codeChallengeMethod: 'S256',\n codeChallenge: this.#storage.getString('codeChallenge') as string,\n email,\n password,\n remember: !!remember,\n }) as Promise<LoginAuthenticationResponse>;\n }\n\n /**\n * Tries to sign in with Google authentication.\n * The response parameter is the result of a Google authentication.\n * See: https://developers.google.com/identity/gsi/web/guides/handle-credential-responses-js-functions\n * @param googleResponse The Google credential response.\n * @returns Promise to the authentication response.\n */\n async startGoogleLogin(googleResponse: GoogleCredentialResponse): Promise<LoginAuthenticationResponse> {\n await this.#startPkce();\n return this.post('auth/google', googleResponse) as Promise<LoginAuthenticationResponse>;\n }\n\n /**\n * Signs out locally.\n * Does not invalidate tokens with the server.\n */\n signOut(): Promise<void> {\n this.clear();\n return Promise.resolve();\n }\n\n /**\n * Tries to sign in the user.\n * Returns true if the user is signed in.\n * This may result in navigating away to the sign in page.\n */\n signInWithRedirect(): Promise<ProfileResource | void> | undefined {\n const urlParams = new URLSearchParams(window.location.search);\n const code = urlParams.get('code');\n if (!code) {\n this.#requestAuthorization();\n return undefined;\n } else {\n return this.processCode(code);\n }\n }\n\n /**\n * Tries to sign out the user.\n * See: https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html\n */\n signOutWithRedirect(): void {\n window.location.assign(this.#logoutUrl);\n }\n\n /**\n * Builds a FHIR URL from a collection of URL path components.\n * For example, `buildUrl('/Patient', '123')` returns `fhir/R4/Patient/123`.\n * @param path The path component of the URL.\n * @returns The well-formed FHIR URL.\n */\n fhirUrl(...path: string[]): string {\n const builder = [this.#baseUrl, 'fhir/R4'];\n path.forEach((p) => builder.push('/', encodeURIComponent(p)));\n return builder.join('');\n }\n\n /**\n * Sends a FHIR search request.\n *\n * Example using a FHIR search string:\n *\n * ```typescript\n * const bundle = await client.search('Patient?name=Alice');\n * console.log(bundle);\n * ```\n *\n * Example using a structured search:\n *\n * ```typescript\n * const bundle = await client.search({\n * resourceType: 'Patient',\n * filters: [{\n * code: 'name',\n * operator: 'eq',\n * value: 'Alice',\n * }]\n * });\n * console.log(bundle);\n * ```\n *\n * The return value is a FHIR bundle:\n *\n * ```json\n * {\n * \"resourceType\": \"Bundle\",\n * \"type\": \"searchest\",\n * \"total\": 1,\n * \"entry\": [\n * {\n * \"resource\": {\n * \"resourceType\": \"Patient\",\n * \"name\": [\n * {\n * \"given\": [\n * \"George\"\n * ],\n * \"family\": \"Washington\"\n * }\n * ],\n * }\n * }\n * ]\n * }\n * ```\n *\n * See FHIR search for full details: https://www.hl7.org/fhir/search.html\n *\n * @param query The search query as either a string or a structured search object.\n * @returns Promise to the search result bundle.\n */\n search<T extends Resource>(query: string | SearchRequest, options: RequestInit = {}): Promise<Bundle<T>> {\n return this.get(\n typeof query === 'string' ? 'fhir/R4/' + query : this.fhirUrl(query.resourceType) + formatSearchQuery(query),\n options\n );\n }\n\n /**\n * Sends a FHIR search request for a single resource.\n *\n * This is a convenience method for `search()` that returns the first resource rather than a `Bundle`.\n *\n * Example using a FHIR search string:\n *\n * ```typescript\n * const patient = await client.searchOne('Patient?identifier=123');\n * console.log(patient);\n * ```\n *\n * The return value is the resource, if available; otherwise, undefined.\n *\n * See FHIR search for full details: https://www.hl7.org/fhir/search.html\n *\n * @param query The search query as either a string or a structured search object.\n * @returns Promise to the search result bundle.\n */\n async searchOne<T extends Resource>(\n query: string | SearchRequest,\n options: RequestInit = {}\n ): Promise<T | undefined> {\n const search: SearchRequest = typeof query === 'string' ? parseSearchDefinition(query) : query;\n (search as any).count = 1;\n const bundle = await this.search<T>(search, options);\n return bundle.entry?.[0]?.resource;\n }\n\n /**\n * Sends a FHIR search request for an array of resources.\n *\n * This is a convenience method for `search()` that returns the resources as an array rather than a `Bundle`.\n *\n * Example using a FHIR search string:\n *\n * ```typescript\n * const patients = await client.searchResources('Patient?name=Alice');\n * console.log(patients);\n * ```\n *\n * The return value is an array of resources.\n *\n * See FHIR search for full details: https://www.hl7.org/fhir/search.html\n *\n * @param query The search query as either a string or a structured search object.\n * @returns Promise to the search result bundle.\n */\n async searchResources<T extends Resource>(query: string | SearchRequest, options: RequestInit = {}): Promise<T[]> {\n const bundle = await this.search<T>(query, options);\n return bundle.entry?.map((entry) => entry.resource as T) ?? [];\n }\n\n /**\n * Searches a ValueSet resource using the \"expand\" operation.\n * See: https://www.hl7.org/fhir/operation-valueset-expand.html\n * @param system The ValueSet system url.\n * @param filter The search string.\n * @returns Promise to expanded ValueSet.\n */\n searchValueSet(system: string, filter: string, options: RequestInit = {}): Promise<ValueSet> {\n return this.get(\n this.fhirUrl('ValueSet', '$expand') +\n `?url=${encodeURIComponent(system)}` +\n `&filter=${encodeURIComponent(filter)}`,\n options\n );\n }\n\n /**\n * Returns a cached resource if it is available.\n * @param resourceType The FHIR resource type.\n * @param id The FHIR resource ID.\n * @returns The resource if it is available in the cache; undefined otherwise.\n */\n getCached<T extends Resource>(resourceType: string, id: string): T | undefined {\n const cached = this.#resourceCache.get(resourceType + '/' + id) as T | undefined;\n if (cached && !('then' in cached)) {\n return cached;\n }\n return undefined;\n }\n\n /**\n * Returns a cached resource if it is available.\n * @param resourceType The FHIR resource type.\n * @param id The FHIR resource ID.\n * @returns The resource if it is available in the cache; undefined otherwise.\n */\n getCachedReference<T extends Resource>(reference: Reference<T>): T | undefined {\n const cached = this.#resourceCache.get(reference.reference as string) as T | undefined;\n if (cached && !('then' in cached)) {\n return cached;\n }\n return undefined;\n }\n\n /**\n * Reads a resource by resource type and ID.\n *\n * Example:\n *\n * ```typescript\n * const patient = await medplum.readResource('Patient', '123');\n * console.log(patient);\n * ```\n *\n * See the FHIR \"read\" operation for full details: https://www.hl7.org/fhir/http.html#read\n *\n * @param resourceType The FHIR resource type.\n * @param id The resource ID.\n * @returns The resource if available; undefined otherwise.\n */\n readResource<T extends Resource>(resourceType: string, id: string): Promise<T> {\n const cacheKey = resourceType + '/' + id;\n const promise = this.get(this.fhirUrl(resourceType, id)).then((resource: T) => {\n this.#resourceCache.set(cacheKey, resource);\n return resource;\n });\n this.#resourceCache.set(cacheKey, promise);\n return promise;\n }\n\n /**\n * Reads a resource by resource type and ID using the in-memory resource cache.\n *\n * If the resource is not available in the cache, it will be read from the server.\n *\n * Example:\n *\n * ```typescript\n * const patient = await medplum.readCached('Patient', '123');\n * console.log(patient);\n * ```\n *\n * See the FHIR \"read\" operation for full details: https://www.hl7.org/fhir/http.html#read\n *\n * @param resourceType The FHIR resource type.\n * @param id The resource ID.\n * @returns The resource if available; undefined otherwise.\n */\n readCached<T extends Resource>(resourceType: string, id: string): Promise<T> {\n const cached = this.#resourceCache.get(resourceType + '/' + id) as T | Promise<T> | undefined;\n return cached ? Promise.resolve(cached) : this.readResource(resourceType, id);\n }\n\n /**\n * Reads a resource by `Reference`.\n *\n * This is a convenience method for `readResource()` that accepts a `Reference` object.\n *\n * Example:\n *\n * ```typescript\n * const serviceRequest = await medplum.readResource('ServiceRequest', '123');\n * const patient = await medplum.readReference(serviceRequest.subject);\n * console.log(patient);\n * ```\n *\n * See the FHIR \"read\" operation for full details: https://www.hl7.org/fhir/http.html#read\n *\n * @param reference The FHIR reference object.\n * @returns The resource if available; undefined otherwise.\n */\n readReference<T extends Resource>(reference: Reference<T>): Promise<T> {\n const refString = reference?.reference;\n if (!refString) {\n return Promise.reject('Missing reference');\n }\n const [resourceType, id] = refString.split('/');\n return this.readResource(resourceType, id);\n }\n\n /**\n * Reads a resource by `Reference` using the in-memory resource cache.\n *\n * This is a convenience method for `readResource()` that accepts a `Reference` object.\n *\n * If the resource is not available in the cache, it will be read from the server.\n *\n * Example:\n *\n * ```typescript\n * const serviceRequest = await medplum.readResource('ServiceRequest', '123');\n * const patient = await medplum.readCachedReference(serviceRequest.subject);\n * console.log(patient);\n * ```\n *\n * See the FHIR \"read\" operation for full details: https://www.hl7.org/fhir/http.html#read\n *\n * @param reference The FHIR reference object.\n * @returns The resource if available; undefined otherwise.\n */\n readCachedReference<T extends Resource>(reference: Reference<T>): Promise<T> {\n const refString = reference?.reference;\n if (!refString) {\n return Promise.reject('Missing reference');\n }\n const [resourceType, id] = refString.split('/');\n return this.readCached(resourceType, id);\n }\n\n /**\n * Returns a cached schema for a resource type.\n * If the schema is not cached, returns undefined.\n * It is assumed that a client will call requestSchema before using this method.\n * @param resourceType The FHIR resource type.\n * @returns The schema if immediately available, undefined otherwise.\n */\n getSchema(): IndexedStructureDefinition {\n return this.#schema;\n }\n\n /**\n * Requests the schema for a resource type.\n * If the schema is already cached, the promise is resolved immediately.\n * @param resourceType The FHIR resource type.\n * @returns Promise to a schema with the requested resource type.\n */\n async requestSchema(resourceType: string): Promise<IndexedStructureDefinition> {\n if (resourceType in this.#schema.types) {\n return Promise.resolve(this.#schema);\n }\n\n const query = `{\n StructureDefinitionList(name: \"${encodeURIComponent(resourceType)}\") {\n name,\n description,\n snapshot {\n element {\n id,\n path,\n min,\n max,\n type {\n code,\n targetProfile\n },\n binding {\n valueSet\n },\n definition\n }\n }\n }\n SearchParameterList(base: \"${encodeURIComponent(resourceType)}\") {\n base,\n code,\n type,\n expression,\n target\n }\n }`.replace(/\\s+/g, ' ');\n\n const response = (await this.graphql(query)) as SchemaGraphQLResponse;\n\n for (const structureDefinition of response.data.StructureDefinitionList) {\n indexStructureDefinition(this.#schema, structureDefinition);\n }\n\n for (const searchParameter of response.data.SearchParameterList) {\n indexSearchParameter(this.#schema, searchParameter);\n }\n\n return this.#schema;\n }\n\n /**\n * Reads resource history by resource type and ID.\n *\n * The return value is a bundle of all versions of the resource.\n *\n * Example:\n *\n * ```typescript\n * const history = await medplum.readHistory('Patient', '123');\n * console.log(history);\n * ```\n *\n * See the FHIR \"history\" operation for full details: https://www.hl7.org/fhir/http.html#history\n *\n * @param resourceType The FHIR resource type.\n * @param id The resource ID.\n * @returns The resource if available; undefined otherwise.\n */\n readHistory<T extends Resource>(resourceType: string, id: string): Promise<Bundle<T>> {\n return this.get(this.fhirUrl(resourceType, id, '_history'));\n }\n\n /**\n * Reads a specific version of a resource by resource type, ID, and version ID.\n *\n * Example:\n *\n * ```typescript\n * const version = await medplum.readVersion('Patient', '123', '456');\n * console.log(version);\n * ```\n *\n * See the FHIR \"vread\" operation for full details: https://www.hl7.org/fhir/http.html#vread\n *\n * @param resourceType The FHIR resource type.\n * @param id The resource ID.\n * @returns The resource if available; undefined otherwise.\n */\n readVersion<T extends Resource>(resourceType: string, id: string, vid: string): Promise<T> {\n return this.get(this.fhirUrl(resourceType, id, '_history', vid));\n }\n\n readPatientEverything(id: string): Promise<Bundle> {\n return this.get(this.fhirUrl('Patient', id, '$everything'));\n }\n\n /**\n * Creates a new FHIR resource.\n *\n * The return value is the newly created resource, including the ID and meta.\n *\n * Example:\n *\n * ```typescript\n * const result = await medplum.createResource({\n * resourceType: 'Patient',\n * name: [{\n * family: 'Smith',\n * given: ['John']\n * }]\n * });\n * console.log(result.id);\n * ```\n *\n * See the FHIR \"create\" operation for full details: https://www.hl7.org/fhir/http.html#create\n *\n * @param resource The FHIR resource to create.\n * @returns The result of the create operation.\n */\n createResource<T extends Resource>(resource: T): Promise<T> {\n if (!resource.resourceType) {\n return Promise.reject('Missing resourceType');\n }\n return this.post(this.fhirUrl(resource.resourceType), resource);\n }\n\n /**\n * Creates a FHIR `Binary` resource with the provided data content.\n *\n * The return value is the newly created resource, including the ID and meta.\n *\n * The `data` parameter can be a string or a `File` object.\n *\n * A `File` object often comes from a `<input type=\"file\">` element.\n *\n * Example:\n *\n * ```typescript\n * const result = await medplum.createBinary(myFile, 'test.jpg', 'image/jpeg');\n * console.log(result.id);\n * ```\n *\n * See the FHIR \"create\" operation for full details: https://www.hl7.org/fhir/http.html#create\n *\n * @param resource The FHIR resource to create.\n * @returns The result of the create operation.\n */\n createBinary(data: any, filename: string, contentType: string): Promise<Binary> {\n return this.post(this.fhirUrl('Binary') + '?_filename=' + encodeURIComponent(filename), data, contentType);\n }\n\n /**\n * Updates a FHIR resource.\n *\n * The return value is the updated resource, including the ID and meta.\n *\n * Example:\n *\n * ```typescript\n * const result = await medplum.updateResource({\n * resourceType: 'Patient',\n * id: '123',\n * name: [{\n * family: 'Smith',\n * given: ['John']\n * }]\n * });\n * console.log(result.meta.versionId);\n * ```\n *\n * See the FHIR \"update\" operation for full details: https://www.hl7.org/fhir/http.html#update\n *\n * @param resource The FHIR resource to update.\n * @returns The result of the update operation.\n */\n updateResource<T extends Resource>(resource: T): Promise<T> {\n if (!resource.resourceType) {\n return Promise.reject('Missing resourceType');\n }\n if (!resource.id) {\n return Promise.reject('Missing id');\n }\n return this.put(this.fhirUrl(resource.resourceType, resource.id), resource);\n }\n\n /**\n * Updates a FHIR resource using JSONPatch operations.\n *\n * The return value is the updated resource, including the ID and meta.\n *\n * Example:\n *\n * ```typescript\n * const result = await medplum.patchResource('Patient', '123', [\n * {op: 'replace', path: '/name/0/family', value: 'Smith'},\n * ]);\n * console.log(result.meta.versionId);\n * ```\n *\n * See the FHIR \"update\" operation for full details: https://www.hl7.org/fhir/http.html#patch\n *\n * See the JSONPatch specification for full details: https://tools.ietf.org/html/rfc6902\n *\n * @param resourceType The FHIR resource type.\n * @param id The resource ID.\n * @param operations The JSONPatch operations.\n * @returns The result of the patch operations.\n */\n patchResource<T extends Resource>(resourceType: string, id: string, operations: Operation[]): Promise<T> {\n return this.patch(this.fhirUrl(resourceType, id), operations);\n }\n\n /**\n * Deletes a FHIR resource by resource type and ID.\n *\n * Example:\n *\n * ```typescript\n * await medplum.deleteResource('Patient', '123');\n * ```\n *\n * See the FHIR \"delete\" operation for full details: https://www.hl7.org/fhir/http.html#delete\n *\n * @param resourceType The FHIR resource type.\n * @param id The resource ID.\n * @returns The result of the delete operation.\n */\n deleteResource(resourceType: string, id: string): Promise<any> {\n return this.delete(this.fhirUrl(resourceType, id));\n }\n\n graphql(query: string, options?: RequestInit): Promise<any> {\n return this.post(this.fhirUrl('$graphql'), { query }, JSON_CONTENT_TYPE, options);\n }\n\n getActiveLogin(): LoginState | undefined {\n return this.#storage.getObject('activeLogin');\n }\n\n async setActiveLogin(login: LoginState): Promise<void> {\n this.#accessToken = login.accessToken;\n this.#refreshToken = login.refreshToken;\n this.#profile = undefined;\n this.#config = undefined;\n this.#storage.setObject('activeLogin', login);\n this.#addLogin(login);\n this.#resourceCache.clear();\n this.#refreshPromise = undefined;\n await this.#refreshProfile();\n }\n\n setAccessToken(accessToken: string): void {\n this.#accessToken = accessToken;\n this.#refreshToken = undefined;\n this.#profile = undefined;\n this.#config = undefined;\n }\n\n getLogins(): LoginState[] {\n return this.#storage.getObject<LoginState[]>('logins') ?? [];\n }\n\n #addLogin(newLogin: LoginState): void {\n const logins = this.getLogins().filter((login) => login.profile?.reference !== newLogin.profile?.reference);\n logins.push(newLogin);\n this.#storage.setObject('logins', logins);\n }\n\n async #refreshProfile(): Promise<ProfileResource | undefined> {\n this.#profilePromise = new Promise((resolve, reject) => {\n this.get('auth/me')\n .then((result) => {\n this.#profilePromise = undefined;\n this.#profile = result.profile;\n this.#config = result.config;\n this.dispatchEvent({ type: 'change' });\n resolve(this.#profile);\n })\n .catch(reject);\n });\n\n return this.#profilePromise;\n }\n\n isLoading(): boolean {\n return !!this.#profilePromise;\n }\n\n getProfile(): ProfileResource | undefined {\n return this.#profile;\n }\n\n async getProfileAsync(): Promise<ProfileResource | undefined> {\n if (this.#profilePromise) {\n await this.#profilePromise;\n }\n return this.getProfile();\n }\n\n getUserConfiguration(): UserConfiguration | undefined {\n return this.#config;\n }\n\n /**\n * Downloads the URL as a blob.\n * @param url The URL to request.\n * @returns Promise to the response body as a blob.\n */\n async download(url: string, options: RequestInit = {}): Promise<Blob> {\n if (this.#refreshPromise) {\n await this.#refreshPromise;\n }\n this.#addFetchOptionsDefaults(options);\n const response = await this.#fetch(url, options);\n return response.blob();\n }\n\n /**\n * Makes an HTTP request.\n * @param {string} method\n * @param {string} url\n * @param {string=} contentType\n * @param {Object=} body\n */\n async #request(method: string, url: string, options: RequestInit = {}): Promise<any> {\n if (this.#refreshPromise) {\n await this.#refreshPromise;\n }\n\n if (!url.startsWith('http')) {\n url = this.#baseUrl + url;\n }\n\n options.method = method;\n this.#addFetchOptionsDefaults(options);\n\n const response = await this.#fetch(url, options);\n if (response.status === 401) {\n // Refresh and try again\n return this.#handleUnauthenticated(method, url, options);\n }\n\n if (response.status === 204 || response.status === 304) {\n // No content or change\n return undefined;\n }\n\n const obj = await response.json();\n if (obj?.resourceType === 'OperationOutcome' && !isOk(obj)) {\n return Promise.reject(obj);\n }\n return obj;\n }\n\n /**\n * Adds default options to the fetch options.\n * @param options The options to add defaults to.\n */\n #addFetchOptionsDefaults(options: RequestInit): void {\n if (!options.headers) {\n options.headers = {};\n }\n\n const headers = options.headers as Record<string, string>;\n if (!headers['Content-Type']) {\n headers['Content-Type'] = FHIR_CONTENT_TYPE;\n }\n\n if (this.#accessToken) {\n headers['Authorization'] = 'Bearer ' + this.#accessToken;\n }\n\n if (!options.cache) {\n options.cache = 'no-cache';\n }\n\n if (!options.credentials) {\n options.credentials = 'include';\n }\n }\n\n /**\n * Sets the \"Content-Type\" header on fetch options.\n * @param options The fetch options.\n * @param contentType The new content type to set.\n */\n #setRequestContentType(options: RequestInit, contentType: string): void {\n if (!options.headers) {\n options.headers = {};\n }\n const headers = options.headers as Record<string, string>;\n headers['Content-Type'] = contentType;\n }\n\n /**\n * Sets the body on fetch options.\n * @param options The fetch options.\n * @param data The new content body.\n */\n #setRequestBody(options: RequestInit, data: any): void {\n if (typeof data === 'string' || (typeof File !== 'undefined' && data instanceof File)) {\n options.body = data;\n } else if (data) {\n options.body = stringify(data);\n }\n }\n\n /**\n * Handles an unauthenticated response from the server.\n * First, tries to refresh the access token and retry the request.\n * Otherwise, calls unauthenticated callbacks and rejects.\n * @param method The HTTP method of the original request.\n * @param url The URL of the original request.\n * @param contentType The content type of the original request.\n * @param body The body of the original request.\n */\n async #handleUnauthenticated(method: string, url: string, options: RequestInit): Promise<any> {\n return this.#refresh()\n .then(() => this.#request(method, url, options))\n .catch((error) => {\n this.clear();\n if (this.#onUnauthenticated) {\n this.#onUnauthenticated();\n }\n return Promise.reject(error);\n });\n }\n\n /**\n * Starts a new PKCE flow.\n * These PKCE values are stateful, and must survive redirects and page refreshes.\n */\n async #startPkce(): Promise<void> {\n const pkceState = getRandomString();\n this.#storage.setString('pkceState', pkceState);\n\n const codeVerifier = getRandomString();\n this.#storage.setString('codeVerifier', codeVerifier);\n\n const arrayHash = await encryptSHA256(codeVerifier);\n const codeChallenge = arrayBufferToBase64(arrayHash).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n this.#storage.setString('codeChallenge', codeChallenge);\n }\n\n /**\n * Redirects the user to the login screen for authorization.\n * Clears all auth state including local storage and session storage.\n * See: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint\n */\n async #requestAuthorization(): Promise<void> {\n if (!this.#authorizeUrl) {\n return Promise.reject('Missing authorize URL');\n }\n\n this.#startPkce();\n\n window.location.assign(\n this.#authorizeUrl +\n '?response_type=code' +\n '&state=' +\n encodeURIComponent(this.#storage.getString('pkceState') as string) +\n '&client_id=' +\n encodeURIComponent(this.#clientId) +\n '&redirect_uri=' +\n encodeURIComponent(getBaseUrl()) +\n '&scope=' +\n encodeURIComponent(DEFAULT_SCOPE) +\n '&code_challenge_method=S256' +\n '&code_challenge=' +\n encodeURIComponent(this.#storage.getString('codeChallenge') as string)\n );\n }\n\n /**\n * Processes an OAuth authorization code.\n * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest\n * @param code The authorization code received by URL parameter.\n */\n processCode(code: string): Promise<ProfileResource> {\n const pkceState = this.#storage.getString('pkceState');\n if (!pkceState) {\n this.clear();\n return Promise.reject('Invalid PCKE state');\n }\n\n const codeVerifier = this.#storage.getString('codeVerifier');\n if (!codeVerifier) {\n this.clear();\n return Promise.reject('Invalid PCKE code verifier');\n }\n\n return this.#fetchTokens(\n 'grant_type=authorization_code' +\n (this.#clientId ? '&client_id=' + encodeURIComponent(this.#clientId) : '') +\n '&code_verifier=' +\n encodeURIComponent(codeVerifier) +\n '&redirect_uri=' +\n encodeURIComponent(getBaseUrl()) +\n '&code=' +\n encodeURIComponent(code)\n );\n }\n\n /**\n * Tries to refresh the auth tokens.\n * See: https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens\n */\n async #refresh(): Promise<void> {\n if (this.#refreshPromise) {\n return this.#refreshPromise;\n }\n\n if (!this.#refreshToken) {\n this.clear();\n return Promise.reject('Invalid refresh token');\n }\n\n this.#refreshPromise = this.#fetchTokens(\n 'grant_type=refresh_token' +\n '&client_id=' +\n encodeURIComponent(this.#clientId) +\n '&refresh_token=' +\n encodeURIComponent(this.#refreshToken)\n );\n\n await this.#refreshPromise;\n }\n\n async clientCredentials(clientId: string, clientSecret: string): Promise<ProfileResource> {\n return this.#fetchTokens(\n 'grant_type=client_credentials' +\n '&client_id=' +\n encodeURIComponent(clientId) +\n '&client_secret=' +\n encodeURIComponent(clientSecret)\n );\n }\n\n /**\n * Makes a POST request to the tokens endpoint.\n * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint\n * @param formBody Token parameters in URL encoded format.\n */\n async #fetchTokens(formBody: string): Promise<ProfileResource> {\n if (!this.#tokenUrl) {\n return Promise.reject('Missing token URL');\n }\n\n return this.#fetch(this.#tokenUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: formBody,\n })\n .then((response) => {\n if (!response.ok) {\n return Promise.reject('Failed to fetch tokens');\n }\n return response.json();\n })\n .then((tokens) => this.#verifyTokens(tokens))\n .then(() => this.getProfile() as ProfileResource);\n }\n\n /**\n * Verifies the tokens received from the auth server.\n * Validates the JWT against the JWKS.\n * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint\n * @param tokens\n */\n async #verifyTokens(tokens: TokenResponse): Promise<void> {\n const token = tokens.access_token;\n\n // Verify token has not expired\n const tokenPayload = parseJWTPayload(token);\n if (Date.now() >= (tokenPayload.exp as number) * 1000) {\n this.clear();\n return Promise.reject('Token expired');\n }\n\n // Verify app_client_id\n if (this.#clientId && tokenPayload.client_id !== this.#clientId) {\n this.clear();\n return Promise.reject('Token was not issued for this audience');\n }\n\n await this.setActiveLogin({\n accessToken: token,\n refreshToken: tokens.refresh_token,\n project: tokens.project,\n profile: tokens.profile,\n });\n }\n\n /**\n * Sets up a listener for window storage events.\n * This synchronizes state across browser windows and browser tabs.\n */\n #setupStorageListener(): void {\n try {\n window.addEventListener('storage', (e: StorageEvent) => {\n if (e.key === null || e.key === 'activeLogin') {\n // Storage events fire when different tabs make changes.\n // On storage clear (key === null) or activeLogin change (key === 'activeLogin')\n // Refresh the page to ensure the active login is up to date.\n window.location.reload();\n }\n });\n } catch (err) {\n // Silently ignore if this environment does not support storage events\n }\n }\n}\n\n/**\n * Returns the base URL for the current page.\n */\nfunction getBaseUrl(): string {\n return window.location.protocol + '//' + window.location.host + '/';\n}\n","/*\n * Based on: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\n */\n\ninterface Event {\n readonly type: string;\n readonly defaultPrevented?: boolean;\n}\n\ntype EventListener = (e: Event) => void;\n\nexport class EventTarget {\n readonly #listeners: Record<string, EventListener[]>;\n\n constructor() {\n this.#listeners = {};\n }\n\n addEventListener(type: string, callback: EventListener): void {\n if (!this.#listeners[type]) {\n this.#listeners[type] = [];\n }\n this.#listeners[type].push(callback);\n }\n\n removeEventListeneer(type: string, callback: EventListener): void {\n const array = this.#listeners[type];\n if (!array) {\n return;\n }\n for (let i = 0; i < array.length; i++) {\n if (array[i] === callback) {\n array.splice(i, 1);\n return;\n }\n }\n }\n\n dispatchEvent(event: Event): boolean {\n const array = this.#listeners[event.type];\n if (array) {\n array.forEach((listener) => listener.call(this, event));\n }\n return !event.defaultPrevented;\n }\n}\n","import { isStringArray } from './utils';\n\nexport const SEGMENT_SEPARATOR = '\\r';\nexport const FIELD_SEPARATOR = '|';\nexport const COMPONENT_SEPARATOR = '^';\n\n/**\n * The Hl7Message class represents one HL7 message.\n * A message is a collection of segments.\n * Note that we do not strictly parse messages, and only use default delimeters.\n */\nexport class Hl7Message {\n readonly segments: Hl7Segment[];\n\n constructor(segments: Hl7Segment[]) {\n this.segments = segments;\n }\n\n get(index: number | string): Hl7Segment | undefined {\n if (typeof index === 'number') {\n return this.segments[index];\n }\n return this.segments.find((s) => s.name === index);\n }\n\n getAll(name: string): Hl7Segment[] {\n return this.segments.filter((s) => s.name === name);\n }\n\n toString(): string {\n return this.segments.map((s) => s.toString()).join(SEGMENT_SEPARATOR);\n }\n\n buildAck(): Hl7Message {\n const now = new Date();\n const msh = this.get('MSH');\n const sendingApp = msh?.get(2)?.toString() || '';\n const sendingFacility = msh?.get(3)?.toString() || '';\n const receivingApp = msh?.get(4)?.toString() || '';\n const receivingFacility = msh?.get(5)?.toString() || '';\n const controlId = msh?.get(9)?.toString() || '';\n const versionId = msh?.get(12)?.toString() || '2.5.1';\n\n return new Hl7Message([\n new Hl7Segment([\n 'MSH',\n '^~\\\\&',\n receivingApp,\n receivingFacility,\n sendingApp,\n sendingFacility,\n now.toISOString(),\n '',\n 'ACK',\n now.getTime().toString(),\n 'P',\n versionId,\n ]),\n new Hl7Segment(['MSA', 'AA', controlId, 'OK']),\n ]);\n }\n\n static parse(text: string): Hl7Message {\n if (!text.startsWith('MSH|^~\\\\&')) {\n const err = new Error('Invalid HL7 message');\n (err as any).type = 'entity.parse.failed';\n throw err;\n }\n return new Hl7Message(text.split(/[\\r\\n]+/).map((line) => Hl7Segment.parse(line)));\n }\n}\n\n/**\n * The Hl7Segment class represents one HL7 segment.\n * A segment is a collection of fields.\n * The name field is the first field.\n * Note that we do not strictly parse messages, and only use default delimeters.\n */\nexport class Hl7Segment {\n readonly name: string;\n readonly fields: Hl7Field[];\n\n constructor(fields: Hl7Field[] | string[]) {\n if (isStringArray(fields)) {\n this.fields = fields.map((f) => Hl7Field.parse(f));\n } else {\n this.fields = fields;\n }\n this.name = this.fields[0].components[0];\n }\n\n get(index: number): Hl7Field {\n return this.fields[index];\n }\n\n toString(): string {\n return this.fields.map((f) => f.toString()).join(FIELD_SEPARATOR);\n }\n\n static parse(text: string): Hl7Segment {\n return new Hl7Segment(text.split(FIELD_SEPARATOR).map((f) => Hl7Field.parse(f)));\n }\n}\n\n/**\n * The Hl7Field class represents one HL7 field.\n * A field is a collection of components.\n * Note that we do not strictly parse messages, and only use default delimeters.\n */\nexport class Hl7Field {\n readonly components: string[];\n\n constructor(components: string[]) {\n this.components = components;\n }\n\n get(index: number): string {\n return this.components[index];\n }\n\n toString(): string {\n return this.components.join(COMPONENT_SEPARATOR);\n }\n\n static parse(text: string): Hl7Field {\n return new Hl7Field(text.split(COMPONENT_SEPARATOR));\n }\n}\n","import { ElementDefinition, SearchParameter } from '@medplum/fhirtypes';\nimport { IndexedStructureDefinition } from './types';\nimport { capitalize } from './utils';\n\nexport enum SearchParameterType {\n BOOLEAN = 'BOOLEAN',\n NUMBER = 'NUMBER',\n QUANTITY = 'QUANTITY',\n TEXT = 'TEXT',\n REFERENCE = 'REFERENCE',\n DATE = 'DATE',\n DATETIME = 'DATETIME',\n PERIOD = 'PERIOD',\n}\n\nexport interface SearchParameterDetails {\n readonly columnName: string;\n readonly type: SearchParameterType;\n readonly elementDefinition?: ElementDefinition;\n readonly array?: boolean;\n}\n\n/**\n * Returns the type details of a SearchParameter.\n *\n * The SearchParameter resource has a \"type\" parameter, but that is missing some critical information.\n *\n * For example:\n * 1) The \"date\" type includes \"date\", \"datetime\", and \"period\".\n * 2) The \"token\" type includes enums and booleans.\n * 3) Arrays/multiple values are not reflected at all.\n *\n * @param structureDefinitions Collection of StructureDefinition resources indexed by name.\n * @param resourceType The root resource type.\n * @param searchParam The search parameter.\n * @returns The search parameter type details.\n */\nexport function getSearchParameterDetails(\n structureDefinitions: IndexedStructureDefinition,\n resourceType: string,\n searchParam: SearchParameter\n): SearchParameterDetails {\n if (searchParam.code === '_lastUpdated') {\n return { columnName: 'lastUpdated', type: SearchParameterType.DATETIME };\n }\n\n const columnName = convertCodeToColumnName(searchParam.code as string);\n const expression = getExpressionForResourceType(resourceType, searchParam.expression as string)?.split('.');\n if (!expression) {\n // This happens on compound types\n // In the future, explore returning multiple column definitions\n return { columnName, type: SearchParameterType.TEXT };\n }\n\n let baseType = resourceType;\n let elementDefinition = undefined;\n let propertyType = undefined;\n let array = false;\n\n for (let i = 1; i < expression.length; i++) {\n const propertyName = expression[i];\n elementDefinition = structureDefinitions.types[baseType]?.properties?.[propertyName];\n if (!elementDefinition) {\n // This happens on complex properties such as \"collected[x]\"/\"collectedDateTime\"/\"collectedPeriod\"\n // In the future, explore returning multiple column definitions\n return { columnName, type: SearchParameterType.TEXT, array };\n }\n\n if (elementDefinition.max === '*') {\n array = true;\n }\n\n propertyType = elementDefinition.type?.[0].code;\n if (!propertyType) {\n // This happens when one of parent properties uses contentReference\n // In the future, explore following the reference\n return { columnName, type: SearchParameterType.TEXT, array };\n }\n\n if (i < expression.length - 1) {\n if (propertyType === 'Element' || propertyType === 'BackboneElement') {\n baseType = baseType + capitalize(propertyName);\n } else {\n baseType = propertyType;\n }\n }\n }\n\n const type = getSearchParameterType(searchParam, propertyType as string);\n return { columnName, type, elementDefinition, array };\n}\n\n/**\n * Converts a hyphen-delimited code to camelCase string.\n * @param code The search parameter code.\n * @returns The SQL column name.\n */\nfunction convertCodeToColumnName(code: string): string {\n return code.split('-').reduce((result, word, index) => result + (index ? capitalize(word) : word), '');\n}\n\nfunction getSearchParameterType(searchParam: SearchParameter, propertyType: string): SearchParameterType {\n let type = SearchParameterType.TEXT;\n switch (searchParam.type) {\n case 'date':\n type = SearchParameterType.DATE;\n break;\n case 'number':\n type = SearchParameterType.NUMBER;\n break;\n case 'quantity':\n type = SearchParameterType.QUANTITY;\n break;\n case 'reference':\n type = SearchParameterType.REFERENCE;\n break;\n case 'token':\n if (propertyType === 'boolean') {\n type = SearchParameterType.BOOLEAN;\n }\n break;\n }\n return type;\n}\n\nexport function getExpressionForResourceType(resourceType: string, expression: string): string | undefined {\n const expressions = expression.split(' | ');\n for (const e of expressions) {\n const simplified = simplifyExpression(e);\n if (simplified.startsWith(resourceType + '.')) {\n return simplified;\n }\n }\n return undefined;\n}\n\nfunction simplifyExpression(input: string): string {\n let result = input.trim();\n\n if (result.startsWith('(') && result.endsWith(')')) {\n result = result.substring(1, result.length - 1);\n }\n\n if (result.includes(' as ')) {\n result = result.substring(0, result.indexOf(' as '));\n }\n\n if (result.includes('.where(')) {\n result = result.substring(0, result.indexOf('.where('));\n }\n\n return result;\n}\n","import { Bundle, OperationOutcome, Reference, Resource } from '@medplum/fhirtypes';\nimport { Operation } from 'fast-json-patch';\nimport { MedplumClient } from './client';\nimport { allOk, created } from './outcomes';\nimport { parseSearchDefinition, SearchRequest } from './search';\n\n/**\n * The LegacyRepositoryResult type is a tuple of operation outcome and optional resource.\n * @deprecated\n */\nexport type LegacyRepositoryResult<T extends Resource | undefined> = Promise<[OperationOutcome, T | undefined]>;\n\n/**\n * The LegacyRepositoryClient is a supplementary API client that matches the legacy \"Repository\" API.\n * The \"Repository\" API is deprecated and will be removed in a future release.\n * This LegacyRepositoryClient is also deprecated and will be removed in a future release.\n * @deprecated\n */\nexport class LegacyRepositoryClient {\n readonly #client: MedplumClient;\n\n constructor(client: MedplumClient) {\n this.#client = client;\n }\n\n /**\n * Creates a resource.\n *\n * See: https://www.hl7.org/fhir/http.html#create\n *\n * @param resource The resource to create.\n * @returns Operation outcome and the new resource.\n * @deprecated\n */\n async createResource<T extends Resource>(resource: T): LegacyRepositoryResult<T> {\n try {\n const result = await this.#client.createResource<T>(resource);\n return [created, result];\n } catch (error) {\n return [error as OperationOutcome, undefined];\n }\n }\n\n /**\n * Returns a resource.\n *\n * See: https://www.hl7.org/fhir/http.html#read\n *\n * @param resourceType The FHIR resource type.\n * @param id The FHIR resource ID.\n * @returns Operation outcome and a resource.\n * @deprecated\n */\n async readResource<T extends Resource>(resourceType: string, id: string): LegacyRepositoryResult<T> {\n try {\n const resource = await this.#client.readResource<T>(resourceType, id);\n return [allOk, resource];\n } catch (error) {\n return [error as OperationOutcome, undefined];\n }\n }\n\n /**\n * Returns a resource by FHIR reference.\n *\n * See: https://www.hl7.org/fhir/http.html#read\n *\n * @param reference The FHIR reference.\n * @returns Operation outcome and a resource.\n * @deprecated\n */\n async readReference<T extends Resource>(reference: Reference<T>): LegacyRepositoryResult<T> {\n try {\n const resource = await this.#client.readReference<T>(reference);\n return [allOk, resource];\n } catch (error) {\n return [error as OperationOutcome, undefined];\n }\n }\n\n /**\n * Returns resource history.\n *\n * See: https://www.hl7.org/fhir/http.html#history\n *\n * @param resourceType The FHIR resource type.\n * @param id The FHIR resource ID.\n * @returns Operation outcome and a history bundle.\n * @deprecated\n */\n async readHistory<T extends Resource>(resourceType: string, id: string): LegacyRepositoryResult<Bundle<T>> {\n try {\n const resource = await this.#client.readHistory<T>(resourceType, id);\n return [allOk, resource];\n } catch (error) {\n return [error as OperationOutcome, undefined];\n }\n }\n\n /**\n * Returns a resource version.\n *\n * See: https://www.hl7.org/fhir/http.html#vread\n *\n * @param resourceType The FHIR resource type.\n * @param id The FHIR resource ID.\n * @param vid The version ID.\n * @returns Operation outcome and a resource.\n * @deprecated\n */\n async readVersion<T extends Resource>(resourceType: string, id: string, vid: string): LegacyRepositoryResult<T> {\n try {\n const resource = await this.#client.readVersion<T>(resourceType, id, vid);\n return [allOk, resource];\n } catch (error) {\n return [error as OperationOutcome, undefined];\n }\n }\n\n /**\n * Updates a resource.\n *\n * See: https://www.hl7.org/fhir/http.html#update\n *\n * @param resource The resource to update.\n * @returns Operation outcome and the updated resource.\n * @deprecated\n */\n async updateResource<T extends Resource>(resource: T): LegacyRepositoryResult<T> {\n try {\n const updated = await this.#client.updateResource<T>(resource);\n return [allOk, updated];\n } catch (error) {\n return [error as OperationOutcome, undefined];\n }\n }\n\n /**\n * Deletes a resource.\n *\n * See: https://www.hl7.org/fhir/http.html#delete\n *\n * @param resourceType The FHIR resource type.\n * @param id The resource ID.\n * @returns Operation outcome.\n * @deprecated\n */\n async deleteResource(resourceType: string, id: string): LegacyRepositoryResult<undefined> {\n try {\n await this.#client.deleteResource(resourceType, id);\n return [allOk, undefined];\n } catch (error) {\n return [error as OperationOutcome, undefined];\n }\n }\n\n /**\n * Patches a resource.\n *\n * See: https://www.hl7.org/fhir/http.html#patch\n *\n * @param resourceType The FHIR resource type.\n * @param id The resource ID.\n * @param patch Array of JSONPatch operations.\n * @returns Operation outcome and the resource.\n * @deprecated\n */\n async patchResource(resourceType: string, id: string, patch: Operation[]): LegacyRepositoryResult<Resource> {\n try {\n const resource = await this.#client.patchResource(resourceType, id, patch);\n return [allOk, resource];\n } catch (error) {\n return [error as OperationOutcome, undefined];\n }\n }\n\n /**\n * Searches for resources.\n *\n * See: https://www.hl7.org/fhir/http.html#search\n *\n * @param searchRequest The search request.\n * @returns The search result bundle.\n * @deprecated\n */\n async search<T extends Resource>(query: SearchRequest | string): LegacyRepositoryResult<Bundle<T>> {\n const searchRequest = typeof query === 'string' ? parseSearchDefinition(query) : query;\n try {\n const bundle = await this.#client.search<T>(searchRequest);\n return [allOk, bundle];\n } catch (error) {\n return [error as OperationOutcome, undefined];\n }\n }\n}\n"],"names":["__awaiter","thisArg","_arguments","P","generator","Promise","resolve","reject","fulfilled","value","step","next","e","rejected","result","done","then","apply","__classPrivateFieldGet","receiver","state","kind","f","TypeError","has","call","get","__classPrivateFieldSet","set","LRUCache","constructor","max","_LRUCache_max","this","_LRUCache_cache","Map","clear","key","item","delete","val","size","_LRUCache_instances","_LRUCache_first","formatAddress","address","options","builder","line","push","city","postalCode","use","all","join","trim","formatHumanName","name","prefix","given","family","suffix","formatGivenName","formatFamilyName","createReference","resource","reference","getReferenceString","display","getDisplayString","resourceType","id","resolveId","_a","split","isProfileResource","profileName","names","length","getProfileResourceDisplayString","deviceName","device","getDeviceDisplayString","code","text","_b","email","getImageSrc","photos","photo","url","getPhotoImageSrc","contentType","startsWith","getDateProperty","date","Date","undefined","calculateAge","birthDateStr","endDateStr","startDate","setUTCHours","endDate","startYear","getUTCFullYear","startMonth","getUTCMonth","startDay","getUTCDate","endYear","endMonth","endDay","years","months","days","Math","floor","getTime","calculateAgeString","toString","padStart","getQuestionnaireAnswers","response","buildQuestionnaireAnswerItems","items","linkId","answer","getExtensionValue","urls","curr","i","extension","find","valueString","stringify","pretty","JSON","stringifyReplacer","k","v","match","isArrayKey","isEmpty","t","Object","keys","deepEquals","object1","object2","path","Array","isArray","array1","array2","deepEqualsArray","isObject","keySet","Set","forEach","add","deepEqualsObject","obj","isStringArray","arr","every","byteToHex","n","arrayBufferToHex","arrayBuffer","bytes","Uint8Array","arrayBufferToBase64","String","fromCharCode","window","btoa","capitalize","word","charAt","toUpperCase","substr","isLowerCase","c","toLowerCase","getRandomString","randomItems","Uint32Array","crypto","getRandomValues","buffer","decodePayload","payload","decodedPayload","data","atob","Buffer","from","Error","decodeBase64","replace","uriEncodedPayload","reduce","acc","char","charCodeAt","slice","jsonPayload","decodeURIComponent","parse","allOk","issue","severity","details","created","notModified","notFound","gone","accessDenied","badRequest","expression","isOk","outcome","isNotFound","isGone","getStatus","assertOk","OperationOutcomeError","super","DEFAULT_SEARCH_COUNT","Operator","MODIFIER_OPERATORS","CONTAINS","EXACT","TEXT","ABOVE","BELOW","IN","NOT_IN","OF_TYPE","PREFIX_OPERATORS","NOT_EQUALS","GREATER_THAN","LESS_THAN","GREATER_THAN_OR_EQUALS","LESS_THAN_OR_EQUALS","STARTS_AFTER","ENDS_BEFORE","APPROXIMATELY","parseSearchDefinition","location","URL","pathname","pop","filters","sortRules","fields","offset","count","total","URLSearchParams","search","parseInt","substring","descending","parseSortRule","operator","EQUALS","modifier","modifierIndex","indexOf","RegExp","parseSearchFilter","formatSearchQuery","definition","params","filter","includes","encodeURIComponent","formatFilter","map","sr","formatSortRules","sort","PropertyType","ClientStorage","_ClientStorage_storage","localStorage","MemoryStorage","getString","getItem","setString","setItem","removeItem","getObject","str","setObject","_MemoryStorage_data","index","createSchema","types","createTypeSchema","typeName","description","properties","searchParams","_lastUpdated","base","type","indexStructureDefinition","schema","structureDefinition","elements","snapshot","element","filtered","typeCode","parts","buildTypeName","parentType","indexType","typeSchema","indexProperty","indexSearchParameter","searchParam","components","getPropertyDisplayName","property","propertyName","replaceAll","DEFAULT_SCOPE","MedplumClient","_EventTarget_listeners","addEventListener","callback","removeEventListeneer","array","splice","dispatchEvent","event","listener","defaultPrevented","_MedplumClient_fetch","_MedplumClient_storage","_MedplumClient_schema","_MedplumClient_resourceCache","_MedplumClient_baseUrl","_MedplumClient_clientId","_MedplumClient_authorizeUrl","_MedplumClient_tokenUrl","_MedplumClient_logoutUrl","_MedplumClient_onUnauthenticated","_MedplumClient_accessToken","_MedplumClient_refreshToken","_MedplumClient_refreshPromise","_MedplumClient_profilePromise","_MedplumClient_profile","_MedplumClient_config","baseUrl","endsWith","fetch","bind","resourceCacheSize","clientId","authorizeUrl","tokenUrl","logoutUrl","onUnauthenticated","activeLogin","getActiveLogin","accessToken","refreshToken","_MedplumClient_instances","_MedplumClient_refreshProfile","catch","console","log","_MedplumClient_setupStorageListener","_MedplumClient_request","post","body","put","patch","operations","register","request","setActiveLogin","startLogin","password","remember","_MedplumClient_startPkce","scope","codeChallengeMethod","codeChallenge","startGoogleLogin","googleResponse","signOut","signInWithRedirect","processCode","_MedplumClient_requestAuthorization","signOutWithRedirect","assign","fhirUrl","p","query","searchOne","bundle","entry","searchResources","searchValueSet","system","getCached","cached","getCachedReference","readResource","cacheKey","promise","readCached","readReference","refString","readCachedReference","getSchema","requestSchema","graphql","StructureDefinitionList","searchParameter","SearchParameterList","readHistory","readVersion","vid","readPatientEverything","createResource","createBinary","filename","updateResource","patchResource","deleteResource","login","_MedplumClient_addLogin","setAccessToken","getLogins","isLoading","getProfile","getProfileAsync","getUserConfiguration","download","_MedplumClient_addFetchOptionsDefaults","blob","codeVerifier","_MedplumClient_fetchTokens","getBaseUrl","clientCredentials","clientSecret","protocol","host","newLogin","logins","profile","config","method","status","_MedplumClient_handleUnauthenticated","json","headers","cache","credentials","_MedplumClient_setRequestContentType","_MedplumClient_setRequestBody","File","_MedplumClient_refresh","error","pkceState","subtle","digest","TextEncoder","encode","encryptSHA256","formBody","ok","tokens","_MedplumClient_verifyTokens","token","access_token","tokenPayload","_header","_signature","parseJWTPayload","now","exp","client_id","refresh_token","project","reload","err","SEGMENT_SEPARATOR","FIELD_SEPARATOR","COMPONENT_SEPARATOR","Hl7Message","segments","s","getAll","buildAck","msh","sendingApp","sendingFacility","receivingApp","_c","receivingFacility","_d","controlId","_e","versionId","_f","Hl7Segment","toISOString","static","Hl7Field","SearchParameterType","LegacyRepositoryClient","client","_LegacyRepositoryClient_client","updated","searchRequest","getSearchParameterDetails","structureDefinitions","columnName","DATETIME","getExpressionForResourceType","elementDefinition","propertyType","baseType","DATE","NUMBER","QUANTITY","REFERENCE","BOOLEAN","getSearchParameterType","expressions","simplified","simplifyExpression","input"],"mappings":"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"}
|