UNPKG

@medplum/core

Version:

Medplum TS/JS Library

4 lines 1.14 MB
{ "version": 3, "sources": ["../../src/fhirlexer/parse.ts", "../../src/cache.ts", "../../src/constants.ts", "../../src/outcomes.ts", "../../src/base-schema.ts", "../../src/base-schema.json", "../../src/typeschema/types.ts", "../../src/typeschema/crawler.ts", "../../src/typeschema/validation.ts", "../../src/fhirpath/utils.ts", "../../src/utils.ts", "../../src/format.ts", "../../src/types.ts", "../../src/fhirpath/date.ts", "../../src/fhirpath/functions.ts", "../../src/fhirpath/atoms.ts", "../../src/fhirlexer/tokenize.ts", "../../src/fhirpath/tokenize.ts", "../../src/fhirpath/parse.ts", "../../src/search/ir.ts", "../../src/search/search.ts", "../../src/search/match.ts", "../../src/access.ts", "../../src/base64.ts", "../../src/crypto.ts", "../../src/bundle.ts", "../../src/contenttype.ts", "../../src/eventtarget.ts", "../../src/fhircast/index.ts", "../../src/jwt.ts", "../../src/keyvalue.ts", "../../src/readablepromise.ts", "../../src/storage.ts", "../../src/websockets/reconnecting-websocket.ts", "../../src/subscriptions/index.ts", "../../src/client.ts", "../../src/config.ts", "../../src/datasampler.ts", "../../src/elements-context.ts", "../../src/typeschema/slices.ts", "../../src/schema-crawler.ts", "../../src/default-values.ts", "../../src/fhirmapper/conceptmaptranslate.ts", "../../src/fhirmapper/tokenize.ts", "../../src/fhirmapper/parse.ts", "../../src/fhirmapper/transform.ts", "../../src/filebuilder.ts", "../../src/filter/tokenize.ts", "../../src/filter/types.ts", "../../src/filter/parse.ts", "../../src/hl7.ts", "../../src/logger.ts", "../../src/schema.ts", "../../src/search/details.ts", "../../src/sftp.ts", "../../src/sql-on-fhir/eval.ts", "../../src/version-utils.ts"], "sourcesContent": ["// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { TypedValue } from '../types';\nimport { Token } from './tokenize';\n\nexport interface AtomContext {\n parent?: AtomContext;\n variables: Record<string, TypedValue>;\n}\nexport interface Atom {\n eval(context: AtomContext, input: TypedValue[]): TypedValue[];\n\n toString(): string;\n}\n\nexport abstract class PrefixOperatorAtom implements Atom {\n readonly operator: string;\n readonly child: Atom;\n\n constructor(operator: string, child: Atom) {\n this.operator = operator;\n this.child = child;\n }\n\n abstract eval(context: AtomContext, input: TypedValue[]): TypedValue[];\n\n toString(): string {\n return `${this.operator}(${this.child.toString()})`;\n }\n}\n\nexport abstract class InfixOperatorAtom implements Atom {\n readonly operator: string;\n readonly left: Atom;\n readonly right: Atom;\n\n constructor(operator: string, left: Atom, right: Atom) {\n this.operator = operator;\n this.left = left;\n this.right = right;\n }\n\n abstract eval(context: AtomContext, input: TypedValue[]): TypedValue[];\n\n toString(): string {\n return `(${this.left.toString()} ${this.operator} ${this.right.toString()})`;\n }\n}\n\nexport interface PrefixParselet {\n parse(parser: Parser, token: Token): Atom;\n}\n\nexport interface InfixParselet {\n precedence: number;\n parse?(parser: Parser, left: Atom, token: Token): Atom;\n}\n\nexport class ParserBuilder {\n private readonly prefixParselets: Record<string, PrefixParselet> = {};\n private readonly infixParselets: Record<string, InfixParselet> = {};\n\n public registerInfix(tokenType: string, parselet: InfixParselet): this {\n this.infixParselets[tokenType] = parselet;\n return this;\n }\n\n public registerPrefix(tokenType: string, parselet: PrefixParselet): this {\n this.prefixParselets[tokenType] = parselet;\n return this;\n }\n\n public prefix(tokenType: string, precedence: number, builder: (token: Token, right: Atom) => Atom): this {\n return this.registerPrefix(tokenType, {\n parse(parser, token) {\n const right = parser.consumeAndParse(precedence);\n return builder(token, right);\n },\n });\n }\n\n public infixLeft(\n tokenType: string,\n precedence: number,\n builder: (left: Atom, token: Token, right: Atom) => Atom\n ): this {\n return this.registerInfix(tokenType, {\n parse(parser, left, token) {\n const right = parser.consumeAndParse(precedence);\n return builder(left, token, right);\n },\n precedence,\n });\n }\n\n public construct(input: Token[]): Parser {\n return new Parser(input, this.prefixParselets, this.infixParselets);\n }\n}\n\nexport class Parser {\n private tokens: Token[];\n private readonly prefixParselets: Record<string, PrefixParselet>;\n private readonly infixParselets: Record<string, InfixParselet>;\n\n constructor(\n tokens: Token[],\n prefixParselets: Record<string, PrefixParselet>,\n infixParselets: Record<string, InfixParselet>\n ) {\n this.tokens = tokens;\n this.prefixParselets = prefixParselets;\n this.infixParselets = infixParselets;\n }\n\n hasMore(): boolean {\n return this.tokens.length > 0;\n }\n\n match(expected: string): boolean {\n const token = this.peek();\n if (token?.id !== expected) {\n return false;\n }\n\n this.consume();\n return true;\n }\n\n consumeAndParse(precedence = Infinity): Atom {\n const token = this.consume();\n const prefix = this.prefixParselets[token.id];\n if (!prefix) {\n throw Error(\n `Parse error at \"${token.value}\" (line ${token.line}, column ${token.column}). No matching prefix parselet.`\n );\n }\n\n let left = prefix.parse(this, token);\n\n while (precedence > this.getPrecedence()) {\n const next = this.consume();\n const infix = this.getInfixParselet(next) as InfixParselet;\n left = (infix.parse as (parser: Parser, left: Atom, token: Token) => Atom)(this, left, next);\n }\n\n return left;\n }\n\n getPrecedence(): number {\n const nextToken = this.peek();\n if (!nextToken) {\n return Infinity;\n }\n const parser = this.getInfixParselet(nextToken);\n if (parser) {\n return parser.precedence;\n }\n return Infinity;\n }\n\n consume(expectedId?: string, expectedValue?: string): Token {\n if (!this.tokens.length) {\n throw Error('Cant consume unknown more tokens.');\n }\n if (expectedId && this.peek()?.id !== expectedId) {\n const actual = this.peek() as Token;\n throw Error(\n `Expected ${expectedId} but got \"${actual.id}\" (${actual.value}) at line ${actual.line} column ${actual.column}.`\n );\n }\n if (expectedValue && this.peek()?.value !== expectedValue) {\n const actual = this.peek() as Token;\n throw Error(\n `Expected \"${expectedValue}\" but got \"${actual.value}\" at line ${actual.line} column ${actual.column}.`\n );\n }\n return this.tokens.shift() as Token;\n }\n\n peek(): Token | undefined {\n return this.tokens.length > 0 ? this.tokens[0] : undefined;\n }\n\n removeComments(): void {\n this.tokens = this.tokens.filter((t) => t.id !== 'Comment');\n }\n\n getInfixParselet(token: Token): InfixParselet | undefined {\n return this.infixParselets[token.id === 'Symbol' ? token.value : token.id];\n }\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * LRU cache (least recently used)\n * Source: https://stackoverflow.com/a/46432113\n */\n\nexport class LRUCache<T> {\n private readonly max: number;\n private readonly cache: Map<string, T>;\n\n constructor(max = 10) {\n this.max = max;\n this.cache = new Map();\n }\n\n /**\n * Deletes all values from the cache.\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Returns the value for the given key.\n * @param key - The key to retrieve.\n * @returns The value if found; undefined otherwise.\n */\n get(key: string): T | undefined {\n const item = this.cache.get(key);\n if (item) {\n this.cache.delete(key);\n this.cache.set(key, item);\n }\n return item;\n }\n\n /**\n * Sets the value for the given key.\n * @param key - The key to set.\n * @param val - The value to set.\n */\n set(key: string, val: T): void {\n if (this.cache.has(key)) {\n this.cache.delete(key);\n } else if (this.cache.size >= this.max) {\n this.cache.delete(this.first());\n }\n this.cache.set(key, val);\n }\n\n /**\n * Deletes the value for the given key.\n * @param key - The key to delete.\n */\n delete(key: string): void {\n this.cache.delete(key);\n }\n\n /**\n * Returns the list of all keys in the cache.\n * @returns The array of keys in the cache.\n */\n keys(): IterableIterator<string> {\n return this.cache.keys();\n }\n\n private first(): string {\n // This works because the Map class maintains ordered keys.\n return this.cache.keys().next().value as string;\n }\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\n\n// Common terminology systems, taken from https://terminology.hl7.org/external_terminologies.html\nexport const UCUM = 'http://unitsofmeasure.org';\nexport const LOINC = 'http://loinc.org';\nexport const SNOMED = 'http://snomed.info/sct';\nexport const RXNORM = 'http://www.nlm.nih.gov/research/umls/rxnorm';\nexport const CPT = 'http://www.ama-assn.org/go/cpt';\nexport const ICD10 = 'http://hl7.org/fhir/sid/icd-10';\nexport const NDC = 'http://hl7.org/fhir/sid/ndc';\n\n// common http-based origins useful for avoiding false-positives about preferring https over http,\n// e.g. https://rules.sonarsource.com/javascript/type/Security%20Hotspot/RSPEC-5332/\nexport const HTTP_HL7_ORG = 'http://hl7.org';\nexport const HTTP_TERMINOLOGY_HL7_ORG = 'http://terminology.hl7.org';\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { OperationOutcome, OperationOutcomeIssue } from '@medplum/fhirtypes';\nimport { Constraint } from './typeschema/types';\n\nconst OK_ID = 'ok';\nconst CREATED_ID = 'created';\nconst GONE_ID = 'gone';\nconst NOT_MODIFIED_ID = 'not-modified';\nconst FOUND_ID = 'found';\nconst NOT_FOUND_ID = 'not-found';\nconst CONFLICT_ID = 'conflict';\nconst UNAUTHORIZED_ID = 'unauthorized';\nconst FORBIDDEN_ID = 'forbidden';\nconst PRECONDITION_FAILED_ID = 'precondition-failed';\nconst MULTIPLE_MATCHES_ID = 'multiple-matches';\nconst TOO_MANY_REQUESTS_ID = 'too-many-requests';\nconst ACCEPTED_ID = 'accepted';\nconst SERVER_TIMEOUT_ID = 'server-timeout';\nconst BUSINESS_RULE = 'business-rule';\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 unauthorizedTokenExpired: OperationOutcome = {\n ...unauthorized,\n issue: [\n ...unauthorized.issue,\n {\n severity: 'error',\n code: 'expired',\n details: {\n text: 'Token expired',\n },\n },\n ],\n};\n\nexport const unauthorizedTokenAudience: OperationOutcome = {\n ...unauthorized,\n issue: [\n ...unauthorized.issue,\n {\n severity: 'error',\n code: 'invalid',\n details: {\n text: 'Token not issued for this audience',\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 preconditionFailed: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: PRECONDITION_FAILED_ID,\n issue: [\n {\n severity: 'error',\n code: 'processing',\n details: {\n text: 'Precondition Failed',\n },\n },\n ],\n};\n\nexport const multipleMatches: OperationOutcome = {\n resourceType: 'OperationOutcome',\n id: MULTIPLE_MATCHES_ID,\n issue: [\n {\n severity: 'error',\n code: 'multiple-matches',\n details: {\n text: 'Multiple resources found matching condition',\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 function accepted(location: string): OperationOutcome {\n return {\n resourceType: 'OperationOutcome',\n id: ACCEPTED_ID,\n issue: [\n {\n severity: 'information',\n code: 'informational',\n details: {\n text: 'Accepted',\n },\n diagnostics: location,\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 conflict(details: string, code?: string): OperationOutcome {\n return {\n resourceType: 'OperationOutcome',\n id: CONFLICT_ID,\n issue: [\n {\n severity: 'error',\n code: 'conflict',\n details: {\n coding: code ? [{ code }] : undefined,\n text: details,\n },\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 serverError(err: Error): OperationOutcome {\n return {\n resourceType: 'OperationOutcome',\n issue: [\n {\n severity: 'error',\n code: 'exception',\n details: {\n text: 'Internal server error',\n },\n diagnostics: err.toString(),\n },\n ],\n };\n}\n\nexport function serverTimeout(msg?: string): OperationOutcome {\n return {\n resourceType: 'OperationOutcome',\n id: SERVER_TIMEOUT_ID,\n issue: [\n {\n severity: 'error',\n code: 'timeout',\n details: {\n text: msg ?? 'Server timeout',\n },\n },\n ],\n };\n}\n\nexport function redirect(url: URL): OperationOutcome {\n const urlStr = url.toString();\n return {\n resourceType: 'OperationOutcome',\n id: FOUND_ID,\n issue: [\n {\n severity: 'information',\n code: 'informational',\n details: {\n coding: [{ system: 'urn:ietf:rfc:3986', code: urlStr }],\n text: 'Redirect to ' + urlStr,\n },\n },\n ],\n };\n}\n\nexport function businessRule(key: string, message: string): OperationOutcome {\n return {\n resourceType: 'OperationOutcome',\n id: BUSINESS_RULE,\n issue: [\n {\n severity: 'error',\n code: 'business-rule',\n details: { id: key, text: message },\n },\n ],\n };\n}\n\n/**\n * Returns true if the input is an Error object.\n * This should be replaced with `Error.isError` when it is more widely supported.\n * See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/isError\n * @param value - The candidate value.\n * @returns True if the input is an Error object.\n */\nexport function isError(value: unknown): value is Error {\n // Quick type check\n if (!value || typeof value !== 'object') {\n return false;\n }\n\n // Fast path for same-realm errors using instanceof\n if (value instanceof Error) {\n return true;\n }\n\n // Handle DOMException case\n if (typeof DOMException !== 'undefined' && value instanceof DOMException) {\n return true;\n }\n\n // Cross-realm check using toString (most reliable method)\n return Object.prototype.toString.call(value) === '[object Error]';\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 (\n outcome.id === OK_ID || outcome.id === CREATED_ID || outcome.id === NOT_MODIFIED_ID || outcome.id === ACCEPTED_ID\n );\n}\n\nexport function isCreated(outcome: OperationOutcome): boolean {\n return outcome.id === CREATED_ID;\n}\n\nexport function isAccepted(outcome: OperationOutcome): boolean {\n return outcome.id === ACCEPTED_ID;\n}\n\nexport function isRedirect(outcome: OperationOutcome): boolean {\n return outcome.id === FOUND_ID;\n}\n\nexport function isNotFound(outcome: OperationOutcome): boolean {\n return outcome.id === NOT_FOUND_ID;\n}\n\nexport function isConflict(outcome: OperationOutcome): boolean {\n return outcome.id === CONFLICT_ID;\n}\n\nexport function isGone(outcome: OperationOutcome): boolean {\n return outcome.id === GONE_ID;\n}\n\nexport function isUnauthenticated(outcome: OperationOutcome): boolean {\n return outcome.id === UNAUTHORIZED_ID;\n}\n\nexport function getStatus(outcome: OperationOutcome): number {\n switch (outcome.id) {\n case OK_ID:\n return 200;\n case CREATED_ID:\n return 201;\n case ACCEPTED_ID:\n return 202;\n case FOUND_ID:\n return 302;\n case NOT_MODIFIED_ID:\n return 304;\n case UNAUTHORIZED_ID:\n return 401;\n case FORBIDDEN_ID:\n return 403;\n case NOT_FOUND_ID:\n return 404;\n case CONFLICT_ID:\n return 409;\n case GONE_ID:\n return 410;\n case PRECONDITION_FAILED_ID:\n case MULTIPLE_MATCHES_ID:\n return 412;\n case BUSINESS_RULE:\n return 422;\n case TOO_MANY_REQUESTS_ID:\n return 429;\n case SERVER_TIMEOUT_ID:\n return 504;\n default:\n return outcome.issue?.[0]?.code === 'exception' ? 500 : 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 (isError(error)) {\n return error.message;\n }\n if (isOperationOutcome(error)) {\n return operationOutcomeToString(error);\n }\n if (typeof error === 'object' && 'code' in error && typeof error.code === 'string') {\n return error.code;\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;\n if (issue.details?.text) {\n if (issue.diagnostics) {\n issueStr = `${issue.details.text} (${issue.diagnostics})`;\n } else {\n issueStr = issue.details.text;\n }\n } else if (issue.diagnostics) {\n issueStr = issue.diagnostics;\n } else {\n issueStr = 'Unknown error';\n }\n if (issue.expression?.length) {\n issueStr += ` (${issue.expression.join(', ')})`;\n }\n return issueStr;\n}\n\nexport type IssueSeverity = 'error' | 'fatal' | 'warning' | 'information';\nexport type IssueType = 'structure' | 'invariant' | 'processing';\n\nexport function createOperationOutcomeIssue(\n severity: IssueSeverity,\n code: IssueType,\n message: string,\n path: string,\n data?: Record<string, any>\n): OperationOutcomeIssue {\n const issue: OperationOutcomeIssue = {\n severity,\n code,\n details: {\n text: message,\n },\n expression: [path],\n };\n if (data) {\n issue.diagnostics = JSON.stringify(data);\n }\n return issue;\n}\n\nexport function createStructureIssue(expression: string, details: string): OperationOutcomeIssue {\n return createOperationOutcomeIssue('error', 'structure', details, expression);\n}\n\nexport function createConstraintIssue(expression: string, constraint: Constraint): OperationOutcomeIssue {\n return createOperationOutcomeIssue(\n 'error',\n 'invariant',\n `Constraint ${constraint.key} not met: ${constraint.description}`,\n expression,\n {\n fhirpath: constraint.expression,\n }\n );\n}\n\nexport function createProcessingIssue(\n expression: string,\n message: string,\n err: Error,\n data?: Record<string, any>\n): OperationOutcomeIssue {\n return createOperationOutcomeIssue('error', 'processing', message, expression, { ...data, error: err });\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { InternalSchemaElement, InternalTypeSchema } from './typeschema/types';\n\nexport type BaseSchema = Record<string, { elements: Record<string, Partial<InternalSchemaElement>> }>;\n\nconst normalizedTypes: Record<string, string> = {\n 'http://hl7.org/fhirpath/System.String': 'string',\n};\n\nexport function compressElement(element: InternalSchemaElement): Partial<InternalSchemaElement> {\n // For each property, only keep \"min\", \"max\", and \"type\"\n // Only keep \"min\" if not 0\n // Only keep \"max\" if not 1\n const outputPropertySchema: Partial<InternalSchemaElement> = {};\n if (element.min !== 0) {\n outputPropertySchema.min = element.min;\n }\n\n if (element.max !== 1 && Number.isFinite(element.max)) {\n outputPropertySchema.max = element.max;\n } else if (element.max === Number.POSITIVE_INFINITY) {\n outputPropertySchema.max = Number.MAX_SAFE_INTEGER;\n }\n\n outputPropertySchema.type = element.type?.map((t) => ({\n ...t,\n extension: undefined,\n code: normalizedTypes[t.code] ?? t.code,\n }));\n return outputPropertySchema;\n}\n\nexport function inflateElement(path: string, partial: Partial<InternalSchemaElement>): InternalSchemaElement {\n const max = partial.max && partial.max === Number.MAX_SAFE_INTEGER ? Number.POSITIVE_INFINITY : partial.max;\n return {\n path,\n description: '',\n type: partial.type ?? [],\n min: partial.min ?? 0,\n max: max ?? 1,\n isArray: !!max && max > 1,\n constraints: [],\n };\n}\n\nexport type DataTypesMap = { [type: string]: InternalTypeSchema };\n\nexport function inflateBaseSchema(base: BaseSchema): DataTypesMap {\n const output: DataTypesMap = Object.create(null);\n for (const [key, schema] of Object.entries(base)) {\n output[key] = {\n name: key,\n type: key,\n path: key,\n elements: Object.fromEntries(\n Object.entries(schema.elements).map(([property, partial]) => [property, inflateElement(property, partial)])\n ),\n constraints: [],\n innerTypes: [],\n };\n }\n return output;\n}\n", "{\n \"Element\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n }\n }\n },\n \"BackboneElement\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"modifierExtension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n }\n }\n },\n \"Address\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"use\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"type\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"text\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"line\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"city\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"district\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"state\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"postalCode\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"country\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"period\": {\n \"type\": [\n {\n \"code\": \"Period\"\n }\n ]\n }\n }\n },\n \"Age\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"value\": {\n \"type\": [\n {\n \"code\": \"decimal\"\n }\n ]\n },\n \"comparator\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"unit\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"system\": {\n \"type\": [\n {\n \"code\": \"uri\"\n }\n ]\n },\n \"code\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n }\n }\n },\n \"Annotation\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"author[x]\": {\n \"type\": [\n {\n \"code\": \"Reference\",\n \"targetProfile\": [\n \"http://hl7.org/fhir/StructureDefinition/Practitioner\",\n \"http://hl7.org/fhir/StructureDefinition/Patient\",\n \"http://hl7.org/fhir/StructureDefinition/RelatedPerson\",\n \"http://hl7.org/fhir/StructureDefinition/Organization\"\n ]\n },\n {\n \"code\": \"string\"\n }\n ]\n },\n \"time\": {\n \"type\": [\n {\n \"code\": \"dateTime\"\n }\n ]\n },\n \"text\": {\n \"min\": 1,\n \"type\": [\n {\n \"code\": \"markdown\"\n }\n ]\n }\n }\n },\n \"Attachment\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"contentType\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"language\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"data\": {\n \"type\": [\n {\n \"code\": \"base64Binary\"\n }\n ]\n },\n \"url\": {\n \"type\": [\n {\n \"code\": \"url\"\n }\n ]\n },\n \"size\": {\n \"type\": [\n {\n \"code\": \"unsignedInt\"\n }\n ]\n },\n \"hash\": {\n \"type\": [\n {\n \"code\": \"base64Binary\"\n }\n ]\n },\n \"title\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"creation\": {\n \"type\": [\n {\n \"code\": \"dateTime\"\n }\n ]\n }\n }\n },\n \"CodeableConcept\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"coding\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Coding\"\n }\n ]\n },\n \"text\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n }\n }\n },\n \"Coding\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"system\": {\n \"type\": [\n {\n \"code\": \"uri\"\n }\n ]\n },\n \"version\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"code\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"display\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"userSelected\": {\n \"type\": [\n {\n \"code\": \"boolean\"\n }\n ]\n }\n }\n },\n \"ContactDetail\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"name\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"telecom\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"ContactPoint\"\n }\n ]\n }\n }\n },\n \"ContactPoint\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"system\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"value\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"use\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"rank\": {\n \"type\": [\n {\n \"code\": \"positiveInt\"\n }\n ]\n },\n \"period\": {\n \"type\": [\n {\n \"code\": \"Period\"\n }\n ]\n }\n }\n },\n \"Contributor\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"type\": {\n \"min\": 1,\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"name\": {\n \"min\": 1,\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"contact\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"ContactDetail\"\n }\n ]\n }\n }\n },\n \"Count\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"value\": {\n \"type\": [\n {\n \"code\": \"decimal\"\n }\n ]\n },\n \"comparator\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"unit\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"system\": {\n \"type\": [\n {\n \"code\": \"uri\"\n }\n ]\n },\n \"code\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n }\n }\n },\n \"DataRequirement\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"type\": {\n \"min\": 1,\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"profile\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"canonical\",\n \"targetProfile\": [\"http://hl7.org/fhir/StructureDefinition/StructureDefinition\"]\n }\n ]\n },\n \"subject[x]\": {\n \"type\": [\n {\n \"code\": \"CodeableConcept\"\n },\n {\n \"code\": \"Reference\",\n \"targetProfile\": [\"http://hl7.org/fhir/StructureDefinition/Group\"]\n }\n ]\n },\n \"mustSupport\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"codeFilter\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"DataRequirementCodeFilter\"\n }\n ]\n },\n \"dateFilter\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"DataRequirementDateFilter\"\n }\n ]\n },\n \"limit\": {\n \"type\": [\n {\n \"code\": \"positiveInt\"\n }\n ]\n },\n \"sort\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"DataRequirementSort\"\n }\n ]\n }\n }\n },\n \"DataRequirementCodeFilter\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"path\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"searchParam\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"valueSet\": {\n \"type\": [\n {\n \"code\": \"canonical\",\n \"targetProfile\": [\"http://hl7.org/fhir/StructureDefinition/ValueSet\"]\n }\n ]\n },\n \"code\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Coding\"\n }\n ]\n }\n }\n },\n \"DataRequirementDateFilter\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"path\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"searchParam\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"value[x]\": {\n \"type\": [\n {\n \"code\": \"dateTime\"\n },\n {\n \"code\": \"Period\"\n },\n {\n \"code\": \"Duration\"\n }\n ]\n }\n }\n },\n \"DataRequirementSort\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"path\": {\n \"min\": 1,\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"direction\": {\n \"min\": 1,\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n }\n }\n },\n \"Distance\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"value\": {\n \"type\": [\n {\n \"code\": \"decimal\"\n }\n ]\n },\n \"comparator\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"unit\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"system\": {\n \"type\": [\n {\n \"code\": \"uri\"\n }\n ]\n },\n \"code\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n }\n }\n },\n \"Dosage\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"modifierExtension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"sequence\": {\n \"type\": [\n {\n \"code\": \"integer\"\n }\n ]\n },\n \"text\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"additionalInstruction\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"CodeableConcept\"\n }\n ]\n },\n \"patientInstruction\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"timing\": {\n \"type\": [\n {\n \"code\": \"Timing\"\n }\n ]\n },\n \"asNeeded[x]\": {\n \"type\": [\n {\n \"code\": \"boolean\"\n },\n {\n \"code\": \"CodeableConcept\"\n }\n ]\n },\n \"site\": {\n \"type\": [\n {\n \"code\": \"CodeableConcept\"\n }\n ]\n },\n \"route\": {\n \"type\": [\n {\n \"code\": \"CodeableConcept\"\n }\n ]\n },\n \"method\": {\n \"type\": [\n {\n \"code\": \"CodeableConcept\"\n }\n ]\n },\n \"doseAndRate\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"DosageDoseAndRate\"\n }\n ]\n },\n \"maxDosePerPeriod\": {\n \"type\": [\n {\n \"code\": \"Ratio\"\n }\n ]\n },\n \"maxDosePerAdministration\": {\n \"type\": [\n {\n \"code\": \"Quantity\",\n \"profile\": [\"http://hl7.org/fhir/StructureDefinition/SimpleQuantity\"]\n }\n ]\n },\n \"maxDosePerLifetime\": {\n \"type\": [\n {\n \"code\": \"Quantity\",\n \"profile\": [\"http://hl7.org/fhir/StructureDefinition/SimpleQuantity\"]\n }\n ]\n }\n }\n },\n \"DosageDoseAndRate\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"type\": {\n \"type\": [\n {\n \"code\": \"CodeableConcept\"\n }\n ]\n },\n \"dose[x]\": {\n \"type\": [\n {\n \"code\": \"Range\"\n },\n {\n \"code\": \"Quantity\",\n \"profile\": [\"http://hl7.org/fhir/StructureDefinition/SimpleQuantity\"]\n }\n ]\n },\n \"rate[x]\": {\n \"type\": [\n {\n \"code\": \"Ratio\"\n },\n {\n \"code\": \"Range\"\n },\n {\n \"code\": \"Quantity\",\n \"profile\": [\"http://hl7.org/fhir/StructureDefinition/SimpleQuantity\"]\n }\n ]\n }\n }\n },\n \"Duration\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"value\": {\n \"type\": [\n {\n \"code\": \"decimal\"\n }\n ]\n },\n \"comparator\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"unit\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"system\": {\n \"type\": [\n {\n \"code\": \"uri\"\n }\n ]\n },\n \"code\": {\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n }\n }\n },\n \"ElementDefinition\": {\n \"elements\": {\n \"id\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"extension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"modifierExtension\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Extension\"\n }\n ]\n },\n \"path\": {\n \"min\": 1,\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"representation\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"code\"\n }\n ]\n },\n \"sliceName\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"sliceIsConstraining\": {\n \"type\": [\n {\n \"code\": \"boolean\"\n }\n ]\n },\n \"label\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"code\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"Coding\"\n }\n ]\n },\n \"slicing\": {\n \"type\": [\n {\n \"code\": \"ElementDefinitionSlicing\"\n }\n ]\n },\n \"short\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"definition\": {\n \"type\": [\n {\n \"code\": \"markdown\"\n }\n ]\n },\n \"comment\": {\n \"type\": [\n {\n \"code\": \"markdown\"\n }\n ]\n },\n \"requirements\": {\n \"type\": [\n {\n \"code\": \"markdown\"\n }\n ]\n },\n \"alias\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"min\": {\n \"type\": [\n {\n \"code\": \"unsignedInt\"\n }\n ]\n },\n \"max\": {\n \"type\": [\n {\n \"code\": \"string\"\n }\n ]\n },\n \"base\": {\n \"type\": [\n {\n \"code\": \"ElementDefinitionBase\"\n }\n ]\n },\n \"contentReference\": {\n \"type\": [\n {\n \"code\": \"uri\"\n }\n ]\n },\n \"type\": {\n \"max\": 9007199254740991,\n \"type\": [\n {\n \"code\": \"ElementDefinitionType\"\n }\n ]\n },\n \"defaultValue[x]\": {\n \"type\": [\n {\n \"code\": \"base64Binary\"\n },\n {\n \"code\": \"boolean\"\n },\n {\n \"code\": \"canonical\"\n },\n {\n \"code\": \"code\"\n },\n {\n \"code\": \"date\"\n },\n {\n \"code\": \"dateTime\"\n },\n {\n \"code\": \"decimal\"\n },\n {\n \"code\": \"id\"\n },\n {\n