@medplum/core 2.0.19 → 2.0.21

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.
@@ -51,26 +51,28 @@ function buildSearchParamterDetails(resourceType, searchParam) {
51
51
  // In the future, explore returning multiple column definitions
52
52
  return { columnName, type: SearchParameterType.TEXT };
53
53
  }
54
- const defaultType = getSearchParameterType(searchParam);
55
54
  let baseType = resourceType;
56
55
  let elementDefinition = undefined;
57
56
  let propertyType = undefined;
58
57
  let array = false;
59
58
  for (let i = 1; i < expression.length; i++) {
60
- const propertyName = expression[i];
59
+ let propertyName = expression[i];
60
+ let hasArrayIndex = false;
61
+ const arrayIndexMatch = /\[\d+\]$/.exec(propertyName);
62
+ if (arrayIndexMatch) {
63
+ propertyName = propertyName.substring(0, propertyName.length - arrayIndexMatch[0].length);
64
+ hasArrayIndex = true;
65
+ }
61
66
  elementDefinition = getElementDefinition(baseType, propertyName);
62
67
  if (!elementDefinition) {
63
68
  throw new Error(`Element definition not found for ${resourceType} ${searchParam.code}`);
64
69
  }
65
- if (elementDefinition.max !== '0' && elementDefinition.max !== '1') {
70
+ if (elementDefinition.max !== '0' && elementDefinition.max !== '1' && !hasArrayIndex) {
66
71
  array = true;
67
72
  }
73
+ // "code" is only missing when using "contentReference"
74
+ // "contentReference" is handled above in "getElementDefinition"
68
75
  propertyType = elementDefinition.type?.[0].code;
69
- if (!propertyType) {
70
- // This happens when one of parent properties uses contentReference
71
- // In the future, explore following the reference
72
- return { columnName, type: defaultType, array };
73
- }
74
76
  if (i < expression.length - 1) {
75
77
  if (isBackboneElement(propertyType)) {
76
78
  baseType = buildTypeName(elementDefinition.path?.split('.'));
@@ -150,9 +152,6 @@ function simplifyExpression(input) {
150
152
  if (result.startsWith('(') && result.endsWith(')')) {
151
153
  result = result.substring(1, result.length - 1);
152
154
  }
153
- if (result.includes('[0]')) {
154
- result = result.replaceAll('[0]', '');
155
- }
156
155
  const stopStrings = [' != ', ' as ', '.as(', '.exists(', '.resolve(', '.where('];
157
156
  for (const stopString of stopStrings) {
158
157
  if (result.includes(stopString)) {
@@ -1 +1 @@
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 *\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 const defaultType = getSearchParameterType(searchParam);\n let baseType = resourceType;\n let elementDefinition = undefined;\n let propertyType = undefined;\n let array = false;\n\n for (let i = 1; i < expression.length; i++) {\n const propertyName = expression[i];\n elementDefinition = 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') {\n array = true;\n }\n\n propertyType = elementDefinition.type?.[0].code;\n if (!propertyType) {\n // This happens when one of parent properties uses contentReference\n // In the future, explore following the reference\n return { columnName, type: defaultType, array };\n }\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 if (result.includes('[0]')) {\n result = result.replaceAll('[0]', '');\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 { 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 *\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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"}
@@ -146,7 +146,7 @@ function parseKeyValue(searchRequest, key, value) {
146
146
  searchRequest.total = value;
147
147
  break;
148
148
  case '_summary':
149
- searchRequest.total = 'estimate';
149
+ searchRequest.total = 'accurate';
150
150
  searchRequest.count = 0;
151
151
  break;
152
152
  case '_include': {
@@ -1 +1 @@
1
- {"version":3,"file":"search.mjs","sources":["../../../src/search/search.ts"],"sourcesContent":["import { Resource, ResourceType, SearchParameter } from '@medplum/fhirtypes';\nimport { globalSchema } from '../types';\nimport { OperationOutcomeError, badRequest } from '../outcomes';\n\nexport const DEFAULT_SEARCH_COUNT = 20;\n\nexport interface SearchRequest<T extends Resource = Resource> {\n readonly resourceType: T['resourceType'];\n filters?: Filter[];\n sortRules?: SortRule[];\n offset?: number;\n count?: number;\n fields?: string[];\n name?: string;\n total?: 'none' | 'estimate' | 'accurate';\n include?: IncludeTarget[];\n revInclude?: IncludeTarget[];\n}\n\nexport interface Filter {\n code: string;\n operator: Operator;\n value: string;\n unitSystem?: string;\n unitCode?: string;\n}\n\nexport interface SortRule {\n code: string;\n descending?: boolean;\n}\n\nexport interface IncludeTarget {\n resourceType: string;\n searchParam: string;\n targetType?: string;\n modifier?: string;\n}\n\n/**\n * Search operators.\n * These operators represent \"modifiers\" and \"prefixes\" in FHIR search.\n * See: https://www.hl7.org/fhir/search.html\n */\nexport enum Operator {\n EQUALS = 'eq',\n NOT_EQUALS = 'ne',\n\n // Numbers\n GREATER_THAN = 'gt',\n LESS_THAN = 'lt',\n GREATER_THAN_OR_EQUALS = 'ge',\n LESS_THAN_OR_EQUALS = 'le',\n\n // Dates\n STARTS_AFTER = 'sa',\n ENDS_BEFORE = 'eb',\n APPROXIMATELY = 'ap',\n\n // String\n CONTAINS = 'contains',\n EXACT = 'exact',\n\n // Token\n TEXT = 'text',\n NOT = 'not',\n ABOVE = 'above',\n BELOW = 'below',\n IN = 'in',\n NOT_IN = 'not-in',\n OF_TYPE = 'of-type',\n\n // All\n MISSING = 'missing',\n\n // Reference\n IDENTIFIER = 'identifier',\n\n // _include and _revinclude\n ITERATE = 'iterate',\n}\n\n/**\n * Parameter names may specify a modifier as a suffix.\n * The modifiers are separated from the parameter name by a colon.\n * See: https://www.hl7.org/fhir/search.html#modifiers\n */\nconst MODIFIER_OPERATORS: Record<string, Operator> = {\n contains: Operator.CONTAINS,\n exact: Operator.EXACT,\n above: Operator.ABOVE,\n below: Operator.BELOW,\n text: Operator.TEXT,\n not: Operator.NOT,\n in: Operator.IN,\n 'not-in': Operator.NOT_IN,\n 'of-type': Operator.OF_TYPE,\n missing: Operator.MISSING,\n identifier: Operator.IDENTIFIER,\n iterate: Operator.ITERATE,\n};\n\n/**\n * For the ordered parameter types of number, date, and quantity,\n * a prefix to the parameter value may be used to control the nature\n * of the matching.\n * See: https://www.hl7.org/fhir/search.html#prefix\n */\nconst PREFIX_OPERATORS: Record<string, Operator> = {\n eq: Operator.EQUALS,\n ne: Operator.NOT_EQUALS,\n lt: Operator.LESS_THAN,\n le: Operator.LESS_THAN_OR_EQUALS,\n gt: Operator.GREATER_THAN,\n ge: Operator.GREATER_THAN_OR_EQUALS,\n sa: Operator.STARTS_AFTER,\n eb: Operator.ENDS_BEFORE,\n ap: Operator.APPROXIMATELY,\n};\n\n/**\n * Parses a search URL into a search request.\n * @param resourceType The FHIR resource type.\n * @param query The collection of query string parameters.\n * @returns A parsed SearchRequest.\n */\nexport function parseSearchRequest<T extends Resource = Resource>(\n resourceType: T['resourceType'],\n query: Record<string, string[] | string | undefined>\n): SearchRequest<T> {\n const queryArray: [string, string][] = [];\n for (const [key, value] of Object.entries(query)) {\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n queryArray.push([key, value[i]]);\n }\n } else {\n queryArray.push([key, value || '']);\n }\n }\n return parseSearchImpl(resourceType, queryArray);\n}\n\n/**\n * Parses a search URL into a search request.\n * @param url The search URL.\n * @returns A parsed SearchRequest.\n */\nexport function parseSearchUrl<T extends Resource = Resource>(url: URL): SearchRequest<T> {\n const resourceType = url.pathname.split('/').filter(Boolean).pop() as ResourceType;\n return parseSearchImpl<T>(resourceType, url.searchParams.entries());\n}\n\n/**\n * Parses a URL string into a SearchRequest.\n * @param url The URL to parse.\n * @returns Parsed search definition.\n */\nexport function parseSearchDefinition<T extends Resource = Resource>(url: string): SearchRequest<T> {\n return parseSearchUrl<T>(new URL(url, 'https://example.com/'));\n}\n\nfunction parseSearchImpl<T extends Resource = Resource>(\n resourceType: T['resourceType'],\n query: [string, string][] | IterableIterator<[string, string]>\n): SearchRequest<T> {\n const searchRequest: SearchRequest<T> = {\n resourceType,\n };\n\n for (const [key, value] of query) {\n parseKeyValue(searchRequest, key, value);\n }\n\n return searchRequest;\n}\n\nfunction parseKeyValue(searchRequest: SearchRequest, key: string, value: string): void {\n let code;\n let modifier;\n\n const colonIndex = key.indexOf(':');\n if (colonIndex >= 0) {\n code = key.substring(0, colonIndex);\n modifier = key.substring(colonIndex + 1);\n } else {\n code = key;\n modifier = '';\n }\n\n switch (code) {\n case '_sort':\n parseSortRule(searchRequest, value);\n break;\n\n case '_count':\n searchRequest.count = parseInt(value);\n break;\n\n case '_offset':\n searchRequest.offset = parseInt(value);\n break;\n\n case '_total':\n searchRequest.total = value as 'none' | 'estimate' | 'accurate';\n break;\n\n case '_summary':\n searchRequest.total = 'estimate';\n searchRequest.count = 0;\n break;\n\n case '_include': {\n const target = parseIncludeTarget(value);\n if (modifier === 'iterate') {\n target.modifier = Operator.ITERATE;\n }\n if (searchRequest.include) {\n searchRequest.include.push(target);\n } else {\n searchRequest.include = [target];\n }\n break;\n }\n\n case '_revinclude': {\n const target = parseIncludeTarget(value);\n if (modifier === 'iterate') {\n target.modifier = Operator.ITERATE;\n }\n if (searchRequest.revInclude) {\n searchRequest.revInclude.push(target);\n } else {\n searchRequest.revInclude = [target];\n }\n break;\n }\n\n case '_fields':\n searchRequest.fields = value.split(',');\n break;\n\n default: {\n const param = globalSchema.types[searchRequest.resourceType]?.searchParams?.[code];\n if (param) {\n parseParameter(searchRequest, param, modifier, value);\n } else {\n parseUnknownParameter(searchRequest, code, modifier, value);\n }\n }\n }\n}\n\nfunction parseSortRule(searchRequest: SearchRequest, value: string): void {\n for (const field of value.split(',')) {\n let code;\n let descending = false;\n if (field.startsWith('-')) {\n code = field.substring(1);\n descending = true;\n } else {\n code = field;\n }\n if (!searchRequest.sortRules) {\n searchRequest.sortRules = [];\n }\n searchRequest.sortRules.push({ code, descending });\n }\n}\n\nfunction parseParameter(\n searchRequest: SearchRequest,\n searchParam: SearchParameter,\n modifier: string,\n value: string\n): void {\n if (modifier === 'missing') {\n addFilter(searchRequest, {\n code: searchParam.code as string,\n operator: Operator.MISSING,\n value,\n });\n return;\n }\n switch (searchParam.type) {\n case 'number':\n case 'date':\n parsePrefixType(searchRequest, searchParam, value);\n break;\n case 'reference':\n case 'string':\n case 'token':\n case 'uri':\n parseModifierType(searchRequest, searchParam, modifier, value);\n break;\n case 'quantity':\n parseQuantity(searchRequest, searchParam, value);\n break;\n }\n}\n\nfunction parsePrefixType(searchRequest: SearchRequest, param: SearchParameter, input: string): void {\n const { operator, value } = parsePrefix(input);\n addFilter(searchRequest, {\n code: param.code as string,\n operator,\n value,\n });\n}\n\nfunction parseModifierType(\n searchRequest: SearchRequest,\n param: SearchParameter,\n modifier: string,\n value: string\n): void {\n addFilter(searchRequest, {\n code: param.code as string,\n operator: parseModifier(modifier),\n value,\n });\n}\n\nfunction parseQuantity(searchRequest: SearchRequest, param: SearchParameter, input: string): void {\n const [prefixNumber, unitSystem, unitCode] = input.split('|');\n const { operator, value } = parsePrefix(prefixNumber);\n addFilter(searchRequest, {\n code: param.code as string,\n operator,\n value,\n unitSystem,\n unitCode,\n });\n}\n\nfunction parseUnknownParameter(searchRequest: SearchRequest, code: string, modifier: string, value: string): void {\n let operator = Operator.EQUALS;\n if (modifier) {\n operator = modifier as Operator;\n } else if (value.length >= 2) {\n const prefix = value.substring(0, 2);\n if (prefix in PREFIX_OPERATORS) {\n if (value.length === 2 || value.at(2)?.match(/\\d/)) {\n operator = prefix as Operator;\n value = value.substring(prefix.length);\n }\n }\n }\n\n addFilter(searchRequest, {\n code,\n operator,\n value,\n });\n}\n\nfunction parsePrefix(input: string): { operator: Operator; value: string } {\n const prefix = input.substring(0, 2);\n const prefixOperator = PREFIX_OPERATORS[prefix];\n if (prefixOperator) {\n return { operator: prefixOperator, value: input.substring(2) };\n }\n return { operator: Operator.EQUALS, value: input };\n}\n\nfunction parseModifier(modifier: string): Operator {\n return MODIFIER_OPERATORS[modifier] || Operator.EQUALS;\n}\n\nfunction parseIncludeTarget(input: string): IncludeTarget {\n const parts = input.split(':');\n\n parts.forEach((p) => {\n if (p === '*') {\n throw new OperationOutcomeError(badRequest(`'*' is not supported as a value for search inclusion parameters`));\n }\n });\n\n if (parts.length === 1) {\n // Full wildcard, not currently supported\n throw new OperationOutcomeError(\n badRequest(`Invalid include value '${input}': must be of the form ResourceType:search-parameter`)\n );\n } else if (parts.length === 2) {\n return {\n resourceType: parts[0],\n searchParam: parts[1],\n };\n } else if (parts.length === 3) {\n return {\n resourceType: parts[0],\n searchParam: parts[1],\n targetType: parts[2],\n };\n } else {\n throw new OperationOutcomeError(badRequest(`Invalid include value '${input}'`));\n }\n}\n\nfunction addFilter(searchRequest: SearchRequest, filter: Filter): void {\n if (searchRequest.filters) {\n searchRequest.filters.push(filter);\n } else {\n searchRequest.filters = [filter];\n }\n}\n\n/**\n * Formats a search definition object into a query string.\n * Note: The return value does not include the resource type.\n * @param {!SearchRequest} definition The search definition.\n * @returns Formatted URL.\n */\nexport function formatSearchQuery(definition: SearchRequest): string {\n const params: string[] = [];\n\n if (definition.fields) {\n params.push('_fields=' + definition.fields.join(','));\n }\n\n if (definition.filters) {\n definition.filters.forEach((filter) => params.push(formatFilter(filter)));\n }\n\n if (definition.sortRules && definition.sortRules.length > 0) {\n params.push(formatSortRules(definition.sortRules));\n }\n\n if (definition.offset !== undefined) {\n params.push('_offset=' + definition.offset);\n }\n\n if (definition.count !== undefined) {\n params.push('_count=' + definition.count);\n }\n\n if (definition.total !== undefined) {\n params.push('_total=' + definition.total);\n }\n\n if (params.length === 0) {\n return '';\n }\n\n params.sort();\n return '?' + params.join('&');\n}\n\nfunction formatFilter(filter: Filter): string {\n const modifier = filter.operator in MODIFIER_OPERATORS ? ':' + filter.operator : '';\n const prefix = filter.operator !== Operator.EQUALS && filter.operator in PREFIX_OPERATORS ? filter.operator : '';\n return `${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`;\n}\n\nfunction formatSortRules(sortRules: SortRule[]): string {\n return '_sort=' + sortRules.map((sr) => (sr.descending ? '-' + sr.code : sr.code)).join(',');\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search.mjs","sources":["../../../src/search/search.ts"],"sourcesContent":["import { Resource, ResourceType, SearchParameter } from '@medplum/fhirtypes';\nimport { globalSchema } from '../types';\nimport { OperationOutcomeError, badRequest } from '../outcomes';\n\nexport const DEFAULT_SEARCH_COUNT = 20;\n\nexport interface SearchRequest<T extends Resource = Resource> {\n readonly resourceType: T['resourceType'];\n filters?: Filter[];\n sortRules?: SortRule[];\n offset?: number;\n count?: number;\n fields?: string[];\n name?: string;\n total?: 'none' | 'estimate' | 'accurate';\n include?: IncludeTarget[];\n revInclude?: IncludeTarget[];\n}\n\nexport interface Filter {\n code: string;\n operator: Operator;\n value: string;\n unitSystem?: string;\n unitCode?: string;\n}\n\nexport interface SortRule {\n code: string;\n descending?: boolean;\n}\n\nexport interface IncludeTarget {\n resourceType: string;\n searchParam: string;\n targetType?: string;\n modifier?: string;\n}\n\n/**\n * Search operators.\n * These operators represent \"modifiers\" and \"prefixes\" in FHIR search.\n * See: https://www.hl7.org/fhir/search.html\n */\nexport enum Operator {\n EQUALS = 'eq',\n NOT_EQUALS = 'ne',\n\n // Numbers\n GREATER_THAN = 'gt',\n LESS_THAN = 'lt',\n GREATER_THAN_OR_EQUALS = 'ge',\n LESS_THAN_OR_EQUALS = 'le',\n\n // Dates\n STARTS_AFTER = 'sa',\n ENDS_BEFORE = 'eb',\n APPROXIMATELY = 'ap',\n\n // String\n CONTAINS = 'contains',\n EXACT = 'exact',\n\n // Token\n TEXT = 'text',\n NOT = 'not',\n ABOVE = 'above',\n BELOW = 'below',\n IN = 'in',\n NOT_IN = 'not-in',\n OF_TYPE = 'of-type',\n\n // All\n MISSING = 'missing',\n\n // Reference\n IDENTIFIER = 'identifier',\n\n // _include and _revinclude\n ITERATE = 'iterate',\n}\n\n/**\n * Parameter names may specify a modifier as a suffix.\n * The modifiers are separated from the parameter name by a colon.\n * See: https://www.hl7.org/fhir/search.html#modifiers\n */\nconst MODIFIER_OPERATORS: Record<string, Operator> = {\n contains: Operator.CONTAINS,\n exact: Operator.EXACT,\n above: Operator.ABOVE,\n below: Operator.BELOW,\n text: Operator.TEXT,\n not: Operator.NOT,\n in: Operator.IN,\n 'not-in': Operator.NOT_IN,\n 'of-type': Operator.OF_TYPE,\n missing: Operator.MISSING,\n identifier: Operator.IDENTIFIER,\n iterate: Operator.ITERATE,\n};\n\n/**\n * For the ordered parameter types of number, date, and quantity,\n * a prefix to the parameter value may be used to control the nature\n * of the matching.\n * See: https://www.hl7.org/fhir/search.html#prefix\n */\nconst PREFIX_OPERATORS: Record<string, Operator> = {\n eq: Operator.EQUALS,\n ne: Operator.NOT_EQUALS,\n lt: Operator.LESS_THAN,\n le: Operator.LESS_THAN_OR_EQUALS,\n gt: Operator.GREATER_THAN,\n ge: Operator.GREATER_THAN_OR_EQUALS,\n sa: Operator.STARTS_AFTER,\n eb: Operator.ENDS_BEFORE,\n ap: Operator.APPROXIMATELY,\n};\n\n/**\n * Parses a search URL into a search request.\n * @param resourceType The FHIR resource type.\n * @param query The collection of query string parameters.\n * @returns A parsed SearchRequest.\n */\nexport function parseSearchRequest<T extends Resource = Resource>(\n resourceType: T['resourceType'],\n query: Record<string, string[] | string | undefined>\n): SearchRequest<T> {\n const queryArray: [string, string][] = [];\n for (const [key, value] of Object.entries(query)) {\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n queryArray.push([key, value[i]]);\n }\n } else {\n queryArray.push([key, value || '']);\n }\n }\n return parseSearchImpl(resourceType, queryArray);\n}\n\n/**\n * Parses a search URL into a search request.\n * @param url The search URL.\n * @returns A parsed SearchRequest.\n */\nexport function parseSearchUrl<T extends Resource = Resource>(url: URL): SearchRequest<T> {\n const resourceType = url.pathname.split('/').filter(Boolean).pop() as ResourceType;\n return parseSearchImpl<T>(resourceType, url.searchParams.entries());\n}\n\n/**\n * Parses a URL string into a SearchRequest.\n * @param url The URL to parse.\n * @returns Parsed search definition.\n */\nexport function parseSearchDefinition<T extends Resource = Resource>(url: string): SearchRequest<T> {\n return parseSearchUrl<T>(new URL(url, 'https://example.com/'));\n}\n\nfunction parseSearchImpl<T extends Resource = Resource>(\n resourceType: T['resourceType'],\n query: [string, string][] | IterableIterator<[string, string]>\n): SearchRequest<T> {\n const searchRequest: SearchRequest<T> = {\n resourceType,\n };\n\n for (const [key, value] of query) {\n parseKeyValue(searchRequest, key, value);\n }\n\n return searchRequest;\n}\n\nfunction parseKeyValue(searchRequest: SearchRequest, key: string, value: string): void {\n let code;\n let modifier;\n\n const colonIndex = key.indexOf(':');\n if (colonIndex >= 0) {\n code = key.substring(0, colonIndex);\n modifier = key.substring(colonIndex + 1);\n } else {\n code = key;\n modifier = '';\n }\n\n switch (code) {\n case '_sort':\n parseSortRule(searchRequest, value);\n break;\n\n case '_count':\n searchRequest.count = parseInt(value);\n break;\n\n case '_offset':\n searchRequest.offset = parseInt(value);\n break;\n\n case '_total':\n searchRequest.total = value as 'none' | 'estimate' | 'accurate';\n break;\n\n case '_summary':\n searchRequest.total = 'accurate';\n searchRequest.count = 0;\n break;\n\n case '_include': {\n const target = parseIncludeTarget(value);\n if (modifier === 'iterate') {\n target.modifier = Operator.ITERATE;\n }\n if (searchRequest.include) {\n searchRequest.include.push(target);\n } else {\n searchRequest.include = [target];\n }\n break;\n }\n\n case '_revinclude': {\n const target = parseIncludeTarget(value);\n if (modifier === 'iterate') {\n target.modifier = Operator.ITERATE;\n }\n if (searchRequest.revInclude) {\n searchRequest.revInclude.push(target);\n } else {\n searchRequest.revInclude = [target];\n }\n break;\n }\n\n case '_fields':\n searchRequest.fields = value.split(',');\n break;\n\n default: {\n const param = globalSchema.types[searchRequest.resourceType]?.searchParams?.[code];\n if (param) {\n parseParameter(searchRequest, param, modifier, value);\n } else {\n parseUnknownParameter(searchRequest, code, modifier, value);\n }\n }\n }\n}\n\nfunction parseSortRule(searchRequest: SearchRequest, value: string): void {\n for (const field of value.split(',')) {\n let code;\n let descending = false;\n if (field.startsWith('-')) {\n code = field.substring(1);\n descending = true;\n } else {\n code = field;\n }\n if (!searchRequest.sortRules) {\n searchRequest.sortRules = [];\n }\n searchRequest.sortRules.push({ code, descending });\n }\n}\n\nfunction parseParameter(\n searchRequest: SearchRequest,\n searchParam: SearchParameter,\n modifier: string,\n value: string\n): void {\n if (modifier === 'missing') {\n addFilter(searchRequest, {\n code: searchParam.code as string,\n operator: Operator.MISSING,\n value,\n });\n return;\n }\n switch (searchParam.type) {\n case 'number':\n case 'date':\n parsePrefixType(searchRequest, searchParam, value);\n break;\n case 'reference':\n case 'string':\n case 'token':\n case 'uri':\n parseModifierType(searchRequest, searchParam, modifier, value);\n break;\n case 'quantity':\n parseQuantity(searchRequest, searchParam, value);\n break;\n }\n}\n\nfunction parsePrefixType(searchRequest: SearchRequest, param: SearchParameter, input: string): void {\n const { operator, value } = parsePrefix(input);\n addFilter(searchRequest, {\n code: param.code as string,\n operator,\n value,\n });\n}\n\nfunction parseModifierType(\n searchRequest: SearchRequest,\n param: SearchParameter,\n modifier: string,\n value: string\n): void {\n addFilter(searchRequest, {\n code: param.code as string,\n operator: parseModifier(modifier),\n value,\n });\n}\n\nfunction parseQuantity(searchRequest: SearchRequest, param: SearchParameter, input: string): void {\n const [prefixNumber, unitSystem, unitCode] = input.split('|');\n const { operator, value } = parsePrefix(prefixNumber);\n addFilter(searchRequest, {\n code: param.code as string,\n operator,\n value,\n unitSystem,\n unitCode,\n });\n}\n\nfunction parseUnknownParameter(searchRequest: SearchRequest, code: string, modifier: string, value: string): void {\n let operator = Operator.EQUALS;\n if (modifier) {\n operator = modifier as Operator;\n } else if (value.length >= 2) {\n const prefix = value.substring(0, 2);\n if (prefix in PREFIX_OPERATORS) {\n if (value.length === 2 || value.at(2)?.match(/\\d/)) {\n operator = prefix as Operator;\n value = value.substring(prefix.length);\n }\n }\n }\n\n addFilter(searchRequest, {\n code,\n operator,\n value,\n });\n}\n\nfunction parsePrefix(input: string): { operator: Operator; value: string } {\n const prefix = input.substring(0, 2);\n const prefixOperator = PREFIX_OPERATORS[prefix];\n if (prefixOperator) {\n return { operator: prefixOperator, value: input.substring(2) };\n }\n return { operator: Operator.EQUALS, value: input };\n}\n\nfunction parseModifier(modifier: string): Operator {\n return MODIFIER_OPERATORS[modifier] || Operator.EQUALS;\n}\n\nfunction parseIncludeTarget(input: string): IncludeTarget {\n const parts = input.split(':');\n\n parts.forEach((p) => {\n if (p === '*') {\n throw new OperationOutcomeError(badRequest(`'*' is not supported as a value for search inclusion parameters`));\n }\n });\n\n if (parts.length === 1) {\n // Full wildcard, not currently supported\n throw new OperationOutcomeError(\n badRequest(`Invalid include value '${input}': must be of the form ResourceType:search-parameter`)\n );\n } else if (parts.length === 2) {\n return {\n resourceType: parts[0],\n searchParam: parts[1],\n };\n } else if (parts.length === 3) {\n return {\n resourceType: parts[0],\n searchParam: parts[1],\n targetType: parts[2],\n };\n } else {\n throw new OperationOutcomeError(badRequest(`Invalid include value '${input}'`));\n }\n}\n\nfunction addFilter(searchRequest: SearchRequest, filter: Filter): void {\n if (searchRequest.filters) {\n searchRequest.filters.push(filter);\n } else {\n searchRequest.filters = [filter];\n }\n}\n\n/**\n * Formats a search definition object into a query string.\n * Note: The return value does not include the resource type.\n * @param {!SearchRequest} definition The search definition.\n * @returns Formatted URL.\n */\nexport function formatSearchQuery(definition: SearchRequest): string {\n const params: string[] = [];\n\n if (definition.fields) {\n params.push('_fields=' + definition.fields.join(','));\n }\n\n if (definition.filters) {\n definition.filters.forEach((filter) => params.push(formatFilter(filter)));\n }\n\n if (definition.sortRules && definition.sortRules.length > 0) {\n params.push(formatSortRules(definition.sortRules));\n }\n\n if (definition.offset !== undefined) {\n params.push('_offset=' + definition.offset);\n }\n\n if (definition.count !== undefined) {\n params.push('_count=' + definition.count);\n }\n\n if (definition.total !== undefined) {\n params.push('_total=' + definition.total);\n }\n\n if (params.length === 0) {\n return '';\n }\n\n params.sort();\n return '?' + params.join('&');\n}\n\nfunction formatFilter(filter: Filter): string {\n const modifier = filter.operator in MODIFIER_OPERATORS ? ':' + filter.operator : '';\n const prefix = filter.operator !== Operator.EQUALS && filter.operator in PREFIX_OPERATORS ? filter.operator : '';\n return `${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`;\n}\n\nfunction formatSortRules(sortRules: SortRule[]): string {\n return '_sort=' + sortRules.map((sr) => (sr.descending ? '-' + sr.code : sr.code)).join(',');\n}\n"],"names":[],"mappings":"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"}
package/dist/esm/sftp.mjs CHANGED
@@ -8,7 +8,6 @@ function streamToBuffer(stream) {
8
8
  return new Promise((resolve, reject) => {
9
9
  stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
10
10
  stream.on('error', (err) => {
11
- console.error(err.message);
12
11
  stream.destroy();
13
12
  reject(err);
14
13
  });
@@ -1 +1 @@
1
- {"version":3,"file":"sftp.mjs","sources":["../../src/sftp.ts"],"sourcesContent":["import { Readable } from 'stream';\n\n/**\n * Reads data from a Readable stream and returns a Promise that resolves with a Buffer containing all the data.\n * @param stream - The Readable stream to read from.\n * @returns A Promise that resolves with a Buffer containing all the data from the Readable stream.\n */\nexport function streamToBuffer(stream: Readable): Promise<Buffer> {\n const chunks: Uint8Array[] = [];\n return new Promise<Buffer>((resolve, reject) => {\n stream.on('data', (chunk: Uint8Array) => chunks.push(Buffer.from(chunk)));\n stream.on('error', (err: Error) => {\n console.error(err.message);\n stream.destroy();\n reject(err);\n });\n stream.on('end', () => {\n resolve(Buffer.concat(chunks));\n });\n stream.on('close', () => {\n stream.destroy();\n });\n });\n}\n"],"names":[],"mappings":"AAEA;;;;AAIG;AACG,SAAU,cAAc,CAAC,MAAgB,EAAA;IAC7C,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,KAAI;QAC7C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAiB,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1E,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,KAAI;AAChC,YAAA,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3B,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,GAAG,CAAC,CAAC;AACd,SAAC,CAAC,CAAC;AACH,QAAA,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAK;YACpB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AACjC,SAAC,CAAC,CAAC;AACH,QAAA,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAK;YACtB,MAAM,CAAC,OAAO,EAAE,CAAC;AACnB,SAAC,CAAC,CAAC;AACL,KAAC,CAAC,CAAC;AACL;;;;"}
1
+ {"version":3,"file":"sftp.mjs","sources":["../../src/sftp.ts"],"sourcesContent":["import { Readable } from 'stream';\n\n/**\n * Reads data from a Readable stream and returns a Promise that resolves with a Buffer containing all the data.\n * @param stream - The Readable stream to read from.\n * @returns A Promise that resolves with a Buffer containing all the data from the Readable stream.\n */\nexport function streamToBuffer(stream: Readable): Promise<Buffer> {\n const chunks: Uint8Array[] = [];\n return new Promise<Buffer>((resolve, reject) => {\n stream.on('data', (chunk: Uint8Array) => chunks.push(Buffer.from(chunk)));\n stream.on('error', (err: Error) => {\n stream.destroy();\n reject(err);\n });\n stream.on('end', () => {\n resolve(Buffer.concat(chunks));\n });\n stream.on('close', () => {\n stream.destroy();\n });\n });\n}\n"],"names":[],"mappings":"AAEA;;;;AAIG;AACG,SAAU,cAAc,CAAC,MAAgB,EAAA;IAC7C,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,KAAI;QAC7C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAiB,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1E,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,KAAI;YAChC,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,GAAG,CAAC,CAAC;AACd,SAAC,CAAC,CAAC;AACH,QAAA,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAK;YACpB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AACjC,SAAC,CAAC,CAAC;AACH,QAAA,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAK;YACtB,MAAM,CAAC,OAAO,EAAE,CAAC;AACnB,SAAC,CAAC,CAAC;AACL,KAAC,CAAC,CAAC;AACL;;;;"}
@@ -1,4 +1,4 @@
1
- import { AccessPolicy, Binary, Bundle, Communication, ExtractResource, Identifier, Media, OperationOutcome, Project, ProjectMembership, ProjectSecret, Reference, Resource, ResourceType, UserConfiguration, ValueSet } from '@medplum/fhirtypes';
1
+ import { AccessPolicy, Binary, BulkDataExport, Bundle, Communication, ExtractResource, Identifier, Media, OperationOutcome, Project, ProjectMembership, ProjectSecret, Reference, Resource, ResourceType, UserConfiguration, ValueSet } from '@medplum/fhirtypes';
2
2
  /** @ts-ignore */
3
3
  import type { CustomTableLayout, TDocumentDefinitions, TFontDictionary } from 'pdfmake/interfaces';
4
4
  import { EventTarget } from './eventtarget';
@@ -444,6 +444,11 @@ export declare class MedplumClient extends EventTarget {
444
444
  * @param url The URL to invalidate.
445
445
  */
446
446
  invalidateUrl(url: URL | string): void;
447
+ /**
448
+ * Invalidates all cached values and flushes the cache.
449
+ * @category Caching
450
+ */
451
+ invalidateAll(): void;
447
452
  /**
448
453
  * Invalidates all cached search results or cached requests for the given resourceType.
449
454
  * @category Caching
@@ -1176,9 +1181,10 @@ export declare class MedplumClient extends EventTarget {
1176
1181
  * See The FHIR "batch/transaction" section for full details: https://hl7.org/fhir/http.html#transaction
1177
1182
  * @category Batch
1178
1183
  * @param bundle The FHIR batch/transaction bundle.
1184
+ * @param options Optional fetch options.
1179
1185
  * @returns The FHIR batch/transaction response bundle.
1180
1186
  */
1181
- executeBatch(bundle: Bundle): Promise<Bundle>;
1187
+ executeBatch(bundle: Bundle, options?: RequestInit): Promise<Bundle>;
1182
1188
  /**
1183
1189
  * Sends an email using the Medplum Email API.
1184
1190
  *
@@ -1336,6 +1342,16 @@ export declare class MedplumClient extends EventTarget {
1336
1342
  * @returns Promise that resolves to the created Media
1337
1343
  */
1338
1344
  uploadMedia(contents: string | Uint8Array | File | Blob, contentType: string, filename: string | undefined, additionalFields?: Partial<Media>): Promise<Media>;
1345
+ /**
1346
+ * Performs Bulk Data Export operation request flow. See The FHIR "Bulk Data Export" for full details: https://build.fhir.org/ig/HL7/bulk-data/export.html#bulk-data-export
1347
+ *
1348
+ * @param exportLevel Optional export level. Defaults to system level export. 'Group/:id' - Group of Patients, 'Patient' - All Patients.
1349
+ * @param resourceTypes A string of comma-delimited FHIR resource types.
1350
+ * @param since Resources will be included in the response if their state has changed after the supplied time (e.g. if Resource.meta.lastUpdated is later than the supplied _since time).
1351
+ * @param options Optional fetch options.
1352
+ * @returns Bulk Data Response containing links to Bulk Data files. See "Response - Complete Status" for full details: https://build.fhir.org/ig/HL7/bulk-data/export.html#response---complete-status
1353
+ */
1354
+ bulkExport(exportLevel?: string, resourceTypes?: string, since?: string, options?: RequestInit): Promise<Partial<BulkDataExport>>;
1339
1355
  /**
1340
1356
  * Returns the cache entry if available and not expired.
1341
1357
  * @param key The cache key to retrieve.
@@ -1369,7 +1385,9 @@ export declare class MedplumClient extends EventTarget {
1369
1385
  * @param {Object=} body
1370
1386
  */
1371
1387
  private request;
1388
+ private parseResponse;
1372
1389
  private fetchWithRetry;
1390
+ private pollStatus;
1373
1391
  /**
1374
1392
  * Executes a batch of requests that were automatically batched together.
1375
1393
  */
@@ -1485,4 +1503,5 @@ export declare class MedplumClient extends EventTarget {
1485
1503
  * This synchronizes state across browser windows and browser tabs.
1486
1504
  */
1487
1505
  private setupStorageListener;
1506
+ private retryCatch;
1488
1507
  }
@@ -0,0 +1,49 @@
1
+ export interface MedplumInfraConfig {
2
+ name: string;
3
+ stackName: string;
4
+ accountNumber: string;
5
+ region: string;
6
+ domainName: string;
7
+ vpcId: string;
8
+ apiPort: number;
9
+ apiDomainName: string;
10
+ apiSslCertArn: string;
11
+ apiInternetFacing?: boolean;
12
+ appDomainName: string;
13
+ appSslCertArn: string;
14
+ appApiProxy?: boolean;
15
+ appLoggingBucket?: string;
16
+ appLoggingPrefix?: string;
17
+ storageBucketName: string;
18
+ storageDomainName: string;
19
+ storageSslCertArn: string;
20
+ storagePublicKey: string;
21
+ storageLoggingBucket?: string;
22
+ storageLoggingPrefix?: string;
23
+ maxAzs: number;
24
+ rdsInstances: number;
25
+ rdsInstanceType: string;
26
+ rdsSecretsArn?: string;
27
+ cacheNodeType?: string;
28
+ desiredServerCount: number;
29
+ serverImage: string;
30
+ serverMemory: number;
31
+ serverCpu: number;
32
+ loadBalancerLoggingBucket?: string;
33
+ loadBalancerLoggingPrefix?: string;
34
+ clamscanEnabled: boolean;
35
+ clamscanLoggingBucket: string;
36
+ clamscanLoggingPrefix: string;
37
+ skipDns?: boolean;
38
+ additionalContainers?: {
39
+ name: string;
40
+ image: string;
41
+ cpu?: number;
42
+ memory?: number;
43
+ essential?: boolean;
44
+ command?: string[];
45
+ environment?: {
46
+ [key: string]: string;
47
+ };
48
+ }[];
49
+ }
@@ -1,6 +1,7 @@
1
1
  export * from './bundle';
2
2
  export * from './cache';
3
3
  export * from './client';
4
+ export * from './config';
4
5
  export * from './fhirlexer';
5
6
  export * from './fhirmapper';
6
7
  export * from './fhirpath';
@@ -0,0 +1,56 @@
1
+ import { ResourceType, StructureDefinition } from '@medplum/fhirtypes';
2
+ import { TypedValue } from '../types';
3
+ /**
4
+ * Internal representation of a non-primitive FHIR type, suitable for use in resource validation
5
+ */
6
+ export interface InternalTypeSchema {
7
+ name: ResourceType;
8
+ fields: Record<string, ElementValidator>;
9
+ constraints: Constraint[];
10
+ }
11
+ export interface ElementValidator {
12
+ min: number;
13
+ max: number;
14
+ isArray: boolean;
15
+ constraints: Constraint[];
16
+ type: ElementType[];
17
+ slicing?: SlicingRules;
18
+ fixed?: TypedValue;
19
+ pattern?: TypedValue;
20
+ binding?: string;
21
+ }
22
+ export interface ElementType {
23
+ code: string;
24
+ targetProfile: string[];
25
+ }
26
+ export interface Constraint {
27
+ key: string;
28
+ severity: 'error' | 'warning';
29
+ expression: string;
30
+ description: string;
31
+ }
32
+ export interface SlicingRules {
33
+ discriminator: SliceDiscriminator[];
34
+ ordered: boolean;
35
+ rule?: 'open' | 'closed' | 'openAtEnd';
36
+ slices: SliceDefinition[];
37
+ }
38
+ export interface SliceDefinition {
39
+ name: string;
40
+ fields: Record<string, ElementValidator>;
41
+ min: number;
42
+ max: number;
43
+ }
44
+ export interface SliceDiscriminator {
45
+ path: string;
46
+ type: string;
47
+ }
48
+ /**
49
+ * Parses a StructureDefinition resource into an internal schema better suited for
50
+ * programmatic validation and usage in internal systems
51
+ *
52
+ * @param sd The StructureDefinition resource to parse
53
+ * @returns The parsed schema for the given resource type
54
+ * @experimental
55
+ */
56
+ export declare function parseStructureDefinition(sd: StructureDefinition): InternalTypeSchema;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medplum/core",
3
- "version": "2.0.19",
3
+ "version": "2.0.21",
4
4
  "description": "Medplum TS/JS Library",
5
5
  "author": "Medplum <hello@medplum.com>",
6
6
  "license": "Apache-2.0",