@medplum/core 2.0.22 → 2.0.23

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.
@@ -14,7 +14,7 @@ export { FhirFilterComparison, FhirFilterConnective, FhirFilterNegation } from '
14
14
  export { formatAddress, formatCodeableConcept, formatCoding, formatDate, formatDateTime, formatFamilyName, formatGivenName, formatHumanName, formatMoney, formatObservationValue, formatPeriod, formatQuantity, formatRange, formatTime, formatTiming, isValidDate } from './format.mjs';
15
15
  export { Hl7Context, Hl7Field, Hl7Message, Hl7Segment, parseHl7Date } from './hl7.mjs';
16
16
  export { parseJWTPayload } from './jwt.mjs';
17
- export { OperationOutcomeError, accepted, allOk, assertOk, badRequest, created, forbidden, getStatus, gone, isGone, isNotFound, isOk, isOperationOutcome, normalizeErrorString, normalizeOperationOutcome, notFound, notModified, operationOutcomeToString, tooManyRequests, unauthorized, validationError } from './outcomes.mjs';
17
+ export { OperationOutcomeError, accepted, allOk, assertOk, badRequest, created, forbidden, getStatus, gone, isGone, isNotFound, isOk, isOperationOutcome, normalizeErrorString, normalizeOperationOutcome, notFound, notModified, operationOutcomeIssueToString, operationOutcomeToString, tooManyRequests, unauthorized, validationError } from './outcomes.mjs';
18
18
  export { ReadablePromise } from './readablepromise.mjs';
19
19
  export { FhirSchemaValidator, checkForNull, createStructureIssue, isResourceType, validateResource, validateResourceType } from './schema.mjs';
20
20
  export { SearchParameterType, getExpressionForResourceType, getSearchParameterDetails } from './search/details.mjs';
@@ -251,18 +251,21 @@ function normalizeErrorString(error) {
251
251
  * @returns The string representation of the operation outcome.
252
252
  */
253
253
  function operationOutcomeToString(outcome) {
254
- const strs = [];
255
- if (outcome.issue) {
256
- for (const issue of outcome.issue) {
257
- let issueStr = issue.details?.text || 'Unknown error';
258
- if (issue.expression?.length) {
259
- issueStr += ` (${issue.expression.join(', ')})`;
260
- }
261
- strs.push(issueStr);
262
- }
263
- }
254
+ const strs = outcome.issue?.map(operationOutcomeIssueToString) ?? [];
264
255
  return strs.length > 0 ? strs.join('; ') : 'Unknown error';
265
256
  }
257
+ /**
258
+ * Returns a string represenation of the operation outcome issue.
259
+ * @param issue The operation outcome issue.
260
+ * @returns The string representation of the operation outcome issue.
261
+ */
262
+ function operationOutcomeIssueToString(issue) {
263
+ let issueStr = issue.details?.text ?? issue.diagnostics ?? 'Unknown error';
264
+ if (issue.expression?.length) {
265
+ issueStr += ` (${issue.expression.join(', ')})`;
266
+ }
267
+ return issueStr;
268
+ }
266
269
 
267
- export { OperationOutcomeError, accepted, allOk, assertOk, badRequest, created, forbidden, getStatus, gone, isGone, isNotFound, isOk, isOperationOutcome, normalizeErrorString, normalizeOperationOutcome, notFound, notModified, operationOutcomeToString, tooManyRequests, unauthorized, validationError };
270
+ export { OperationOutcomeError, accepted, allOk, assertOk, badRequest, created, forbidden, getStatus, gone, isGone, isNotFound, isOk, isOperationOutcome, normalizeErrorString, normalizeOperationOutcome, notFound, notModified, operationOutcomeIssueToString, operationOutcomeToString, tooManyRequests, unauthorized, validationError };
268
271
  //# sourceMappingURL=outcomes.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"outcomes.mjs","sources":["../../src/outcomes.ts"],"sourcesContent":["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 UNAUTHORIZED_ID = 'unauthorized';\nconst FORBIDDEN_ID = 'forbidden';\nconst TOO_MANY_REQUESTS_ID = 'too-many-requests';\nconst ACCEPTED_ID = 'accepted';\n\nexport const allOk: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: OK_ID,\n issue: [\n {\n severity: 'information',\n code: 'informational',\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: 'informational',\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: 'informational',\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 unauthorized: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: UNAUTHORIZED_ID,\n issue: [\n {\n severity: 'error',\n code: 'login',\n details: {\n text: 'Unauthorized',\n },\n },\n ],\n};\n\nexport const forbidden: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: FORBIDDEN_ID,\n issue: [\n {\n severity: 'error',\n code: 'forbidden',\n details: {\n text: 'Forbidden',\n },\n },\n ],\n};\n\nexport const gone: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: GONE_ID,\n issue: [\n {\n severity: 'error',\n code: 'deleted',\n details: {\n text: 'Gone',\n },\n },\n ],\n};\n\nexport const tooManyRequests: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: TOO_MANY_REQUESTS_ID,\n issue: [\n {\n severity: 'error',\n code: 'throttled',\n details: {\n text: 'Too Many Requests',\n },\n },\n ],\n};\n\nexport const accepted: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: ACCEPTED_ID,\n issue: [\n {\n severity: 'information',\n code: 'informational',\n details: {\n text: 'Accepted',\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 validationError(details: string): OperationOutcome {\n return {\n resourceType: 'OperationOutcome',\n issue: [\n {\n severity: 'error',\n code: 'structure',\n details: {\n text: details,\n },\n },\n ],\n };\n}\n\nexport function isOperationOutcome(value: unknown): value is OperationOutcome {\n return typeof value === 'object' && value !== null && (value as any).resourceType === 'OperationOutcome';\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 === UNAUTHORIZED_ID) {\n return 401;\n } else if (outcome.id === FORBIDDEN_ID) {\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 if (outcome.id === TOO_MANY_REQUESTS_ID) {\n return 429;\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, cause?: unknown) {\n super(operationOutcomeToString(outcome));\n this.outcome = outcome;\n this.cause = cause;\n }\n}\n\n/**\n * Normalizes an error object into an OperationOutcome.\n * @param error The error value which could be a string, Error, OperationOutcome, or other unknown type.\n * @returns The normalized OperationOutcome.\n */\nexport function normalizeOperationOutcome(error: unknown): OperationOutcome {\n if (error instanceof OperationOutcomeError) {\n return error.outcome;\n }\n if (isOperationOutcome(error)) {\n return error;\n }\n return badRequest(normalizeErrorString(error));\n}\n\n/**\n * Normalizes an error object into a displayable error string.\n * @param error The error value which could be a string, Error, OperationOutcome, or other unknown type.\n * @returns A display string for the error.\n */\nexport function normalizeErrorString(error: unknown): string {\n if (!error) {\n return 'Unknown error';\n }\n if (typeof error === 'string') {\n return error;\n }\n if (error instanceof Error) {\n return error.message;\n }\n if (isOperationOutcome(error)) {\n return operationOutcomeToString(error);\n }\n return JSON.stringify(error);\n}\n\n/**\n * Returns a string represenation of the operation outcome.\n * @param outcome The operation outcome.\n * @returns The string representation of the operation outcome.\n */\nexport function operationOutcomeToString(outcome: OperationOutcome): string {\n const strs = [];\n if (outcome.issue) {\n for (const issue of outcome.issue) {\n let issueStr = issue.details?.text || 'Unknown error';\n if (issue.expression?.length) {\n issueStr += ` (${issue.expression.join(', ')})`;\n }\n strs.push(issueStr);\n }\n }\n return strs.length > 0 ? strs.join('; ') : 'Unknown error';\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"outcomes.mjs","sources":["../../src/outcomes.ts"],"sourcesContent":["import { OperationOutcome, OperationOutcomeIssue } 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 UNAUTHORIZED_ID = 'unauthorized';\nconst FORBIDDEN_ID = 'forbidden';\nconst TOO_MANY_REQUESTS_ID = 'too-many-requests';\nconst ACCEPTED_ID = 'accepted';\n\nexport const allOk: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: OK_ID,\n issue: [\n {\n severity: 'information',\n code: 'informational',\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: 'informational',\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: 'informational',\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 unauthorized: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: UNAUTHORIZED_ID,\n issue: [\n {\n severity: 'error',\n code: 'login',\n details: {\n text: 'Unauthorized',\n },\n },\n ],\n};\n\nexport const forbidden: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: FORBIDDEN_ID,\n issue: [\n {\n severity: 'error',\n code: 'forbidden',\n details: {\n text: 'Forbidden',\n },\n },\n ],\n};\n\nexport const gone: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: GONE_ID,\n issue: [\n {\n severity: 'error',\n code: 'deleted',\n details: {\n text: 'Gone',\n },\n },\n ],\n};\n\nexport const tooManyRequests: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: TOO_MANY_REQUESTS_ID,\n issue: [\n {\n severity: 'error',\n code: 'throttled',\n details: {\n text: 'Too Many Requests',\n },\n },\n ],\n};\n\nexport const accepted: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: ACCEPTED_ID,\n issue: [\n {\n severity: 'information',\n code: 'informational',\n details: {\n text: 'Accepted',\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 validationError(details: string): OperationOutcome {\n return {\n resourceType: 'OperationOutcome',\n issue: [\n {\n severity: 'error',\n code: 'structure',\n details: {\n text: details,\n },\n },\n ],\n };\n}\n\nexport function isOperationOutcome(value: unknown): value is OperationOutcome {\n return typeof value === 'object' && value !== null && (value as any).resourceType === 'OperationOutcome';\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 === UNAUTHORIZED_ID) {\n return 401;\n } else if (outcome.id === FORBIDDEN_ID) {\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 if (outcome.id === TOO_MANY_REQUESTS_ID) {\n return 429;\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, cause?: unknown) {\n super(operationOutcomeToString(outcome));\n this.outcome = outcome;\n this.cause = cause;\n }\n}\n\n/**\n * Normalizes an error object into an OperationOutcome.\n * @param error The error value which could be a string, Error, OperationOutcome, or other unknown type.\n * @returns The normalized OperationOutcome.\n */\nexport function normalizeOperationOutcome(error: unknown): OperationOutcome {\n if (error instanceof OperationOutcomeError) {\n return error.outcome;\n }\n if (isOperationOutcome(error)) {\n return error;\n }\n return badRequest(normalizeErrorString(error));\n}\n\n/**\n * Normalizes an error object into a displayable error string.\n * @param error The error value which could be a string, Error, OperationOutcome, or other unknown type.\n * @returns A display string for the error.\n */\nexport function normalizeErrorString(error: unknown): string {\n if (!error) {\n return 'Unknown error';\n }\n if (typeof error === 'string') {\n return error;\n }\n if (error instanceof Error) {\n return error.message;\n }\n if (isOperationOutcome(error)) {\n return operationOutcomeToString(error);\n }\n return JSON.stringify(error);\n}\n\n/**\n * Returns a string represenation of the operation outcome.\n * @param outcome The operation outcome.\n * @returns The string representation of the operation outcome.\n */\nexport function operationOutcomeToString(outcome: OperationOutcome): string {\n const strs = outcome.issue?.map(operationOutcomeIssueToString) ?? [];\n return strs.length > 0 ? strs.join('; ') : 'Unknown error';\n}\n\n/**\n * Returns a string represenation of the operation outcome issue.\n * @param issue The operation outcome issue.\n * @returns The string representation of the operation outcome issue.\n */\nexport function operationOutcomeIssueToString(issue: OperationOutcomeIssue): string {\n let issueStr = issue.details?.text ?? issue.diagnostics ?? 'Unknown error';\n if (issue.expression?.length) {\n issueStr += ` (${issue.expression.join(', ')})`;\n }\n return issueStr;\n}\n"],"names":[],"mappings":"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"}
@@ -30,18 +30,18 @@ var SearchParameterType;
30
30
  function getSearchParameterDetails(resourceType, searchParam) {
31
31
  let result = globalSchema.types[resourceType]?.searchParamsDetails?.[searchParam.code];
32
32
  if (!result) {
33
- result = buildSearchParamterDetails(resourceType, searchParam);
33
+ result = buildSearchParameterDetails(resourceType, searchParam);
34
34
  }
35
35
  return result;
36
36
  }
37
- function setSearchParamterDetails(resourceType, code, details) {
37
+ function setSearchParameterDetails(resourceType, code, details) {
38
38
  const typeSchema = globalSchema.types[resourceType];
39
39
  if (!typeSchema.searchParamsDetails) {
40
40
  typeSchema.searchParamsDetails = {};
41
41
  }
42
42
  typeSchema.searchParamsDetails[code] = details;
43
43
  }
44
- function buildSearchParamterDetails(resourceType, searchParam) {
44
+ function buildSearchParameterDetails(resourceType, searchParam) {
45
45
  const code = searchParam.code;
46
46
  const columnName = convertCodeToColumnName(code);
47
47
  const expression = getExpressionForResourceType(resourceType, searchParam.expression)?.split('.');
@@ -83,7 +83,7 @@ function buildSearchParamterDetails(resourceType, searchParam) {
83
83
  }
84
84
  const type = getSearchParameterType(searchParam, propertyType);
85
85
  const result = { columnName, type, elementDefinition, array };
86
- setSearchParamterDetails(resourceType, code, result);
86
+ setSearchParameterDetails(resourceType, code, result);
87
87
  return result;
88
88
  }
89
89
  function isBackboneElement(propertyType) {
@@ -1 +1 @@
1
- {"version":3,"file":"details.mjs","sources":["../../../src/search/details.ts"],"sourcesContent":["import { ElementDefinition, SearchParameter } from '@medplum/fhirtypes';\nimport { PropertyType, buildTypeName, getElementDefinition, globalSchema } 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 CANONICAL = 'CANONICAL',\n DATE = 'DATE',\n DATETIME = 'DATETIME',\n PERIOD = 'PERIOD',\n UUID = 'UUID',\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 * @param resourceType The root resource type.\n * @param searchParam The search parameter.\n * @returns The search parameter type details.\n */\nexport function getSearchParameterDetails(resourceType: string, searchParam: SearchParameter): SearchParameterDetails {\n let result: SearchParameterDetails | undefined =\n globalSchema.types[resourceType]?.searchParamsDetails?.[searchParam.code as string];\n if (!result) {\n result = buildSearchParamterDetails(resourceType, searchParam);\n }\n return result;\n}\n\nfunction setSearchParamterDetails(resourceType: string, code: string, details: SearchParameterDetails): void {\n const typeSchema = globalSchema.types[resourceType];\n if (!typeSchema.searchParamsDetails) {\n typeSchema.searchParamsDetails = {};\n }\n typeSchema.searchParamsDetails[code] = details;\n}\n\nfunction buildSearchParamterDetails(resourceType: string, searchParam: SearchParameter): SearchParameterDetails {\n const code = searchParam.code as string;\n const columnName = convertCodeToColumnName(code);\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 let propertyName = expression[i];\n let hasArrayIndex = false;\n\n const arrayIndexMatch = /\\[\\d+\\]$/.exec(propertyName);\n if (arrayIndexMatch) {\n propertyName = propertyName.substring(0, propertyName.length - arrayIndexMatch[0].length);\n hasArrayIndex = true;\n }\n\n elementDefinition = getElementDefinition(baseType, propertyName);\n if (!elementDefinition) {\n throw new Error(`Element definition not found for ${resourceType} ${searchParam.code}`);\n }\n\n if (elementDefinition.max !== '0' && elementDefinition.max !== '1' && !hasArrayIndex) {\n array = true;\n }\n\n // \"code\" is only missing when using \"contentReference\"\n // \"contentReference\" is handled above in \"getElementDefinition\"\n propertyType = elementDefinition.type?.[0].code as string;\n\n if (i < expression.length - 1) {\n if (isBackboneElement(propertyType)) {\n baseType = buildTypeName(elementDefinition.path?.split('.') as string[]);\n } else {\n baseType = propertyType;\n }\n }\n }\n\n const type = getSearchParameterType(searchParam, propertyType as PropertyType);\n const result = { columnName, type, elementDefinition, array };\n setSearchParamterDetails(resourceType, code, result);\n return result;\n}\n\nfunction isBackboneElement(propertyType: string): boolean {\n return propertyType === 'Element' || propertyType === 'BackboneElement';\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: PropertyType): SearchParameterType {\n let type = SearchParameterType.TEXT;\n switch (searchParam.type) {\n case 'date':\n if (propertyType === PropertyType.date) {\n type = SearchParameterType.DATE;\n } else {\n type = SearchParameterType.DATETIME;\n }\n break;\n case 'number':\n type = SearchParameterType.NUMBER;\n break;\n case 'quantity':\n type = SearchParameterType.QUANTITY;\n break;\n case 'reference':\n if (propertyType === PropertyType.canonical) {\n type = SearchParameterType.CANONICAL;\n } else {\n type = SearchParameterType.REFERENCE;\n }\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 if (isIgnoredExpression(e)) {\n continue;\n }\n const simplified = simplifyExpression(e);\n if (simplified.startsWith(resourceType + '.')) {\n return simplified;\n }\n }\n return undefined;\n}\n\nfunction isIgnoredExpression(input: string): boolean {\n return input.includes(' as Period') || input.includes(' as SampledDate');\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 const stopStrings = [' != ', ' as ', '.as(', '.exists(', '.resolve(', '.where('];\n for (const stopString of stopStrings) {\n if (result.includes(stopString)) {\n result = result.substring(0, result.indexOf(stopString));\n }\n }\n\n return result;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"details.mjs","sources":["../../../src/search/details.ts"],"sourcesContent":["import { ElementDefinition, SearchParameter } from '@medplum/fhirtypes';\nimport { buildTypeName, getElementDefinition, globalSchema, PropertyType } 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 CANONICAL = 'CANONICAL',\n DATE = 'DATE',\n DATETIME = 'DATETIME',\n PERIOD = 'PERIOD',\n UUID = 'UUID',\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 * @param resourceType The root resource type.\n * @param searchParam The search parameter.\n * @returns The search parameter type details.\n */\nexport function getSearchParameterDetails(resourceType: string, searchParam: SearchParameter): SearchParameterDetails {\n let result: SearchParameterDetails | undefined =\n globalSchema.types[resourceType]?.searchParamsDetails?.[searchParam.code as string];\n if (!result) {\n result = buildSearchParameterDetails(resourceType, searchParam);\n }\n return result;\n}\n\nfunction setSearchParameterDetails(resourceType: string, code: string, details: SearchParameterDetails): void {\n const typeSchema = globalSchema.types[resourceType];\n if (!typeSchema.searchParamsDetails) {\n typeSchema.searchParamsDetails = {};\n }\n typeSchema.searchParamsDetails[code] = details;\n}\n\nfunction buildSearchParameterDetails(resourceType: string, searchParam: SearchParameter): SearchParameterDetails {\n const code = searchParam.code as string;\n const columnName = convertCodeToColumnName(code);\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 let propertyName = expression[i];\n let hasArrayIndex = false;\n\n const arrayIndexMatch = /\\[\\d+\\]$/.exec(propertyName);\n if (arrayIndexMatch) {\n propertyName = propertyName.substring(0, propertyName.length - arrayIndexMatch[0].length);\n hasArrayIndex = true;\n }\n\n elementDefinition = getElementDefinition(baseType, propertyName);\n if (!elementDefinition) {\n throw new Error(`Element definition not found for ${resourceType} ${searchParam.code}`);\n }\n\n if (elementDefinition.max !== '0' && elementDefinition.max !== '1' && !hasArrayIndex) {\n array = true;\n }\n\n // \"code\" is only missing when using \"contentReference\"\n // \"contentReference\" is handled above in \"getElementDefinition\"\n propertyType = elementDefinition.type?.[0].code as string;\n\n if (i < expression.length - 1) {\n if (isBackboneElement(propertyType)) {\n baseType = buildTypeName(elementDefinition.path?.split('.') as string[]);\n } else {\n baseType = propertyType;\n }\n }\n }\n\n const type = getSearchParameterType(searchParam, propertyType as PropertyType);\n const result = { columnName, type, elementDefinition, array };\n setSearchParameterDetails(resourceType, code, result);\n return result;\n}\n\nfunction isBackboneElement(propertyType: string): boolean {\n return propertyType === 'Element' || propertyType === 'BackboneElement';\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: PropertyType): SearchParameterType {\n let type = SearchParameterType.TEXT;\n switch (searchParam.type) {\n case 'date':\n if (propertyType === PropertyType.date) {\n type = SearchParameterType.DATE;\n } else {\n type = SearchParameterType.DATETIME;\n }\n break;\n case 'number':\n type = SearchParameterType.NUMBER;\n break;\n case 'quantity':\n type = SearchParameterType.QUANTITY;\n break;\n case 'reference':\n if (propertyType === PropertyType.canonical) {\n type = SearchParameterType.CANONICAL;\n } else {\n type = SearchParameterType.REFERENCE;\n }\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 if (isIgnoredExpression(e)) {\n continue;\n }\n const simplified = simplifyExpression(e);\n if (simplified.startsWith(resourceType + '.')) {\n return simplified;\n }\n }\n return undefined;\n}\n\nfunction isIgnoredExpression(input: string): boolean {\n return input.includes(' as Period') || input.includes(' as SampledDate');\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 const stopStrings = [' != ', ' as ', '.as(', '.exists(', '.resolve(', '.where('];\n for (const stopString of stopStrings) {\n if (result.includes(stopString)) {\n result = result.substring(0, result.indexOf(stopString));\n }\n }\n\n return result;\n}\n"],"names":[],"mappings":";;;IAIY,oBAWX;AAXD,CAAA,UAAY,mBAAmB,EAAA;AAC7B,IAAA,mBAAA,CAAA,SAAA,CAAA,GAAA,SAAmB,CAAA;AACnB,IAAA,mBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACjB,IAAA,mBAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACrB,IAAA,mBAAA,CAAA,MAAA,CAAA,GAAA,MAAa,CAAA;AACb,IAAA,mBAAA,CAAA,WAAA,CAAA,GAAA,WAAuB,CAAA;AACvB,IAAA,mBAAA,CAAA,WAAA,CAAA,GAAA,WAAuB,CAAA;AACvB,IAAA,mBAAA,CAAA,MAAA,CAAA,GAAA,MAAa,CAAA;AACb,IAAA,mBAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACrB,IAAA,mBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACjB,IAAA,mBAAA,CAAA,MAAA,CAAA,GAAA,MAAa,CAAA;AACf,CAAC,EAXW,mBAAmB,KAAnB,mBAAmB,GAW9B,EAAA,CAAA,CAAA,CAAA;AASD;;;;;;;;;;;;AAYG;AACa,SAAA,yBAAyB,CAAC,YAAoB,EAAE,WAA4B,EAAA;AAC1F,IAAA,IAAI,MAAM,GACR,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,mBAAmB,GAAG,WAAW,CAAC,IAAc,CAAC,CAAC;IACtF,IAAI,CAAC,MAAM,EAAE;AACX,QAAA,MAAM,GAAG,2BAA2B,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;AACjE,KAAA;AACD,IAAA,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,yBAAyB,CAAC,YAAoB,EAAE,IAAY,EAAE,OAA+B,EAAA;IACpG,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AACpD,IAAA,IAAI,CAAC,UAAU,CAAC,mBAAmB,EAAE;AACnC,QAAA,UAAU,CAAC,mBAAmB,GAAG,EAAE,CAAC;AACrC,KAAA;AACD,IAAA,UAAU,CAAC,mBAAmB,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;AACjD,CAAC;AAED,SAAS,2BAA2B,CAAC,YAAoB,EAAE,WAA4B,EAAA;AACrF,IAAA,MAAM,IAAI,GAAG,WAAW,CAAC,IAAc,CAAC;AACxC,IAAA,MAAM,UAAU,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;AACjD,IAAA,MAAM,UAAU,GAAG,4BAA4B,CAAC,YAAY,EAAE,WAAW,CAAC,UAAoB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5G,IAAI,CAAC,UAAU,EAAE;;;QAGf,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,mBAAmB,CAAC,IAAI,EAAE,CAAC;AACvD,KAAA;IAED,IAAI,QAAQ,GAAG,YAAY,CAAC;IAC5B,IAAI,iBAAiB,GAAG,SAAS,CAAC;IAClC,IAAI,YAAY,GAAG,SAAS,CAAC;IAC7B,IAAI,KAAK,GAAG,KAAK,CAAC;AAElB,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC1C,QAAA,IAAI,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,aAAa,GAAG,KAAK,CAAC;QAE1B,MAAM,eAAe,GAAG,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;AACtD,QAAA,IAAI,eAAe,EAAE;AACnB,YAAA,YAAY,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC1F,aAAa,GAAG,IAAI,CAAC;AACtB,SAAA;AAED,QAAA,iBAAiB,GAAG,oBAAoB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QACjE,IAAI,CAAC,iBAAiB,EAAE;YACtB,MAAM,IAAI,KAAK,CAAC,CAAoC,iCAAA,EAAA,YAAY,CAAI,CAAA,EAAA,WAAW,CAAC,IAAI,CAAE,CAAA,CAAC,CAAC;AACzF,SAAA;AAED,QAAA,IAAI,iBAAiB,CAAC,GAAG,KAAK,GAAG,IAAI,iBAAiB,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE;YACpF,KAAK,GAAG,IAAI,CAAC;AACd,SAAA;;;QAID,YAAY,GAAG,iBAAiB,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAc,CAAC;AAE1D,QAAA,IAAI,CAAC,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;AAC7B,YAAA,IAAI,iBAAiB,CAAC,YAAY,CAAC,EAAE;AACnC,gBAAA,QAAQ,GAAG,aAAa,CAAC,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAa,CAAC,CAAC;AAC1E,aAAA;AAAM,iBAAA;gBACL,QAAQ,GAAG,YAAY,CAAC;AACzB,aAAA;AACF,SAAA;AACF,KAAA;IAED,MAAM,IAAI,GAAG,sBAAsB,CAAC,WAAW,EAAE,YAA4B,CAAC,CAAC;IAC/E,MAAM,MAAM,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC;AAC9D,IAAA,yBAAyB,CAAC,YAAY,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AACtD,IAAA,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,iBAAiB,CAAC,YAAoB,EAAA;AAC7C,IAAA,OAAO,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,iBAAiB,CAAC;AAC1E,CAAC;AAED;;;;AAIG;AACH,SAAS,uBAAuB,CAAC,IAAY,EAAA;AAC3C,IAAA,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,KAAK,MAAM,IAAI,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;AACzG,CAAC;AAED,SAAS,sBAAsB,CAAC,WAA4B,EAAE,YAA0B,EAAA;AACtF,IAAA,IAAI,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC;IACpC,QAAQ,WAAW,CAAC,IAAI;AACtB,QAAA,KAAK,MAAM;AACT,YAAA,IAAI,YAAY,KAAK,YAAY,CAAC,IAAI,EAAE;AACtC,gBAAA,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC;AACjC,aAAA;AAAM,iBAAA;AACL,gBAAA,IAAI,GAAG,mBAAmB,CAAC,QAAQ,CAAC;AACrC,aAAA;YACD,MAAM;AACR,QAAA,KAAK,QAAQ;AACX,YAAA,IAAI,GAAG,mBAAmB,CAAC,MAAM,CAAC;YAClC,MAAM;AACR,QAAA,KAAK,UAAU;AACb,YAAA,IAAI,GAAG,mBAAmB,CAAC,QAAQ,CAAC;YACpC,MAAM;AACR,QAAA,KAAK,WAAW;AACd,YAAA,IAAI,YAAY,KAAK,YAAY,CAAC,SAAS,EAAE;AAC3C,gBAAA,IAAI,GAAG,mBAAmB,CAAC,SAAS,CAAC;AACtC,aAAA;AAAM,iBAAA;AACL,gBAAA,IAAI,GAAG,mBAAmB,CAAC,SAAS,CAAC;AACtC,aAAA;YACD,MAAM;AACR,QAAA,KAAK,OAAO;YACV,IAAI,YAAY,KAAK,SAAS,EAAE;AAC9B,gBAAA,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC;AACpC,aAAA;YACD,MAAM;AACT,KAAA;AACD,IAAA,OAAO,IAAI,CAAC;AACd,CAAC;AAEe,SAAA,4BAA4B,CAAC,YAAoB,EAAE,UAAkB,EAAA;IACnF,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC5C,IAAA,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE;AAC3B,QAAA,IAAI,mBAAmB,CAAC,CAAC,CAAC,EAAE;YAC1B,SAAS;AACV,SAAA;AACD,QAAA,MAAM,UAAU,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;QACzC,IAAI,UAAU,CAAC,UAAU,CAAC,YAAY,GAAG,GAAG,CAAC,EAAE;AAC7C,YAAA,OAAO,UAAU,CAAC;AACnB,SAAA;AACF,KAAA;AACD,IAAA,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa,EAAA;AACxC,IAAA,OAAO,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa,EAAA;AACvC,IAAA,IAAI,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;AAE1B,IAAA,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AAClD,QAAA,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjD,KAAA;AAED,IAAA,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;AACjF,IAAA,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE;AACpC,QAAA,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;AAC/B,YAAA,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;AAC1D,SAAA;AACF,KAAA;AAED,IAAA,OAAO,MAAM,CAAC;AAChB;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","sources":["../../src/utils.ts"],"sourcesContent":["import {\n Attachment,\n CodeableConcept,\n Device,\n Extension,\n Identifier,\n ObservationDefinition,\n ObservationDefinitionQualifiedInterval,\n Patient,\n Practitioner,\n ProjectMembership,\n QuestionnaireResponse,\n QuestionnaireResponseItem,\n QuestionnaireResponseItemAnswer,\n Range,\n Reference,\n RelatedPerson,\n Resource,\n} from '@medplum/fhirtypes';\nimport { formatHumanName } from './format';\n\n/**\n * @internal\n */\nexport type ProfileResource = Patient | Practitioner | RelatedPerson;\n\n/**\n * @internal\n */\nexport interface InviteResult {\n profile: ProfileResource;\n membership: ProjectMembership;\n}\n\ninterface Code {\n code?: CodeableConcept;\n}\n/**\n * @internal\n */\nexport type ResourceWithCode = Resource & Code;\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): resource is ProfileResource {\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 * @returns Human friendly display string.\n */\nexport function getDisplayString(resource: Resource): string {\n if (isProfileResource(resource)) {\n const profileName = getProfileResourceDisplayString(resource);\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?.text) {\n return resource.code.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 (!('photo' in resource)) {\n return undefined;\n }\n\n const photo = resource.photo;\n if (!photo) {\n return undefined;\n }\n\n if (Array.isArray(photo)) {\n for (const p of photo) {\n const url = getPhotoImageSrc(p);\n if (url) {\n return url;\n }\n }\n } else {\n return getPhotoImageSrc(photo);\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 items The current questionnaire response items.\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 the resource identifier for the given system.\n *\n * If multiple identifiers exist with the same system, the first one is returned.\n *\n * If the system is not found, then returns undefined.\n * @param resource The resource to check.\n * @param system The identifier system.\n * @returns The identifier value if found; otherwise undefined.\n */\nexport function getIdentifier(resource: Resource, system: string): string | undefined {\n const identifiers = (resource as any).identifier as Identifier[] | Identifier | undefined;\n if (!identifiers) {\n return undefined;\n }\n const array = Array.isArray(identifiers) ? identifiers : [identifiers];\n for (const identifier of array) {\n if (identifier.system === system) {\n return identifier.value;\n }\n }\n return undefined;\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: any, ...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 * Returns an extension 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 object if found; undefined otherwise.\n */\nexport function getExtension(resource: any, ...urls: string[]): Extension | 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 as Extension | 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 k Property key.\n * @param v Property value.\n * @returns The replaced 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 */\nexport function 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 * @param path Optional path string.\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 * Creates a deep clone of the input value.\n *\n * Limitations:\n * - Only supports JSON primitives and arrays.\n * - Does not support Functions, lambdas, etc.\n * - Does not support circular references.\n *\n * See: https://web.dev/structured-clone/\n * See: https://stackoverflow.com/questions/40488190/how-is-structured-clone-algorithm-different-from-deep-copy\n * @param input The input to clone.\n * @returns A deep clone of the input.\n */\nexport function deepClone<T>(input: T): T {\n return JSON.parse(JSON.stringify(input)) as T;\n}\n\n/**\n * Returns true if the input string is a UUID.\n * @param input The input string.\n * @returns True if the input string matches the UUID format.\n */\nexport function isUUID(input: string): boolean {\n return !!input.match(/^\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12}$/i);\n}\n\n/**\n * Returns true if the input is an object.\n * @param obj 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.substring(1);\n}\n\nexport function isLowerCase(c: string): boolean {\n return c === c.toLowerCase() && c !== c.toUpperCase();\n}\n\n/**\n * Tries to find a code string for a given system within a given codeable concept.\n * @param concept The codeable concept.\n * @param system The system string.\n * @returns The code if found; otherwise undefined.\n */\nexport function getCodeBySystem(concept: CodeableConcept, system: string): string | undefined {\n return concept?.coding?.find((coding) => coding.system === system)?.code;\n}\n\n/**\n * Sets a code for a given system within a given codeable concept.\n * @param concept The codeable concept.\n * @param system The system string.\n * @param code The code value.\n */\nexport function setCodeBySystem(concept: CodeableConcept, system: string, code: string): void {\n if (!concept.coding) {\n concept.coding = [];\n }\n const coding = concept.coding?.find((c) => c.system === system);\n if (coding) {\n coding.code = code;\n } else {\n concept.coding?.push({ system, code });\n }\n}\n\n/**\n * Tries to find an observation interval for the given patient and value.\n * @param definition The observation definition.\n * @param patient The patient.\n * @param value The observation value.\n * @param category Optional interval category restriction.\n * @returns The observation interval if found; otherwise undefined.\n */\nexport function findObservationInterval(\n definition: ObservationDefinition,\n patient: Patient,\n value: number,\n category?: 'reference' | 'critical' | 'absolute'\n): ObservationDefinitionQualifiedInterval | undefined {\n return definition.qualifiedInterval?.find(\n (interval) =>\n observationIntervalMatchesPatient(interval, patient) &&\n observationIntervalMatchesValue(interval, value, definition.quantitativeDetails?.decimalPrecision) &&\n (category === undefined || interval.category === category)\n );\n}\n\n/**\n * Tries to find an observation reference range for the given patient and condition names.\n * @param definition The observation definition.\n * @param patient The patient.\n * @param names The condition names.\n * @returns The observation interval if found; otherwise undefined.\n */\nexport function findObservationReferenceRange(\n definition: ObservationDefinition,\n patient: Patient,\n names: string[]\n): ObservationDefinitionQualifiedInterval | undefined {\n return definition.qualifiedInterval?.find(\n (interval) => observationIntervalMatchesPatient(interval, patient) && names.includes(interval.condition as string)\n );\n}\n\n/**\n * Returns true if the patient matches the observation interval.\n * @param interval The observation interval.\n * @param patient The patient.\n * @returns True if the patient matches the observation interval.\n */\nfunction observationIntervalMatchesPatient(\n interval: ObservationDefinitionQualifiedInterval,\n patient: Patient\n): boolean {\n return observationIntervalMatchesGender(interval, patient) && observationIntervalMatchesAge(interval, patient);\n}\n\n/**\n * Returns true if the patient gender matches the observation interval.\n * @param interval The observation interval.\n * @param patient The patient.\n * @returns True if the patient gender matches the observation interval.\n */\nfunction observationIntervalMatchesGender(interval: ObservationDefinitionQualifiedInterval, patient: Patient): boolean {\n return !interval.gender || interval.gender === patient.gender;\n}\n\n/**\n * Returns true if the patient age matches the observation interval.\n * @param interval The observation interval.\n * @param patient The patient.\n * @returns True if the patient age matches the observation interval.\n */\nfunction observationIntervalMatchesAge(interval: ObservationDefinitionQualifiedInterval, patient: Patient): boolean {\n return !interval.age || matchesRange(calculateAge(patient.birthDate as string).years, interval.age);\n}\n\n/**\n * Returns true if the value matches the observation interval.\n * @param interval The observation interval.\n * @param value The observation value.\n * @param precision Optional precision in number of digits.\n * @returns True if the value matches the observation interval.\n */\nfunction observationIntervalMatchesValue(\n interval: ObservationDefinitionQualifiedInterval,\n value: number,\n precision?: number\n): boolean {\n return !!interval.range && matchesRange(value, interval.range, precision);\n}\n\n/**\n * Returns true if the value is in the range accounting for precision.\n * @param value The numeric value.\n * @param range The numeric range.\n * @param precision Optional precision in number of digits.\n * @returns True if the value is within the range.\n */\nexport function matchesRange(value: number, range: Range, precision?: number): boolean {\n return (\n (range.low?.value === undefined || preciseGreaterThanOrEquals(value, range.low.value, precision)) &&\n (range.high?.value === undefined || preciseLessThanOrEquals(value, range.high.value, precision))\n );\n}\n\n/**\n * Returns the input number rounded to the specified number of digits.\n * @param a The input number.\n * @param precision The precision in number of digits.\n * @returns The number rounded to the specified number of digits.\n */\nexport function preciseRound(a: number, precision: number): number {\n return parseFloat(a.toFixed(precision));\n}\n\n/**\n * Returns true if the two numbers are equal to the given precision.\n * @param a The first number.\n * @param b The second number.\n * @param precision Optional precision in number of digits.\n * @returns True if the two numbers are equal to the given precision.\n */\nexport function preciseEquals(a: number, b: number, precision?: number): boolean {\n return toPreciseInteger(a, precision) === toPreciseInteger(b, precision);\n}\n\n/**\n * Returns true if the first number is less than the second number to the given precision.\n * @param a The first number.\n * @param b The second number.\n * @param precision Optional precision in number of digits.\n * @returns True if the first number is less than the second number to the given precision.\n */\nexport function preciseLessThan(a: number, b: number, precision?: number): boolean {\n return toPreciseInteger(a, precision) < toPreciseInteger(b, precision);\n}\n\n/**\n * Returns true if the first number is greater than the second number to the given precision.\n * @param a The first number.\n * @param b The second number.\n * @param precision Optional precision in number of digits.\n * @returns True if the first number is greater than the second number to the given precision.\n */\nexport function preciseGreaterThan(a: number, b: number, precision?: number): boolean {\n return toPreciseInteger(a, precision) > toPreciseInteger(b, precision);\n}\n\n/**\n * Returns true if the first number is less than or equal to the second number to the given precision.\n * @param a The first number.\n * @param b The second number.\n * @param precision Optional precision in number of digits.\n * @returns True if the first number is less than or equal to the second number to the given precision.\n */\nexport function preciseLessThanOrEquals(a: number, b: number, precision?: number): boolean {\n return toPreciseInteger(a, precision) <= toPreciseInteger(b, precision);\n}\n\n/**\n * Returns true if the first number is greater than or equal to the second number to the given precision.\n * @param a The first number.\n * @param b The second number.\n * @param precision Optional precision in number of digits.\n * @returns True if the first number is greater than or equal to the second number to the given precision.\n */\nexport function preciseGreaterThanOrEquals(a: number, b: number, precision?: number): boolean {\n return toPreciseInteger(a, precision) >= toPreciseInteger(b, precision);\n}\n\n/**\n * Returns an integer representation of the number with the given precision.\n * For example, if precision is 2, then 1.2345 will be returned as 123.\n * @param a The number.\n * @param precision Optional precision in number of digits.\n * @returns The integer with the given precision.\n */\nfunction toPreciseInteger(a: number, precision?: number): number {\n if (precision === undefined) {\n return a;\n }\n return Math.round(a * Math.pow(10, precision));\n}\n\n/**\n * Finds the first resource in the input array that matches the specified code and system.\n * @param resources - The array of resources to search.\n * @param code - The code to search for.\n * @param system - The system to search for.\n * @returns The first resource in the input array that matches the specified code and system, or undefined if no such resource is found.\n */\nexport function findResourceByCode(\n resources: ResourceWithCode[],\n code: CodeableConcept | string,\n system: string\n): ResourceWithCode | undefined {\n return resources.find((r) =>\n typeof code === 'string'\n ? getCodeBySystem(r.code || {}, system) === code\n : getCodeBySystem(r.code || {}, system) === getCodeBySystem(code, system)\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.mjs","sources":["../../src/utils.ts"],"sourcesContent":["import {\n Attachment,\n CodeableConcept,\n Device,\n Extension,\n Identifier,\n ObservationDefinition,\n ObservationDefinitionQualifiedInterval,\n Patient,\n Practitioner,\n QuestionnaireResponse,\n QuestionnaireResponseItem,\n QuestionnaireResponseItemAnswer,\n Range,\n Reference,\n RelatedPerson,\n Resource,\n} from '@medplum/fhirtypes';\nimport { formatHumanName } from './format';\n\n/**\n * @internal\n */\nexport type ProfileResource = Patient | Practitioner | RelatedPerson;\n\ninterface Code {\n code?: CodeableConcept;\n}\n/**\n * @internal\n */\nexport type ResourceWithCode = Resource & Code;\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): resource is ProfileResource {\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 * @returns Human friendly display string.\n */\nexport function getDisplayString(resource: Resource): string {\n if (isProfileResource(resource)) {\n const profileName = getProfileResourceDisplayString(resource);\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?.text) {\n return resource.code.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 (!('photo' in resource)) {\n return undefined;\n }\n\n const photo = resource.photo;\n if (!photo) {\n return undefined;\n }\n\n if (Array.isArray(photo)) {\n for (const p of photo) {\n const url = getPhotoImageSrc(p);\n if (url) {\n return url;\n }\n }\n } else {\n return getPhotoImageSrc(photo);\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 items The current questionnaire response items.\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 the resource identifier for the given system.\n *\n * If multiple identifiers exist with the same system, the first one is returned.\n *\n * If the system is not found, then returns undefined.\n * @param resource The resource to check.\n * @param system The identifier system.\n * @returns The identifier value if found; otherwise undefined.\n */\nexport function getIdentifier(resource: Resource, system: string): string | undefined {\n const identifiers = (resource as any).identifier as Identifier[] | Identifier | undefined;\n if (!identifiers) {\n return undefined;\n }\n const array = Array.isArray(identifiers) ? identifiers : [identifiers];\n for (const identifier of array) {\n if (identifier.system === system) {\n return identifier.value;\n }\n }\n return undefined;\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: any, ...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 * Returns an extension 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 object if found; undefined otherwise.\n */\nexport function getExtension(resource: any, ...urls: string[]): Extension | 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 as Extension | 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 k Property key.\n * @param v Property value.\n * @returns The replaced 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 */\nexport function 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 * @param path Optional path string.\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 * Creates a deep clone of the input value.\n *\n * Limitations:\n * - Only supports JSON primitives and arrays.\n * - Does not support Functions, lambdas, etc.\n * - Does not support circular references.\n *\n * See: https://web.dev/structured-clone/\n * See: https://stackoverflow.com/questions/40488190/how-is-structured-clone-algorithm-different-from-deep-copy\n * @param input The input to clone.\n * @returns A deep clone of the input.\n */\nexport function deepClone<T>(input: T): T {\n return JSON.parse(JSON.stringify(input)) as T;\n}\n\n/**\n * Returns true if the input string is a UUID.\n * @param input The input string.\n * @returns True if the input string matches the UUID format.\n */\nexport function isUUID(input: string): boolean {\n return !!input.match(/^\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12}$/i);\n}\n\n/**\n * Returns true if the input is an object.\n * @param obj 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.substring(1);\n}\n\nexport function isLowerCase(c: string): boolean {\n return c === c.toLowerCase() && c !== c.toUpperCase();\n}\n\n/**\n * Tries to find a code string for a given system within a given codeable concept.\n * @param concept The codeable concept.\n * @param system The system string.\n * @returns The code if found; otherwise undefined.\n */\nexport function getCodeBySystem(concept: CodeableConcept, system: string): string | undefined {\n return concept?.coding?.find((coding) => coding.system === system)?.code;\n}\n\n/**\n * Sets a code for a given system within a given codeable concept.\n * @param concept The codeable concept.\n * @param system The system string.\n * @param code The code value.\n */\nexport function setCodeBySystem(concept: CodeableConcept, system: string, code: string): void {\n if (!concept.coding) {\n concept.coding = [];\n }\n const coding = concept.coding?.find((c) => c.system === system);\n if (coding) {\n coding.code = code;\n } else {\n concept.coding?.push({ system, code });\n }\n}\n\n/**\n * Tries to find an observation interval for the given patient and value.\n * @param definition The observation definition.\n * @param patient The patient.\n * @param value The observation value.\n * @param category Optional interval category restriction.\n * @returns The observation interval if found; otherwise undefined.\n */\nexport function findObservationInterval(\n definition: ObservationDefinition,\n patient: Patient,\n value: number,\n category?: 'reference' | 'critical' | 'absolute'\n): ObservationDefinitionQualifiedInterval | undefined {\n return definition.qualifiedInterval?.find(\n (interval) =>\n observationIntervalMatchesPatient(interval, patient) &&\n observationIntervalMatchesValue(interval, value, definition.quantitativeDetails?.decimalPrecision) &&\n (category === undefined || interval.category === category)\n );\n}\n\n/**\n * Tries to find an observation reference range for the given patient and condition names.\n * @param definition The observation definition.\n * @param patient The patient.\n * @param names The condition names.\n * @returns The observation interval if found; otherwise undefined.\n */\nexport function findObservationReferenceRange(\n definition: ObservationDefinition,\n patient: Patient,\n names: string[]\n): ObservationDefinitionQualifiedInterval | undefined {\n return definition.qualifiedInterval?.find(\n (interval) => observationIntervalMatchesPatient(interval, patient) && names.includes(interval.condition as string)\n );\n}\n\n/**\n * Returns true if the patient matches the observation interval.\n * @param interval The observation interval.\n * @param patient The patient.\n * @returns True if the patient matches the observation interval.\n */\nfunction observationIntervalMatchesPatient(\n interval: ObservationDefinitionQualifiedInterval,\n patient: Patient\n): boolean {\n return observationIntervalMatchesGender(interval, patient) && observationIntervalMatchesAge(interval, patient);\n}\n\n/**\n * Returns true if the patient gender matches the observation interval.\n * @param interval The observation interval.\n * @param patient The patient.\n * @returns True if the patient gender matches the observation interval.\n */\nfunction observationIntervalMatchesGender(interval: ObservationDefinitionQualifiedInterval, patient: Patient): boolean {\n return !interval.gender || interval.gender === patient.gender;\n}\n\n/**\n * Returns true if the patient age matches the observation interval.\n * @param interval The observation interval.\n * @param patient The patient.\n * @returns True if the patient age matches the observation interval.\n */\nfunction observationIntervalMatchesAge(interval: ObservationDefinitionQualifiedInterval, patient: Patient): boolean {\n return !interval.age || matchesRange(calculateAge(patient.birthDate as string).years, interval.age);\n}\n\n/**\n * Returns true if the value matches the observation interval.\n * @param interval The observation interval.\n * @param value The observation value.\n * @param precision Optional precision in number of digits.\n * @returns True if the value matches the observation interval.\n */\nfunction observationIntervalMatchesValue(\n interval: ObservationDefinitionQualifiedInterval,\n value: number,\n precision?: number\n): boolean {\n return !!interval.range && matchesRange(value, interval.range, precision);\n}\n\n/**\n * Returns true if the value is in the range accounting for precision.\n * @param value The numeric value.\n * @param range The numeric range.\n * @param precision Optional precision in number of digits.\n * @returns True if the value is within the range.\n */\nexport function matchesRange(value: number, range: Range, precision?: number): boolean {\n return (\n (range.low?.value === undefined || preciseGreaterThanOrEquals(value, range.low.value, precision)) &&\n (range.high?.value === undefined || preciseLessThanOrEquals(value, range.high.value, precision))\n );\n}\n\n/**\n * Returns the input number rounded to the specified number of digits.\n * @param a The input number.\n * @param precision The precision in number of digits.\n * @returns The number rounded to the specified number of digits.\n */\nexport function preciseRound(a: number, precision: number): number {\n return parseFloat(a.toFixed(precision));\n}\n\n/**\n * Returns true if the two numbers are equal to the given precision.\n * @param a The first number.\n * @param b The second number.\n * @param precision Optional precision in number of digits.\n * @returns True if the two numbers are equal to the given precision.\n */\nexport function preciseEquals(a: number, b: number, precision?: number): boolean {\n return toPreciseInteger(a, precision) === toPreciseInteger(b, precision);\n}\n\n/**\n * Returns true if the first number is less than the second number to the given precision.\n * @param a The first number.\n * @param b The second number.\n * @param precision Optional precision in number of digits.\n * @returns True if the first number is less than the second number to the given precision.\n */\nexport function preciseLessThan(a: number, b: number, precision?: number): boolean {\n return toPreciseInteger(a, precision) < toPreciseInteger(b, precision);\n}\n\n/**\n * Returns true if the first number is greater than the second number to the given precision.\n * @param a The first number.\n * @param b The second number.\n * @param precision Optional precision in number of digits.\n * @returns True if the first number is greater than the second number to the given precision.\n */\nexport function preciseGreaterThan(a: number, b: number, precision?: number): boolean {\n return toPreciseInteger(a, precision) > toPreciseInteger(b, precision);\n}\n\n/**\n * Returns true if the first number is less than or equal to the second number to the given precision.\n * @param a The first number.\n * @param b The second number.\n * @param precision Optional precision in number of digits.\n * @returns True if the first number is less than or equal to the second number to the given precision.\n */\nexport function preciseLessThanOrEquals(a: number, b: number, precision?: number): boolean {\n return toPreciseInteger(a, precision) <= toPreciseInteger(b, precision);\n}\n\n/**\n * Returns true if the first number is greater than or equal to the second number to the given precision.\n * @param a The first number.\n * @param b The second number.\n * @param precision Optional precision in number of digits.\n * @returns True if the first number is greater than or equal to the second number to the given precision.\n */\nexport function preciseGreaterThanOrEquals(a: number, b: number, precision?: number): boolean {\n return toPreciseInteger(a, precision) >= toPreciseInteger(b, precision);\n}\n\n/**\n * Returns an integer representation of the number with the given precision.\n * For example, if precision is 2, then 1.2345 will be returned as 123.\n * @param a The number.\n * @param precision Optional precision in number of digits.\n * @returns The integer with the given precision.\n */\nfunction toPreciseInteger(a: number, precision?: number): number {\n if (precision === undefined) {\n return a;\n }\n return Math.round(a * Math.pow(10, precision));\n}\n\n/**\n * Finds the first resource in the input array that matches the specified code and system.\n * @param resources - The array of resources to search.\n * @param code - The code to search for.\n * @param system - The system to search for.\n * @returns The first resource in the input array that matches the specified code and system, or undefined if no such resource is found.\n */\nexport function findResourceByCode(\n resources: ResourceWithCode[],\n code: CodeableConcept | string,\n system: string\n): ResourceWithCode | undefined {\n return resources.find((r) =>\n typeof code === 'string'\n ? getCodeBySystem(r.code || {}, system) === code\n : getCodeBySystem(r.code || {}, system) === getCodeBySystem(code, system)\n );\n}\n"],"names":[],"mappings":";;AAiCA;;;;AAIG;AACG,SAAU,eAAe,CAAqB,QAAW,EAAA;AAC7D,IAAA,MAAM,SAAS,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AAC/C,IAAA,MAAM,OAAO,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AAC3C,IAAA,OAAO,OAAO,KAAK,SAAS,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AACxE,CAAC;AAED;;;;AAIG;AACG,SAAU,kBAAkB,CAAC,QAAkB,EAAA;IACnD,OAAO,QAAQ,CAAC,YAAY,GAAG,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC;AACnD,CAAC;AAED;;;;AAIG;AACG,SAAU,SAAS,CAAC,SAAgC,EAAA;IACxD,OAAO,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;;;AAIG;AACG,SAAU,iBAAiB,CAAC,QAAkB,EAAA;AAClD,IAAA,QACE,QAAQ,CAAC,YAAY,KAAK,SAAS;QACnC,QAAQ,CAAC,YAAY,KAAK,cAAc;AACxC,QAAA,QAAQ,CAAC,YAAY,KAAK,eAAe,EACzC;AACJ,CAAC;AAED;;;;AAIG;AACG,SAAU,gBAAgB,CAAC,QAAkB,EAAA;AACjD,IAAA,IAAI,iBAAiB,CAAC,QAAQ,CAAC,EAAE;AAC/B,QAAA,MAAM,WAAW,GAAG,+BAA+B,CAAC,QAAQ,CAAC,CAAC;AAC9D,QAAA,IAAI,WAAW,EAAE;AACf,YAAA,OAAO,WAAW,CAAC;AACpB,SAAA;AACF,KAAA;AACD,IAAA,IAAI,QAAQ,CAAC,YAAY,KAAK,QAAQ,EAAE;AACtC,QAAA,MAAM,UAAU,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;AACpD,QAAA,IAAI,UAAU,EAAE;AACd,YAAA,OAAO,UAAU,CAAC;AACnB,SAAA;AACF,KAAA;AACD,IAAA,IAAI,QAAQ,CAAC,YAAY,KAAK,aAAa,EAAE;QAC3C,IAAI,MAAM,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE;AAC7C,YAAA,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;AAC3B,SAAA;AACF,KAAA;AACD,IAAA,IAAI,QAAQ,CAAC,YAAY,KAAK,MAAM,EAAE;QACpC,IAAI,QAAQ,CAAC,KAAK,EAAE;YAClB,OAAO,QAAQ,CAAC,KAAK,CAAC;AACvB,SAAA;AACF,KAAA;AACD,IAAA,IAAI,MAAM,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE;QAC5E,OAAO,QAAQ,CAAC,IAAI,CAAC;AACtB,KAAA;AACD,IAAA,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED;;;;AAIG;AACH,SAAS,+BAA+B,CAAC,QAAyB,EAAA;AAChE,IAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC;AAC5B,IAAA,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;AAC7B,QAAA,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAClC,KAAA;AACD,IAAA,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;AAIG;AACH,SAAS,sBAAsB,CAAC,MAAc,EAAA;AAC5C,IAAA,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC;AAChC,IAAA,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;AAC7B,QAAA,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACtB,KAAA;AACD,IAAA,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;AAIG;AACG,SAAU,WAAW,CAAC,QAAkB,EAAA;AAC5C,IAAA,IAAI,EAAE,OAAO,IAAI,QAAQ,CAAC,EAAE;AAC1B,QAAA,OAAO,SAAS,CAAC;AAClB,KAAA;AAED,IAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC7B,IAAI,CAAC,KAAK,EAAE;AACV,QAAA,OAAO,SAAS,CAAC;AAClB,KAAA;AAED,IAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACxB,QAAA,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE;AACrB,YAAA,MAAM,GAAG,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;AAChC,YAAA,IAAI,GAAG,EAAE;AACP,gBAAA,OAAO,GAAG,CAAC;AACZ,aAAA;AACF,SAAA;AACF,KAAA;AAAM,SAAA;AACL,QAAA,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAChC,KAAA;AAED,IAAA,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAiB,EAAA;AACzC,IAAA,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;QAC5E,OAAO,KAAK,CAAC,GAAG,CAAC;AAClB,KAAA;AACD,IAAA,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;AAMG;AACG,SAAU,eAAe,CAAC,IAAwB,EAAA;AACtD,IAAA,OAAO,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;AAC3C,CAAC;AAED;;;;;AAKG;AACa,SAAA,YAAY,CAC1B,YAAoB,EACpB,UAAmB,EAAA;AAEnB,IAAA,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC;IACzC,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAElC,IAAA,MAAM,OAAO,GAAG,UAAU,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IAC/D,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAEhC,IAAA,MAAM,SAAS,GAAG,SAAS,CAAC,cAAc,EAAE,CAAC;AAC7C,IAAA,MAAM,UAAU,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;AAC3C,IAAA,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC;AAExC,IAAA,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;AACzC,IAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;AACvC,IAAA,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;AAEpC,IAAA,IAAI,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;AAChC,IAAA,IAAI,QAAQ,GAAG,UAAU,KAAK,QAAQ,KAAK,UAAU,IAAI,MAAM,GAAG,QAAQ,CAAC,EAAE;AAC3E,QAAA,KAAK,EAAE,CAAC;AACT,KAAA;AAED,IAAA,IAAI,MAAM,GAAG,OAAO,GAAG,EAAE,GAAG,QAAQ,IAAI,SAAS,GAAG,EAAE,GAAG,UAAU,CAAC,CAAC;IACrE,IAAI,MAAM,GAAG,QAAQ,EAAE;AACrB,QAAA,MAAM,EAAE,CAAC;AACV,KAAA;AAED,IAAA,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AAE3F,IAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACjC,CAAC;AAED;;;;;;;;AAQG;AACa,SAAA,kBAAkB,CAAC,YAAoB,EAAE,UAAmB,EAAA;AAC1E,IAAA,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,YAAY,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IACvE,IAAI,KAAK,IAAI,CAAC,EAAE;AACd,QAAA,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;AAChD,KAAA;SAAM,IAAI,MAAM,IAAI,CAAC,EAAE;AACtB,QAAA,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;AACjD,KAAA;AAAM,SAAA;AACL,QAAA,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;AAC/C,KAAA;AACH,CAAC;AAED;;;;AAIG;AACG,SAAU,uBAAuB,CACrC,QAA+B,EAAA;IAE/B,MAAM,MAAM,GAAoD,EAAE,CAAC;AACnE,IAAA,6BAA6B,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACrD,IAAA,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;AAIG;AACH,SAAS,6BAA6B,CACpC,KAA8C,EAC9C,MAAuD,EAAA;AAEvD,IAAA,IAAI,KAAK,EAAE;AACT,QAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;AACxB,YAAA,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;AACxD,gBAAA,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtC,aAAA;AACD,YAAA,6BAA6B,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAClD,SAAA;AACF,KAAA;AACH,CAAC;AAED;;;;;;;;;AASG;AACa,SAAA,aAAa,CAAC,QAAkB,EAAE,MAAc,EAAA;AAC9D,IAAA,MAAM,WAAW,GAAI,QAAgB,CAAC,UAAmD,CAAC;IAC1F,IAAI,CAAC,WAAW,EAAE;AAChB,QAAA,OAAO,SAAS,CAAC;AAClB,KAAA;AACD,IAAA,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,GAAG,CAAC,WAAW,CAAC,CAAC;AACvE,IAAA,KAAK,MAAM,UAAU,IAAI,KAAK,EAAE;AAC9B,QAAA,IAAI,UAAU,CAAC,MAAM,KAAK,MAAM,EAAE;YAChC,OAAO,UAAU,CAAC,KAAK,CAAC;AACzB,SAAA;AACF,KAAA;AACD,IAAA,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;AAKG;SACa,iBAAiB,CAAC,QAAa,EAAE,GAAG,IAAc,EAAA;;IAEhE,IAAI,IAAI,GAAQ,QAAQ,CAAC;;AAGzB,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,EAAE,EAAE;QAC5C,IAAI,GAAI,IAAI,EAAE,SAAqC,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACrF,KAAA;IAED,OAAO,IAAI,EAAE,WAAiC,CAAC;AACjD,CAAC;AAED;;;;;AAKG;SACa,YAAY,CAAC,QAAa,EAAE,GAAG,IAAc,EAAA;;IAE3D,IAAI,IAAI,GAAQ,QAAQ,CAAC;;AAGzB,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,EAAE,EAAE;QAC5C,IAAI,GAAI,IAAI,EAAE,SAAqC,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACrF,KAAA;AAED,IAAA,OAAO,IAA6B,CAAC;AACvC,CAAC;AAED;;;;;;;;AAQG;AACa,SAAA,SAAS,CAAC,KAAU,EAAE,MAAgB,EAAA;AACpD,IAAA,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;;AAOG;AACH,SAAS,iBAAiB,CAAC,CAAS,EAAE,CAAM,EAAA;AAC1C,IAAA,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC;AACtD,CAAC;AAED;;;;AAIG;AACH,SAAS,UAAU,CAAC,CAAS,EAAA;IAC3B,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED;;;;AAIG;AACG,SAAU,OAAO,CAAC,CAAM,EAAA;AAC5B,IAAA,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,EAAE;AACjC,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;AACD,IAAA,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC;IACnB,OAAO,CAAC,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;AACzF,CAAC;AAED;;;;;;;AAOG;SACa,UAAU,CAAC,OAAgB,EAAE,OAAgB,EAAE,IAAa,EAAA;IAC1E,IAAI,OAAO,KAAK,OAAO,EAAE;AACvB,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;IACD,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;AACxC,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;IACD,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;AACxC,QAAA,OAAO,KAAK,CAAC;AACd,KAAA;AACD,IAAA,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AACpD,QAAA,OAAO,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC1C,KAAA;AACD,IAAA,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AACpD,QAAA,OAAO,KAAK,CAAC;AACd,KAAA;IACD,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE;QAC1C,OAAO,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AACjD,KAAA;IACD,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE;AAC1C,QAAA,OAAO,KAAK,CAAC;AACd,KAAA;AACD,IAAA,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,eAAe,CAAC,MAAiB,EAAE,MAAiB,EAAA;AAC3D,IAAA,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE;AACnC,QAAA,OAAO,KAAK,CAAC;AACd,KAAA;AACD,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACtC,QAAA,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AACrC,YAAA,OAAO,KAAK,CAAC;AACd,SAAA;AACF,KAAA;AACD,IAAA,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CACvB,OAAgC,EAChC,OAAgC,EAChC,IAAwB,EAAA;AAExB,IAAA,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,IAAI,IAAI,KAAK,MAAM,EAAE;AACnB,QAAA,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAC3B,QAAA,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AAC7B,QAAA,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AACzB,KAAA;AACD,IAAA,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE;AACxB,QAAA,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;AAC1B,QAAA,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE;AAChC,YAAA,OAAO,KAAK,CAAC;AACd,SAAA;AACF,KAAA;AACD,IAAA,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;AAYG;AACG,SAAU,SAAS,CAAI,KAAQ,EAAA;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAM,CAAC;AAChD,CAAC;AAED;;;;AAIG;AACG,SAAU,MAAM,CAAC,KAAa,EAAA;IAClC,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;AAC5D,CAAC;AAED;;;;AAIG;AACG,SAAU,QAAQ,CAAC,GAAY,EAAA;IACnC,OAAO,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,CAAC;AACjD,CAAC;AAED;;;;AAIG;AACG,SAAU,aAAa,CAAC,GAAU,EAAA;AACtC,IAAA,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;AACjD,CAAC;AAED;AACA;AACA,MAAM,SAAS,GAAa,EAAE,CAAC;AAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE;AAC5B,IAAA,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AACjD,CAAA;AAED;;;;;AAKG;AACG,SAAU,gBAAgB,CAAC,WAAwB,EAAA;AACvD,IAAA,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAa,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACjD,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACrC,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,KAAA;AACD,IAAA,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAED;;;;AAIG;AACG,SAAU,mBAAmB,CAAC,WAAwB,EAAA;AAC1D,IAAA,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAa,EAAE,CAAC;AAC5B,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACrC,QAAA,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3C,KAAA;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AACtC,CAAC;AAEK,SAAU,UAAU,CAAC,IAAY,EAAA;AACrC,IAAA,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC;AAEK,SAAU,WAAW,CAAC,CAAS,EAAA;AACnC,IAAA,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;AACxD,CAAC;AAED;;;;;AAKG;AACa,SAAA,eAAe,CAAC,OAAwB,EAAE,MAAc,EAAA;AACtE,IAAA,OAAO,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC;AAC3E,CAAC;AAED;;;;;AAKG;SACa,eAAe,CAAC,OAAwB,EAAE,MAAc,EAAE,IAAY,EAAA;AACpF,IAAA,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;AACnB,QAAA,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC;AACrB,KAAA;AACD,IAAA,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AAChE,IAAA,IAAI,MAAM,EAAE;AACV,QAAA,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;AACpB,KAAA;AAAM,SAAA;QACL,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AACxC,KAAA;AACH,CAAC;AAED;;;;;;;AAOG;AACG,SAAU,uBAAuB,CACrC,UAAiC,EACjC,OAAgB,EAChB,KAAa,EACb,QAAgD,EAAA;AAEhD,IAAA,OAAO,UAAU,CAAC,iBAAiB,EAAE,IAAI,CACvC,CAAC,QAAQ,KACP,iCAAiC,CAAC,QAAQ,EAAE,OAAO,CAAC;QACpD,+BAA+B,CAAC,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,mBAAmB,EAAE,gBAAgB,CAAC;SACjG,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAC7D,CAAC;AACJ,CAAC;AAED;;;;;;AAMG;SACa,6BAA6B,CAC3C,UAAiC,EACjC,OAAgB,EAChB,KAAe,EAAA;IAEf,OAAO,UAAU,CAAC,iBAAiB,EAAE,IAAI,CACvC,CAAC,QAAQ,KAAK,iCAAiC,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAmB,CAAC,CACnH,CAAC;AACJ,CAAC;AAED;;;;;AAKG;AACH,SAAS,iCAAiC,CACxC,QAAgD,EAChD,OAAgB,EAAA;AAEhB,IAAA,OAAO,gCAAgC,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,6BAA6B,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACjH,CAAC;AAED;;;;;AAKG;AACH,SAAS,gCAAgC,CAAC,QAAgD,EAAE,OAAgB,EAAA;AAC1G,IAAA,OAAO,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC;AAChE,CAAC;AAED;;;;;AAKG;AACH,SAAS,6BAA6B,CAAC,QAAgD,EAAE,OAAgB,EAAA;IACvG,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,SAAmB,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;AACtG,CAAC;AAED;;;;;;AAMG;AACH,SAAS,+BAA+B,CACtC,QAAgD,EAChD,KAAa,EACb,SAAkB,EAAA;AAElB,IAAA,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,IAAI,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;;AAMG;SACa,YAAY,CAAC,KAAa,EAAE,KAAY,EAAE,SAAkB,EAAA;IAC1E,QACE,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,KAAK,SAAS,IAAI,0BAA0B,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC;SAC/F,KAAK,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS,IAAI,uBAAuB,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,EAChG;AACJ,CAAC;AAED;;;;;AAKG;AACa,SAAA,YAAY,CAAC,CAAS,EAAE,SAAiB,EAAA;IACvD,OAAO,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;;AAMG;SACa,aAAa,CAAC,CAAS,EAAE,CAAS,EAAE,SAAkB,EAAA;AACpE,IAAA,OAAO,gBAAgB,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,gBAAgB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;AAMG;SACa,eAAe,CAAC,CAAS,EAAE,CAAS,EAAE,SAAkB,EAAA;AACtE,IAAA,OAAO,gBAAgB,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,gBAAgB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AACzE,CAAC;AAED;;;;;;AAMG;SACa,kBAAkB,CAAC,CAAS,EAAE,CAAS,EAAE,SAAkB,EAAA;AACzE,IAAA,OAAO,gBAAgB,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,gBAAgB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AACzE,CAAC;AAED;;;;;;AAMG;SACa,uBAAuB,CAAC,CAAS,EAAE,CAAS,EAAE,SAAkB,EAAA;AAC9E,IAAA,OAAO,gBAAgB,CAAC,CAAC,EAAE,SAAS,CAAC,IAAI,gBAAgB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;AAMG;SACa,0BAA0B,CAAC,CAAS,EAAE,CAAS,EAAE,SAAkB,EAAA;AACjF,IAAA,OAAO,gBAAgB,CAAC,CAAC,EAAE,SAAS,CAAC,IAAI,gBAAgB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;AAMG;AACH,SAAS,gBAAgB,CAAC,CAAS,EAAE,SAAkB,EAAA;IACrD,IAAI,SAAS,KAAK,SAAS,EAAE;AAC3B,QAAA,OAAO,CAAC,CAAC;AACV,KAAA;AACD,IAAA,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;AAMG;SACa,kBAAkB,CAChC,SAA6B,EAC7B,IAA8B,EAC9B,MAAc,EAAA;AAEd,IAAA,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,KACtB,OAAO,IAAI,KAAK,QAAQ;AACtB,UAAE,eAAe,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,MAAM,CAAC,KAAK,IAAI;AAChD,UAAE,eAAe,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,MAAM,CAAC,KAAK,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAC5E,CAAC;AACJ;;;;"}
@@ -6,7 +6,7 @@ import { Hl7Message } from './hl7';
6
6
  import { ReadablePromise } from './readablepromise';
7
7
  import { ClientStorage } from './storage';
8
8
  import { IndexedStructureDefinition } from './types';
9
- import { InviteResult, ProfileResource } from './utils';
9
+ import { ProfileResource } from './utils';
10
10
  export declare const MEDPLUM_VERSION: string;
11
11
  /**
12
12
  * The MedplumClientOptions interface defines configuration options for MedplumClient.
@@ -60,6 +60,18 @@ export interface MedplumClientOptions {
60
60
  * Client ID can be used for SMART-on-FHIR customization.
61
61
  */
62
62
  clientId?: string;
63
+ /**
64
+ * The client secret.
65
+ *
66
+ * Client secret can be used for FHIR Oauth Client Credential flows
67
+ */
68
+ clientSecret?: string;
69
+ /**
70
+ * The OAuth Access Token.
71
+ *
72
+ * Access Token used to connect to make request to FHIR servers
73
+ */
74
+ accessToken?: string;
63
75
  /**
64
76
  * Number of resources to store in the cache.
65
77
  *
@@ -414,8 +426,7 @@ export declare class MedplumClient extends EventTarget {
414
426
  private refreshToken?;
415
427
  private refreshPromise?;
416
428
  private profilePromise?;
417
- private profile?;
418
- private config?;
429
+ private sessionDetails?;
419
430
  private basicAuth?;
420
431
  constructor(options?: MedplumClientOptions);
421
432
  /**
@@ -426,6 +437,14 @@ export declare class MedplumClient extends EventTarget {
426
437
  * @returns The current base URL for all API requests.
427
438
  */
428
439
  getBaseUrl(): string;
440
+ /**
441
+ * Returns the current authorize URL.
442
+ * By default, this is set to `https://api.medplum.com/oauth2/authorize`.
443
+ * This can be overridden by setting the `authorizeUrl` option when creating the client.
444
+ * @category HTTP
445
+ * @returns The current authorize URL.
446
+ */
447
+ getAuthorizeUrl(): string;
429
448
  /**
430
449
  * Clears all auth state including local storage and session storage.
431
450
  * @category Authentication
@@ -1310,6 +1329,30 @@ export declare class MedplumClient extends EventTarget {
1310
1329
  * @category Authentication
1311
1330
  */
1312
1331
  isLoading(): boolean;
1332
+ /**
1333
+ * Returns true if the current user is authenticated as a super admin.
1334
+ * @returns True if the current user is authenticated as a super admin.
1335
+ * @category Authentication
1336
+ */
1337
+ isSuperAdmin(): boolean;
1338
+ /**
1339
+ * Returns true if the current user is authenticated as a project admin.
1340
+ * @returns True if the current user is authenticated as a project admin.
1341
+ * @category Authentication
1342
+ */
1343
+ isProjectAdmin(): boolean;
1344
+ /**
1345
+ * Returns the current project if available.
1346
+ * @returns The current project if available.
1347
+ * @category User Profile
1348
+ */
1349
+ getProject(): Project | undefined;
1350
+ /**
1351
+ * Returns the current project membership if available.
1352
+ * @returns The current project membership if available.
1353
+ * @category User Profile
1354
+ */
1355
+ getProjectMembership(): ProjectMembership | undefined;
1313
1356
  /**
1314
1357
  * Returns the current user profile resource if available.
1315
1358
  * This method does not wait for loading promises.
@@ -1330,6 +1373,12 @@ export declare class MedplumClient extends EventTarget {
1330
1373
  * @category User Profile
1331
1374
  */
1332
1375
  getUserConfiguration(): UserConfiguration | undefined;
1376
+ /**
1377
+ * Returns the current user access policy if available.
1378
+ * @returns The current user access policy if available.
1379
+ * @category User Profile
1380
+ */
1381
+ getAccessPolicy(): AccessPolicy | undefined;
1333
1382
  /**
1334
1383
  * Downloads the URL as a blob.
1335
1384
  * @category Read
@@ -1490,9 +1539,9 @@ export declare class MedplumClient extends EventTarget {
1490
1539
  * Invite a user to a project.
1491
1540
  * @param projectId The project ID.
1492
1541
  * @param body The InviteBody.
1493
- * @returns Promise that returns an invite result or an operation outcome.
1542
+ * @returns Promise that returns a project membership or an operation outcome.
1494
1543
  */
1495
- invite(projectId: string, body: InviteBody): Promise<InviteResult | OperationOutcome>;
1544
+ invite(projectId: string, body: InviteBody): Promise<ProjectMembership | OperationOutcome>;
1496
1545
  /**
1497
1546
  * Makes a POST request to the tokens endpoint.
1498
1547
  * See: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
@@ -1,13 +1,17 @@
1
1
  import { TypedValue } from '../types';
2
2
  import { Token } from './tokenize';
3
+ export interface AtomContext {
4
+ parent?: AtomContext;
5
+ variables: Record<string, TypedValue>;
6
+ }
3
7
  export interface Atom {
4
- eval(context: TypedValue[]): TypedValue[];
8
+ eval(context: AtomContext, input: TypedValue[]): TypedValue[];
5
9
  }
6
10
  export declare abstract class PrefixOperatorAtom implements Atom {
7
11
  readonly operator: string;
8
12
  readonly child: Atom;
9
13
  constructor(operator: string, child: Atom);
10
- abstract eval(context: TypedValue[]): TypedValue[];
14
+ abstract eval(context: AtomContext, input: TypedValue[]): TypedValue[];
11
15
  toString(): string;
12
16
  }
13
17
  export declare abstract class InfixOperatorAtom implements Atom {
@@ -15,7 +19,7 @@ export declare abstract class InfixOperatorAtom implements Atom {
15
19
  readonly left: Atom;
16
20
  readonly right: Atom;
17
21
  constructor(operator: string, left: Atom, right: Atom);
18
- abstract eval(context: TypedValue[]): TypedValue[];
22
+ abstract eval(context: AtomContext, input: TypedValue[]): TypedValue[];
19
23
  toString(): string;
20
24
  }
21
25
  export interface PrefixParselet {