@medplum/core 0.10.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ import { Resource } from '@medplum/fhirtypes';
2
+ import { SearchRequest } from './search';
3
+ /**
4
+ * Determines if the resource matches the search request.
5
+ * @param resource The resource that was created or updated.
6
+ * @param searchRequest The subscription criteria as a search request.
7
+ * @returns True if the resource satisfies the search request.
8
+ */
9
+ export declare function matchesSearchRequest(resource: Resource, searchRequest: SearchRequest): boolean;
@@ -0,0 +1,161 @@
1
+ import './fhirpath/atoms.js';
2
+ import { evalFhirPath } from './fhirpath/parse.js';
3
+ import './fhirlexer/parse.js';
4
+ import './fhirlexer/tokenize.js';
5
+ import { globalSchema } from './types.js';
6
+ import './utils.js';
7
+ import { Operator } from './search.js';
8
+ import { getSearchParameterDetails, SearchParameterType } from './searchparams.js';
9
+
10
+ /**
11
+ * Determines if the resource matches the search request.
12
+ * @param resource The resource that was created or updated.
13
+ * @param searchRequest The subscription criteria as a search request.
14
+ * @returns True if the resource satisfies the search request.
15
+ */
16
+ function matchesSearchRequest(resource, searchRequest) {
17
+ if (searchRequest.resourceType !== resource.resourceType) {
18
+ return false;
19
+ }
20
+ if (searchRequest.filters) {
21
+ for (const filter of searchRequest.filters) {
22
+ if (!matchesSearchFilter(resource, searchRequest, filter)) {
23
+ return false;
24
+ }
25
+ }
26
+ }
27
+ return true;
28
+ }
29
+ /**
30
+ * Determines if the resource matches the search filter.
31
+ * @param resource The resource that was created or updated.
32
+ * @param filter One of the filters of a subscription criteria.
33
+ * @returns True if the resource satisfies the search filter.
34
+ */
35
+ function matchesSearchFilter(resource, searchRequest, filter) {
36
+ var _a, _b;
37
+ const searchParam = (_b = (_a = globalSchema.types[searchRequest.resourceType]) === null || _a === void 0 ? void 0 : _a.searchParams) === null || _b === void 0 ? void 0 : _b[filter.code];
38
+ switch (searchParam === null || searchParam === void 0 ? void 0 : searchParam.type) {
39
+ case 'reference':
40
+ return matchesReferenceFilter(resource, filter, searchParam);
41
+ case 'string':
42
+ return matchesStringFilter(resource, filter, searchParam);
43
+ case 'token':
44
+ return matchesTokenFilter(resource, filter, searchParam);
45
+ case 'date':
46
+ return matchesDateFilter(resource, filter, searchParam);
47
+ }
48
+ // Unknown search parameter or search parameter type
49
+ // Default fail the check
50
+ return false;
51
+ }
52
+ function matchesReferenceFilter(resource, filter, searchParam) {
53
+ const values = evalFhirPath(searchParam.expression, resource);
54
+ const negated = isNegated(filter.operator);
55
+ if (filter.value === '' && values.length === 0) {
56
+ // If the filter operator is "equals", then the filter matches.
57
+ // If the filter operator is "not equals", then the filter does not match.
58
+ return filter.operator === Operator.EQUALS;
59
+ }
60
+ // Normalize the values array into reference strings
61
+ const references = values.map((value) => (typeof value === 'string' ? value : value.reference));
62
+ for (const filterValue of filter.value.split(',')) {
63
+ let match = references.includes(filterValue);
64
+ if (!match && filter.code === '_compartment') {
65
+ // Backwards compability for compartment search parameter
66
+ // In previous versions, the resource type was not required in compartment values
67
+ // So, "123" would match "Patient/123"
68
+ // We need to maintain this behavior for backwards compatibility
69
+ match = references.some((reference) => reference === null || reference === void 0 ? void 0 : reference.endsWith('/' + filterValue));
70
+ }
71
+ if (match) {
72
+ return !negated;
73
+ }
74
+ }
75
+ // If "not equals" and no matches, then return true
76
+ // If "equals" and no matches, then return false
77
+ return negated;
78
+ }
79
+ function matchesTokenFilter(resource, filter, searchParam) {
80
+ const details = getSearchParameterDetails(resource.resourceType, searchParam);
81
+ if (details.type === SearchParameterType.BOOLEAN) {
82
+ return matchesBooleanFilter(resource, filter, searchParam);
83
+ }
84
+ else {
85
+ return matchesStringFilter(resource, filter, searchParam);
86
+ }
87
+ }
88
+ function matchesBooleanFilter(resource, filter, searchParam) {
89
+ const values = evalFhirPath(searchParam.expression, resource);
90
+ const expected = filter.value === 'true';
91
+ const result = values.includes(expected);
92
+ return isNegated(filter.operator) ? !result : result;
93
+ }
94
+ function matchesStringFilter(resource, filter, searchParam) {
95
+ const resourceValues = evalFhirPath(searchParam.expression, resource);
96
+ const filterValues = filter.value.split(',');
97
+ const negated = isNegated(filter.operator);
98
+ for (const resourceValue of resourceValues) {
99
+ for (const filterValue of filterValues) {
100
+ const match = matchesStringValue(resourceValue, filter.operator, filterValue);
101
+ if (match) {
102
+ return !negated;
103
+ }
104
+ }
105
+ }
106
+ // If "not equals" and no matches, then return true
107
+ // If "equals" and no matches, then return false
108
+ return negated;
109
+ }
110
+ function matchesStringValue(resourceValue, operator, filterValue) {
111
+ let str = '';
112
+ if (resourceValue) {
113
+ if (typeof resourceValue === 'string') {
114
+ str = resourceValue;
115
+ }
116
+ else if (typeof resourceValue === 'object') {
117
+ str = JSON.stringify(resourceValue);
118
+ }
119
+ }
120
+ return str.toLowerCase().includes(filterValue.toLowerCase());
121
+ }
122
+ function matchesDateFilter(resource, filter, searchParam) {
123
+ const resourceValues = evalFhirPath(searchParam.expression, resource);
124
+ const filterValues = filter.value.split(',');
125
+ const negated = isNegated(filter.operator);
126
+ for (const resourceValue of resourceValues) {
127
+ for (const filterValue of filterValues) {
128
+ const match = matchesDateValue(resourceValue, filter.operator, filterValue);
129
+ if (match) {
130
+ return !negated;
131
+ }
132
+ }
133
+ }
134
+ // If "not equals" and no matches, then return true
135
+ // If "equals" and no matches, then return false
136
+ return negated;
137
+ }
138
+ function matchesDateValue(resourceValue, operator, filterValue) {
139
+ switch (operator) {
140
+ case Operator.STARTS_AFTER:
141
+ case Operator.GREATER_THAN:
142
+ return resourceValue > filterValue;
143
+ case Operator.GREATER_THAN_OR_EQUALS:
144
+ return resourceValue >= filterValue;
145
+ case Operator.ENDS_BEFORE:
146
+ case Operator.LESS_THAN:
147
+ return resourceValue < filterValue;
148
+ case Operator.LESS_THAN_OR_EQUALS:
149
+ return resourceValue <= filterValue;
150
+ case Operator.EQUALS:
151
+ case Operator.NOT_EQUALS:
152
+ return resourceValue === filterValue;
153
+ }
154
+ return false;
155
+ }
156
+ function isNegated(operator) {
157
+ return operator === Operator.NOT_EQUALS || operator === Operator.NOT;
158
+ }
159
+
160
+ export { matchesSearchRequest };
161
+ //# sourceMappingURL=match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match.js","sources":["../../src/match.ts"],"sourcesContent":["import { Reference, Resource, SearchParameter } from '@medplum/fhirtypes';\nimport { evalFhirPath } from './fhirpath';\nimport { Filter, Operator, SearchRequest } from './search';\nimport { getSearchParameterDetails, SearchParameterType } from './searchparams';\nimport { globalSchema } from './types';\n\n/**\n * Determines if the resource matches the search request.\n * @param resource The resource that was created or updated.\n * @param searchRequest The subscription criteria as a search request.\n * @returns True if the resource satisfies the search request.\n */\nexport function matchesSearchRequest(resource: Resource, searchRequest: SearchRequest): boolean {\n if (searchRequest.resourceType !== resource.resourceType) {\n return false;\n }\n if (searchRequest.filters) {\n for (const filter of searchRequest.filters) {\n if (!matchesSearchFilter(resource, searchRequest, filter)) {\n return false;\n }\n }\n }\n return true;\n}\n\n/**\n * Determines if the resource matches the search filter.\n * @param resource The resource that was created or updated.\n * @param filter One of the filters of a subscription criteria.\n * @returns True if the resource satisfies the search filter.\n */\nfunction matchesSearchFilter(resource: Resource, searchRequest: SearchRequest, filter: Filter): boolean {\n const searchParam = globalSchema.types[searchRequest.resourceType]?.searchParams?.[filter.code];\n switch (searchParam?.type) {\n case 'reference':\n return matchesReferenceFilter(resource, filter, searchParam);\n case 'string':\n return matchesStringFilter(resource, filter, searchParam);\n case 'token':\n return matchesTokenFilter(resource, filter, searchParam);\n case 'date':\n return matchesDateFilter(resource, filter, searchParam);\n }\n // Unknown search parameter or search parameter type\n // Default fail the check\n return false;\n}\n\nfunction matchesReferenceFilter(resource: Resource, filter: Filter, searchParam: SearchParameter): boolean {\n const values = evalFhirPath(searchParam.expression as string, resource) as (Reference | string)[];\n const negated = isNegated(filter.operator);\n\n if (filter.value === '' && values.length === 0) {\n // If the filter operator is \"equals\", then the filter matches.\n // If the filter operator is \"not equals\", then the filter does not match.\n return filter.operator === Operator.EQUALS;\n }\n\n // Normalize the values array into reference strings\n const references = values.map((value) => (typeof value === 'string' ? value : value.reference));\n\n for (const filterValue of filter.value.split(',')) {\n let match = references.includes(filterValue);\n if (!match && filter.code === '_compartment') {\n // Backwards compability for compartment search parameter\n // In previous versions, the resource type was not required in compartment values\n // So, \"123\" would match \"Patient/123\"\n // We need to maintain this behavior for backwards compatibility\n match = references.some((reference) => reference?.endsWith('/' + filterValue));\n }\n if (match) {\n return !negated;\n }\n }\n // If \"not equals\" and no matches, then return true\n // If \"equals\" and no matches, then return false\n return negated;\n}\n\nfunction matchesTokenFilter(resource: Resource, filter: Filter, searchParam: SearchParameter): boolean {\n const details = getSearchParameterDetails(resource.resourceType, searchParam);\n if (details.type === SearchParameterType.BOOLEAN) {\n return matchesBooleanFilter(resource, filter, searchParam);\n } else {\n return matchesStringFilter(resource, filter, searchParam);\n }\n}\n\nfunction matchesBooleanFilter(resource: Resource, filter: Filter, searchParam: SearchParameter): boolean {\n const values = evalFhirPath(searchParam.expression as string, resource);\n const expected = filter.value === 'true';\n const result = values.includes(expected);\n return isNegated(filter.operator) ? !result : result;\n}\n\nfunction matchesStringFilter(resource: Resource, filter: Filter, searchParam: SearchParameter): boolean {\n const resourceValues = evalFhirPath(searchParam.expression as string, resource);\n const filterValues = filter.value.split(',');\n const negated = isNegated(filter.operator);\n for (const resourceValue of resourceValues) {\n for (const filterValue of filterValues) {\n const match = matchesStringValue(resourceValue, filter.operator, filterValue);\n if (match) {\n return !negated;\n }\n }\n }\n // If \"not equals\" and no matches, then return true\n // If \"equals\" and no matches, then return false\n return negated;\n}\n\nfunction matchesStringValue(resourceValue: unknown, operator: Operator, filterValue: string): boolean {\n let str = '';\n if (resourceValue) {\n if (typeof resourceValue === 'string') {\n str = resourceValue;\n } else if (typeof resourceValue === 'object') {\n str = JSON.stringify(resourceValue);\n }\n }\n return str.toLowerCase().includes(filterValue.toLowerCase());\n}\n\nfunction matchesDateFilter(resource: Resource, filter: Filter, searchParam: SearchParameter): boolean {\n const resourceValues = evalFhirPath(searchParam.expression as string, resource);\n const filterValues = filter.value.split(',');\n const negated = isNegated(filter.operator);\n for (const resourceValue of resourceValues) {\n for (const filterValue of filterValues) {\n const match = matchesDateValue(resourceValue as string, filter.operator, filterValue);\n if (match) {\n return !negated;\n }\n }\n }\n // If \"not equals\" and no matches, then return true\n // If \"equals\" and no matches, then return false\n return negated;\n}\n\nfunction matchesDateValue(resourceValue: string, operator: Operator, filterValue: string): boolean {\n switch (operator) {\n case Operator.STARTS_AFTER:\n case Operator.GREATER_THAN:\n return resourceValue > filterValue;\n case Operator.GREATER_THAN_OR_EQUALS:\n return resourceValue >= filterValue;\n case Operator.ENDS_BEFORE:\n case Operator.LESS_THAN:\n return resourceValue < filterValue;\n case Operator.LESS_THAN_OR_EQUALS:\n return resourceValue <= filterValue;\n case Operator.EQUALS:\n case Operator.NOT_EQUALS:\n return resourceValue === filterValue;\n }\n return false;\n}\n\nfunction isNegated(operator: Operator): boolean {\n return operator === Operator.NOT_EQUALS || operator === Operator.NOT;\n}\n"],"names":[],"mappings":"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"}
@@ -133,19 +133,26 @@ export declare function createSchema(): IndexedStructureDefinition;
133
133
  /**
134
134
  * Indexes a bundle of StructureDefinitions for faster lookup.
135
135
  * @param bundle A FHIR bundle StructureDefinition resources.
136
+ * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.
136
137
  */
137
138
  export declare function indexStructureDefinitionBundle(bundle: Bundle): void;
138
139
  /**
139
140
  * Indexes a StructureDefinition for fast lookup.
140
- * See comments on IndexedStructureDefinition for more details.
141
141
  * @param structureDefinition The original StructureDefinition.
142
+ * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.
142
143
  */
143
144
  export declare function indexStructureDefinition(structureDefinition: StructureDefinition): void;
145
+ /**
146
+ * Indexes a bundle of SearchParameter resources for faster lookup.
147
+ * @param bundle A FHIR bundle SearchParameter resources.
148
+ * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.
149
+ */
150
+ export declare function indexSearchParameterBundle(bundle: Bundle<SearchParameter>): void;
144
151
  /**
145
152
  * Indexes a SearchParameter resource for fast lookup.
146
153
  * Indexes by SearchParameter.code, which is the query string parameter name.
147
- * @param schema The output IndexedStructureDefinition.
148
154
  * @param searchParam The SearchParameter resource.
155
+ * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.
149
156
  */
150
157
  export declare function indexSearchParameter(searchParam: SearchParameter): void;
151
158
  export declare function buildTypeName(components: string[]): string;
package/dist/esm/types.js CHANGED
@@ -88,6 +88,7 @@ function createTypeSchema(typeName, structureDefinition, elementDefinition) {
88
88
  /**
89
89
  * Indexes a bundle of StructureDefinitions for faster lookup.
90
90
  * @param bundle A FHIR bundle StructureDefinition resources.
91
+ * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.
91
92
  */
92
93
  function indexStructureDefinitionBundle(bundle) {
93
94
  for (const entry of bundle.entry) {
@@ -99,8 +100,8 @@ function indexStructureDefinitionBundle(bundle) {
99
100
  }
100
101
  /**
101
102
  * Indexes a StructureDefinition for fast lookup.
102
- * See comments on IndexedStructureDefinition for more details.
103
103
  * @param structureDefinition The original StructureDefinition.
104
+ * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.
104
105
  */
105
106
  function indexStructureDefinition(structureDefinition) {
106
107
  var _a;
@@ -120,8 +121,9 @@ function indexStructureDefinition(structureDefinition) {
120
121
  * Indexes TypeSchema from an ElementDefinition.
121
122
  * In the common case, there will be many ElementDefinition instances per TypeSchema.
122
123
  * Only the first occurrence is saved.
123
- * @param schema The output IndexedStructureDefinition.
124
- * @param element The input ElementDefinition.
124
+ * @param structureDefinition The parent type structure definition.
125
+ * @param elementDefinition The element definition.
126
+ * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.
125
127
  */
126
128
  function indexType(structureDefinition, elementDefinition) {
127
129
  var _a, _b;
@@ -137,8 +139,8 @@ function indexType(structureDefinition, elementDefinition) {
137
139
  }
138
140
  /**
139
141
  * Indexes PropertySchema from an ElementDefinition.
140
- * @param schema The output IndexedStructureDefinition.
141
142
  * @param element The input ElementDefinition.
143
+ * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.
142
144
  */
143
145
  function indexProperty(element) {
144
146
  const path = element.path;
@@ -154,11 +156,24 @@ function indexProperty(element) {
154
156
  const key = parts[parts.length - 1];
155
157
  typeSchema.properties[key] = element;
156
158
  }
159
+ /**
160
+ * Indexes a bundle of SearchParameter resources for faster lookup.
161
+ * @param bundle A FHIR bundle SearchParameter resources.
162
+ * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.
163
+ */
164
+ function indexSearchParameterBundle(bundle) {
165
+ for (const entry of bundle.entry) {
166
+ const resource = entry.resource;
167
+ if (resource.resourceType === 'SearchParameter') {
168
+ indexSearchParameter(resource);
169
+ }
170
+ }
171
+ }
157
172
  /**
158
173
  * Indexes a SearchParameter resource for fast lookup.
159
174
  * Indexes by SearchParameter.code, which is the query string parameter name.
160
- * @param schema The output IndexedStructureDefinition.
161
175
  * @param searchParam The SearchParameter resource.
176
+ * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.
162
177
  */
163
178
  function indexSearchParameter(searchParam) {
164
179
  if (!searchParam.base) {
@@ -183,6 +198,12 @@ function indexSearchParameter(searchParam) {
183
198
  type: 'date',
184
199
  expression: resourceType + '.meta.lastUpdated',
185
200
  },
201
+ _compartment: {
202
+ base: [resourceType],
203
+ code: '_compartment',
204
+ type: 'reference',
205
+ expression: resourceType + '.meta.compartment',
206
+ },
186
207
  };
187
208
  }
188
209
  typeSchema.searchParams[searchParam.code] = searchParam;
@@ -248,5 +269,5 @@ function getElementDefinition(typeName, propertyName) {
248
269
  */
249
270
  const globalSchema = baseSchema;
250
271
 
251
- export { PropertyType, buildTypeName, createSchema, getElementDefinition, getPropertyDisplayName, globalSchema, indexSearchParameter, indexStructureDefinition, indexStructureDefinitionBundle };
272
+ export { PropertyType, buildTypeName, createSchema, getElementDefinition, getPropertyDisplayName, globalSchema, indexSearchParameter, indexSearchParameterBundle, indexStructureDefinition, indexStructureDefinitionBundle };
252
273
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sources":["../../src/types.ts"],"sourcesContent":["import {\n Bundle,\n BundleEntry,\n ElementDefinition,\n Resource,\n SearchParameter,\n StructureDefinition,\n} from '@medplum/fhirtypes';\nimport baseSchema from './base-schema.json';\nimport { SearchParameterDetails } from './searchparams';\nimport { capitalize } from './utils';\n\nexport interface TypedValue {\n readonly type: string;\n readonly value: any;\n}\n\n/**\n * List of property types.\n * http://www.hl7.org/fhir/valueset-defined-types.html\n * The list here includes additions found from StructureDefinition resources.\n */\nexport enum PropertyType {\n Address = 'Address',\n Age = 'Age',\n Annotation = 'Annotation',\n Attachment = 'Attachment',\n BackboneElement = 'BackboneElement',\n CodeableConcept = 'CodeableConcept',\n Coding = 'Coding',\n ContactDetail = 'ContactDetail',\n ContactPoint = 'ContactPoint',\n Contributor = 'Contributor',\n Count = 'Count',\n DataRequirement = 'DataRequirement',\n Distance = 'Distance',\n Dosage = 'Dosage',\n Duration = 'Duration',\n Expression = 'Expression',\n Extension = 'Extension',\n HumanName = 'HumanName',\n Identifier = 'Identifier',\n MarketingStatus = 'MarketingStatus',\n Meta = 'Meta',\n Money = 'Money',\n Narrative = 'Narrative',\n ParameterDefinition = 'ParameterDefinition',\n Period = 'Period',\n Population = 'Population',\n ProdCharacteristic = 'ProdCharacteristic',\n ProductShelfLife = 'ProductShelfLife',\n Quantity = 'Quantity',\n Range = 'Range',\n Ratio = 'Ratio',\n Reference = 'Reference',\n RelatedArtifact = 'RelatedArtifact',\n SampledData = 'SampledData',\n Signature = 'Signature',\n SubstanceAmount = 'SubstanceAmount',\n SystemString = 'http://hl7.org/fhirpath/System.String',\n Timing = 'Timing',\n TriggerDefinition = 'TriggerDefinition',\n UsageContext = 'UsageContext',\n base64Binary = 'base64Binary',\n boolean = 'boolean',\n canonical = 'canonical',\n code = 'code',\n date = 'date',\n dateTime = 'dateTime',\n decimal = 'decimal',\n id = 'id',\n instant = 'instant',\n integer = 'integer',\n markdown = 'markdown',\n oid = 'oid',\n positiveInt = 'positiveInt',\n string = 'string',\n time = 'time',\n unsignedInt = 'unsignedInt',\n uri = 'uri',\n url = 'url',\n uuid = 'uuid',\n}\n\n/**\n * An IndexedStructureDefinition is a lookup-optimized version of a StructureDefinition.\n *\n * StructureDefinition resources contain schema information for other resource types.\n * These schemas can be used to automatically generate user interface elements for\n * resources.\n *\n * However, a StructureDefinition resource is not optimized for realtime lookups. All\n * resource types, sub types, and property definitions are stored in a flat array of\n * ElementDefinition objects. Therefore, to lookup the schema for a property (i.e., \"Patient.name\")\n * requires a linear scan of all ElementDefinition objects\n *\n * A StructureDefinition resource contains information about one or more types.\n * For example, the \"Patient\" StructureDefinition includes \"Patient\", \"Patient_Contact\",\n * \"Patient_Communication\", and \"Patient_Link\". This is inefficient.\n *\n * Instead, we create an indexed version of the StructureDefinition, called IndexedStructureDefinition.\n * In an IndexedStructureDefinition, retrieving a property definition is a hashtable lookup.\n *\n * The hierarchy is:\n * IndexedStructureDefinition - top level for one resource type\n * TypeSchema - one per resource type and all contained BackboneElements\n * PropertySchema - one per property/field\n */\nexport interface IndexedStructureDefinition {\n types: { [resourceType: string]: TypeSchema };\n}\n\n/**\n * An indexed TypeSchema.\n *\n * Example: The IndexedStructureDefinition for \"Patient\" would include the following TypeSchemas:\n * 1) Patient\n * 2) Patient_Contact\n * 3) Patient_Communication\n * 4) Patient_Link\n */\nexport interface TypeSchema {\n structureDefinition: StructureDefinition;\n elementDefinition: ElementDefinition;\n display: string;\n properties: { [name: string]: ElementDefinition };\n searchParams?: { [code: string]: SearchParameter };\n searchParamsDetails?: { [code: string]: SearchParameterDetails };\n description?: string;\n parentType?: string;\n}\n\n/**\n * Creates a new empty IndexedStructureDefinition.\n * @returns The empty IndexedStructureDefinition.\n * @deprecated Use globalSchema\n */\nexport function createSchema(): IndexedStructureDefinition {\n return { types: {} };\n}\n\nfunction createTypeSchema(\n typeName: string,\n structureDefinition: StructureDefinition,\n elementDefinition: ElementDefinition\n): TypeSchema {\n return {\n structureDefinition,\n elementDefinition,\n display: typeName,\n description: elementDefinition.definition,\n properties: {},\n };\n}\n\n/**\n * Indexes a bundle of StructureDefinitions for faster lookup.\n * @param bundle A FHIR bundle StructureDefinition resources.\n */\nexport function indexStructureDefinitionBundle(bundle: Bundle): void {\n for (const entry of bundle.entry as BundleEntry[]) {\n const resource = entry.resource as Resource;\n if (resource.resourceType === 'StructureDefinition') {\n indexStructureDefinition(resource);\n }\n }\n}\n\n/**\n * Indexes a StructureDefinition for fast lookup.\n * See comments on IndexedStructureDefinition for more details.\n * @param structureDefinition The original StructureDefinition.\n */\nexport function indexStructureDefinition(structureDefinition: StructureDefinition): void {\n const typeName = structureDefinition.name;\n if (!typeName) {\n return;\n }\n\n const elements = structureDefinition.snapshot?.element;\n if (elements) {\n // First pass, build types\n elements.forEach((element) => indexType(structureDefinition, element));\n\n // Second pass, build properties\n elements.forEach((element) => indexProperty(element));\n }\n}\n\n/**\n * Indexes TypeSchema from an ElementDefinition.\n * In the common case, there will be many ElementDefinition instances per TypeSchema.\n * Only the first occurrence is saved.\n * @param schema The output IndexedStructureDefinition.\n * @param element The input ElementDefinition.\n */\nfunction indexType(structureDefinition: StructureDefinition, elementDefinition: ElementDefinition): void {\n const path = elementDefinition.path as string;\n const typeCode = elementDefinition.type?.[0]?.code;\n if (typeCode !== undefined && typeCode !== 'Element' && typeCode !== 'BackboneElement') {\n return;\n }\n const parts = path.split('.');\n const typeName = buildTypeName(parts);\n globalSchema.types[typeName] = createTypeSchema(typeName, structureDefinition, elementDefinition);\n globalSchema.types[typeName].parentType = buildTypeName(parts.slice(0, parts.length - 1));\n}\n\n/**\n * Indexes PropertySchema from an ElementDefinition.\n * @param schema The output IndexedStructureDefinition.\n * @param element The input ElementDefinition.\n */\nfunction indexProperty(element: ElementDefinition): void {\n const path = element.path as string;\n const parts = path.split('.');\n if (parts.length === 1) {\n return;\n }\n const typeName = buildTypeName(parts.slice(0, parts.length - 1));\n const typeSchema = globalSchema.types[typeName];\n if (!typeSchema) {\n return;\n }\n const key = parts[parts.length - 1];\n typeSchema.properties[key] = element;\n}\n\n/**\n * Indexes a SearchParameter resource for fast lookup.\n * Indexes by SearchParameter.code, which is the query string parameter name.\n * @param schema The output IndexedStructureDefinition.\n * @param searchParam The SearchParameter resource.\n */\nexport function indexSearchParameter(searchParam: SearchParameter): void {\n if (!searchParam.base) {\n return;\n }\n\n for (const resourceType of searchParam.base) {\n const typeSchema = globalSchema.types[resourceType];\n if (!typeSchema) {\n continue;\n }\n\n if (!typeSchema.searchParams) {\n typeSchema.searchParams = {\n _id: {\n base: [resourceType],\n code: '_id',\n type: 'token',\n expression: resourceType + '.id',\n } as SearchParameter,\n _lastUpdated: {\n base: [resourceType],\n code: '_lastUpdated',\n type: 'date',\n expression: resourceType + '.meta.lastUpdated',\n } as SearchParameter,\n };\n }\n\n typeSchema.searchParams[searchParam.code as string] = searchParam;\n }\n}\n\nexport function buildTypeName(components: string[]): string {\n if (components.length === 1) {\n return components[0];\n }\n return components.map(capitalize).join('');\n}\n\nexport function getPropertyDisplayName(path: string): string {\n // Get the property name, which is the remainder after the last period\n // For example, for path \"Patient.birthDate\"\n // the property name is \"birthDate\"\n const propertyName = path.replaceAll('[x]', '').split('.').pop() as string;\n\n // Special case for ID\n if (propertyName === 'id') {\n return 'ID';\n }\n\n // Split by capital letters\n // Capitalize the first letter of each word\n // Join together with spaces in between\n // Then normalize whitespace to single space character\n // For example, for property name \"birthDate\",\n // the display name is \"Birth Date\".\n return propertyName\n .split(/(?=[A-Z])/)\n .map(capitalize)\n .join(' ')\n .replace('_', ' ')\n .replace(/\\s+/g, ' ');\n}\n\n/**\n * Returns an element definition by type and property name.\n * Handles content references.\n * @param typeName The type name.\n * @param propertyName The property name.\n * @returns The element definition if found.\n */\nexport function getElementDefinition(typeName: string, propertyName: string): ElementDefinition | undefined {\n const typeSchema = globalSchema.types[typeName];\n if (!typeSchema) {\n return undefined;\n }\n\n const property = typeSchema.properties[propertyName] ?? typeSchema.properties[propertyName + '[x]'];\n if (!property) {\n return undefined;\n }\n\n if (property.contentReference) {\n // Content references start with a \"#\"\n // Remove the \"#\" character\n const contentReference = property.contentReference.substring(1).split('.');\n const referencePropertyName = contentReference.pop() as string;\n const referenceTypeName = buildTypeName(contentReference);\n return getElementDefinition(referenceTypeName, referencePropertyName);\n }\n\n return property;\n}\n\n/**\n * Global schema singleton.\n */\nexport const globalSchema = baseSchema as unknown as IndexedStructureDefinition;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.js","sources":["../../src/types.ts"],"sourcesContent":["import {\n Bundle,\n BundleEntry,\n ElementDefinition,\n Resource,\n SearchParameter,\n StructureDefinition,\n} from '@medplum/fhirtypes';\nimport baseSchema from './base-schema.json';\nimport { SearchParameterDetails } from './searchparams';\nimport { capitalize } from './utils';\n\nexport interface TypedValue {\n readonly type: string;\n readonly value: any;\n}\n\n/**\n * List of property types.\n * http://www.hl7.org/fhir/valueset-defined-types.html\n * The list here includes additions found from StructureDefinition resources.\n */\nexport enum PropertyType {\n Address = 'Address',\n Age = 'Age',\n Annotation = 'Annotation',\n Attachment = 'Attachment',\n BackboneElement = 'BackboneElement',\n CodeableConcept = 'CodeableConcept',\n Coding = 'Coding',\n ContactDetail = 'ContactDetail',\n ContactPoint = 'ContactPoint',\n Contributor = 'Contributor',\n Count = 'Count',\n DataRequirement = 'DataRequirement',\n Distance = 'Distance',\n Dosage = 'Dosage',\n Duration = 'Duration',\n Expression = 'Expression',\n Extension = 'Extension',\n HumanName = 'HumanName',\n Identifier = 'Identifier',\n MarketingStatus = 'MarketingStatus',\n Meta = 'Meta',\n Money = 'Money',\n Narrative = 'Narrative',\n ParameterDefinition = 'ParameterDefinition',\n Period = 'Period',\n Population = 'Population',\n ProdCharacteristic = 'ProdCharacteristic',\n ProductShelfLife = 'ProductShelfLife',\n Quantity = 'Quantity',\n Range = 'Range',\n Ratio = 'Ratio',\n Reference = 'Reference',\n RelatedArtifact = 'RelatedArtifact',\n SampledData = 'SampledData',\n Signature = 'Signature',\n SubstanceAmount = 'SubstanceAmount',\n SystemString = 'http://hl7.org/fhirpath/System.String',\n Timing = 'Timing',\n TriggerDefinition = 'TriggerDefinition',\n UsageContext = 'UsageContext',\n base64Binary = 'base64Binary',\n boolean = 'boolean',\n canonical = 'canonical',\n code = 'code',\n date = 'date',\n dateTime = 'dateTime',\n decimal = 'decimal',\n id = 'id',\n instant = 'instant',\n integer = 'integer',\n markdown = 'markdown',\n oid = 'oid',\n positiveInt = 'positiveInt',\n string = 'string',\n time = 'time',\n unsignedInt = 'unsignedInt',\n uri = 'uri',\n url = 'url',\n uuid = 'uuid',\n}\n\n/**\n * An IndexedStructureDefinition is a lookup-optimized version of a StructureDefinition.\n *\n * StructureDefinition resources contain schema information for other resource types.\n * These schemas can be used to automatically generate user interface elements for\n * resources.\n *\n * However, a StructureDefinition resource is not optimized for realtime lookups. All\n * resource types, sub types, and property definitions are stored in a flat array of\n * ElementDefinition objects. Therefore, to lookup the schema for a property (i.e., \"Patient.name\")\n * requires a linear scan of all ElementDefinition objects\n *\n * A StructureDefinition resource contains information about one or more types.\n * For example, the \"Patient\" StructureDefinition includes \"Patient\", \"Patient_Contact\",\n * \"Patient_Communication\", and \"Patient_Link\". This is inefficient.\n *\n * Instead, we create an indexed version of the StructureDefinition, called IndexedStructureDefinition.\n * In an IndexedStructureDefinition, retrieving a property definition is a hashtable lookup.\n *\n * The hierarchy is:\n * IndexedStructureDefinition - top level for one resource type\n * TypeSchema - one per resource type and all contained BackboneElements\n * PropertySchema - one per property/field\n */\nexport interface IndexedStructureDefinition {\n types: { [resourceType: string]: TypeSchema };\n}\n\n/**\n * An indexed TypeSchema.\n *\n * Example: The IndexedStructureDefinition for \"Patient\" would include the following TypeSchemas:\n * 1) Patient\n * 2) Patient_Contact\n * 3) Patient_Communication\n * 4) Patient_Link\n */\nexport interface TypeSchema {\n structureDefinition: StructureDefinition;\n elementDefinition: ElementDefinition;\n display: string;\n properties: { [name: string]: ElementDefinition };\n searchParams?: { [code: string]: SearchParameter };\n searchParamsDetails?: { [code: string]: SearchParameterDetails };\n description?: string;\n parentType?: string;\n}\n\n/**\n * Creates a new empty IndexedStructureDefinition.\n * @returns The empty IndexedStructureDefinition.\n * @deprecated Use globalSchema\n */\nexport function createSchema(): IndexedStructureDefinition {\n return { types: {} };\n}\n\nfunction createTypeSchema(\n typeName: string,\n structureDefinition: StructureDefinition,\n elementDefinition: ElementDefinition\n): TypeSchema {\n return {\n structureDefinition,\n elementDefinition,\n display: typeName,\n description: elementDefinition.definition,\n properties: {},\n };\n}\n\n/**\n * Indexes a bundle of StructureDefinitions for faster lookup.\n * @param bundle A FHIR bundle StructureDefinition resources.\n * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.\n */\nexport function indexStructureDefinitionBundle(bundle: Bundle): void {\n for (const entry of bundle.entry as BundleEntry[]) {\n const resource = entry.resource as Resource;\n if (resource.resourceType === 'StructureDefinition') {\n indexStructureDefinition(resource);\n }\n }\n}\n\n/**\n * Indexes a StructureDefinition for fast lookup.\n * @param structureDefinition The original StructureDefinition.\n * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.\n */\nexport function indexStructureDefinition(structureDefinition: StructureDefinition): void {\n const typeName = structureDefinition.name;\n if (!typeName) {\n return;\n }\n\n const elements = structureDefinition.snapshot?.element;\n if (elements) {\n // First pass, build types\n elements.forEach((element) => indexType(structureDefinition, element));\n\n // Second pass, build properties\n elements.forEach((element) => indexProperty(element));\n }\n}\n\n/**\n * Indexes TypeSchema from an ElementDefinition.\n * In the common case, there will be many ElementDefinition instances per TypeSchema.\n * Only the first occurrence is saved.\n * @param structureDefinition The parent type structure definition.\n * @param elementDefinition The element definition.\n * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.\n */\nfunction indexType(structureDefinition: StructureDefinition, elementDefinition: ElementDefinition): void {\n const path = elementDefinition.path as string;\n const typeCode = elementDefinition.type?.[0]?.code;\n if (typeCode !== undefined && typeCode !== 'Element' && typeCode !== 'BackboneElement') {\n return;\n }\n const parts = path.split('.');\n const typeName = buildTypeName(parts);\n globalSchema.types[typeName] = createTypeSchema(typeName, structureDefinition, elementDefinition);\n globalSchema.types[typeName].parentType = buildTypeName(parts.slice(0, parts.length - 1));\n}\n\n/**\n * Indexes PropertySchema from an ElementDefinition.\n * @param element The input ElementDefinition.\n * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.\n */\nfunction indexProperty(element: ElementDefinition): void {\n const path = element.path as string;\n const parts = path.split('.');\n if (parts.length === 1) {\n return;\n }\n const typeName = buildTypeName(parts.slice(0, parts.length - 1));\n const typeSchema = globalSchema.types[typeName];\n if (!typeSchema) {\n return;\n }\n const key = parts[parts.length - 1];\n typeSchema.properties[key] = element;\n}\n\n/**\n * Indexes a bundle of SearchParameter resources for faster lookup.\n * @param bundle A FHIR bundle SearchParameter resources.\n * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.\n */\nexport function indexSearchParameterBundle(bundle: Bundle<SearchParameter>): void {\n for (const entry of bundle.entry as BundleEntry[]) {\n const resource = entry.resource as SearchParameter;\n if (resource.resourceType === 'SearchParameter') {\n indexSearchParameter(resource);\n }\n }\n}\n\n/**\n * Indexes a SearchParameter resource for fast lookup.\n * Indexes by SearchParameter.code, which is the query string parameter name.\n * @param searchParam The SearchParameter resource.\n * @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.\n */\nexport function indexSearchParameter(searchParam: SearchParameter): void {\n if (!searchParam.base) {\n return;\n }\n\n for (const resourceType of searchParam.base) {\n const typeSchema = globalSchema.types[resourceType];\n if (!typeSchema) {\n continue;\n }\n\n if (!typeSchema.searchParams) {\n typeSchema.searchParams = {\n _id: {\n base: [resourceType],\n code: '_id',\n type: 'token',\n expression: resourceType + '.id',\n } as SearchParameter,\n _lastUpdated: {\n base: [resourceType],\n code: '_lastUpdated',\n type: 'date',\n expression: resourceType + '.meta.lastUpdated',\n } as SearchParameter,\n _compartment: {\n base: [resourceType],\n code: '_compartment',\n type: 'reference',\n expression: resourceType + '.meta.compartment',\n } as SearchParameter,\n };\n }\n\n typeSchema.searchParams[searchParam.code as string] = searchParam;\n }\n}\n\nexport function buildTypeName(components: string[]): string {\n if (components.length === 1) {\n return components[0];\n }\n return components.map(capitalize).join('');\n}\n\nexport function getPropertyDisplayName(path: string): string {\n // Get the property name, which is the remainder after the last period\n // For example, for path \"Patient.birthDate\"\n // the property name is \"birthDate\"\n const propertyName = path.replaceAll('[x]', '').split('.').pop() as string;\n\n // Special case for ID\n if (propertyName === 'id') {\n return 'ID';\n }\n\n // Split by capital letters\n // Capitalize the first letter of each word\n // Join together with spaces in between\n // Then normalize whitespace to single space character\n // For example, for property name \"birthDate\",\n // the display name is \"Birth Date\".\n return propertyName\n .split(/(?=[A-Z])/)\n .map(capitalize)\n .join(' ')\n .replace('_', ' ')\n .replace(/\\s+/g, ' ');\n}\n\n/**\n * Returns an element definition by type and property name.\n * Handles content references.\n * @param typeName The type name.\n * @param propertyName The property name.\n * @returns The element definition if found.\n */\nexport function getElementDefinition(typeName: string, propertyName: string): ElementDefinition | undefined {\n const typeSchema = globalSchema.types[typeName];\n if (!typeSchema) {\n return undefined;\n }\n\n const property = typeSchema.properties[propertyName] ?? typeSchema.properties[propertyName + '[x]'];\n if (!property) {\n return undefined;\n }\n\n if (property.contentReference) {\n // Content references start with a \"#\"\n // Remove the \"#\" character\n const contentReference = property.contentReference.substring(1).split('.');\n const referencePropertyName = contentReference.pop() as string;\n const referenceTypeName = buildTypeName(contentReference);\n return getElementDefinition(referenceTypeName, referencePropertyName);\n }\n\n return property;\n}\n\n/**\n * Global schema singleton.\n */\nexport const globalSchema = baseSchema as unknown as IndexedStructureDefinition;\n"],"names":[],"mappings":"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"}
@@ -26,7 +26,7 @@ export declare function resolveId(reference: Reference | undefined): string | un
26
26
  * @param resource The FHIR resource.
27
27
  * @returns True if the resource is a "ProfileResource".
28
28
  */
29
- export declare function isProfileResource(resource: Resource): boolean;
29
+ export declare function isProfileResource(resource: Resource): resource is ProfileResource;
30
30
  /**
31
31
  * Returns a display string for the resource.
32
32
  * @param resource The input resource.
package/dist/esm/utils.js CHANGED
@@ -43,7 +43,7 @@ function isProfileResource(resource) {
43
43
  * @return Human friendly display string.
44
44
  */
45
45
  function getDisplayString(resource) {
46
- var _a, _b;
46
+ var _a;
47
47
  if (isProfileResource(resource)) {
48
48
  const profileName = getProfileResourceDisplayString(resource);
49
49
  if (profileName) {
@@ -58,7 +58,7 @@ function getDisplayString(resource) {
58
58
  }
59
59
  if (resource.resourceType === 'Observation') {
60
60
  if ('code' in resource && ((_a = resource.code) === null || _a === void 0 ? void 0 : _a.text)) {
61
- return (_b = resource.code) === null || _b === void 0 ? void 0 : _b.text;
61
+ return resource.code.text;
62
62
  }
63
63
  }
64
64
  if (resource.resourceType === 'User') {
@@ -101,22 +101,23 @@ function getDeviceDisplayString(device) {
101
101
  * @returns The image URL for the resource or undefined.
102
102
  */
103
103
  function getImageSrc(resource) {
104
- if (isProfileResource(resource)) {
105
- const photos = resource.photo;
106
- if (photos) {
107
- for (const photo of photos) {
108
- const url = getPhotoImageSrc(photo);
109
- if (url) {
110
- return url;
111
- }
104
+ if (!('photo' in resource)) {
105
+ return undefined;
106
+ }
107
+ const photo = resource.photo;
108
+ if (!photo) {
109
+ return undefined;
110
+ }
111
+ if (Array.isArray(photo)) {
112
+ for (const p of photo) {
113
+ const url = getPhotoImageSrc(p);
114
+ if (url) {
115
+ return url;
112
116
  }
113
117
  }
114
118
  }
115
- if (resource.resourceType === 'Bot' && resource.photo) {
116
- const url = getPhotoImageSrc(resource.photo);
117
- if (url) {
118
- return url;
119
- }
119
+ else {
120
+ return getPhotoImageSrc(photo);
120
121
  }
121
122
  return undefined;
122
123
  }
@@ -545,12 +546,7 @@ function matchesRange(value, range, precision) {
545
546
  * @returns True if the two numbers are equal to the given precision.
546
547
  */
547
548
  function preciseEquals(a, b, precision) {
548
- if (precision) {
549
- return Math.abs(a - b) < Math.pow(10, -precision);
550
- }
551
- else {
552
- return a === b;
553
- }
549
+ return toPreciseInteger(a, precision) === toPreciseInteger(b, precision);
554
550
  }
555
551
  /**
556
552
  * Returns true if the first number is less than the second number to the given precision.
@@ -560,12 +556,7 @@ function preciseEquals(a, b, precision) {
560
556
  * @returns True if the first number is less than the second number to the given precision.
561
557
  */
562
558
  function preciseLessThan(a, b, precision) {
563
- if (precision) {
564
- return a < b && Math.abs(a - b) > Math.pow(10, -precision);
565
- }
566
- else {
567
- return a < b;
568
- }
559
+ return toPreciseInteger(a, precision) < toPreciseInteger(b, precision);
569
560
  }
570
561
  /**
571
562
  * Returns true if the first number is greater than the second number to the given precision.
@@ -575,12 +566,7 @@ function preciseLessThan(a, b, precision) {
575
566
  * @returns True if the first number is greater than the second number to the given precision.
576
567
  */
577
568
  function preciseGreaterThan(a, b, precision) {
578
- if (precision) {
579
- return a > b && Math.abs(a - b) > Math.pow(10, -precision);
580
- }
581
- else {
582
- return a > b;
583
- }
569
+ return toPreciseInteger(a, precision) > toPreciseInteger(b, precision);
584
570
  }
585
571
  /**
586
572
  * Returns true if the first number is less than or equal to the second number to the given precision.
@@ -590,7 +576,7 @@ function preciseGreaterThan(a, b, precision) {
590
576
  * @returns True if the first number is less than or equal to the second number to the given precision.
591
577
  */
592
578
  function preciseLessThanOrEquals(a, b, precision) {
593
- return preciseLessThan(a, b, precision) || preciseEquals(a, b, precision);
579
+ return toPreciseInteger(a, precision) <= toPreciseInteger(b, precision);
594
580
  }
595
581
  /**
596
582
  * Returns true if the first number is greater than or equal to the second number to the given precision.
@@ -600,7 +586,20 @@ function preciseLessThanOrEquals(a, b, precision) {
600
586
  * @returns True if the first number is greater than or equal to the second number to the given precision.
601
587
  */
602
588
  function preciseGreaterThanOrEquals(a, b, precision) {
603
- return preciseGreaterThan(a, b, precision) || preciseEquals(a, b, precision);
589
+ return toPreciseInteger(a, precision) >= toPreciseInteger(b, precision);
590
+ }
591
+ /**
592
+ * Returns an integer representation of the number with the given precision.
593
+ * For example, if precision is 2, then 1.2345 will be returned as 123.
594
+ * @param a The number.
595
+ * @param precision Optional precision in number of digits.
596
+ * @returns The integer with the given precision.
597
+ */
598
+ function toPreciseInteger(a, precision) {
599
+ if (precision === undefined) {
600
+ return a;
601
+ }
602
+ return Math.round(a * Math.pow(10, precision));
604
603
  }
605
604
 
606
605
  export { arrayBufferToBase64, arrayBufferToHex, calculateAge, calculateAgeString, capitalize, createReference, deepClone, deepEquals, findObservationInterval, findObservationReferenceRange, getCodeBySystem, getDateProperty, getDisplayString, getExtensionValue, getIdentifier, getImageSrc, getQuestionnaireAnswers, getReferenceString, isEmpty, isLowerCase, isObject, isProfileResource, isStringArray, isUUID, matchesRange, preciseEquals, preciseGreaterThan, preciseGreaterThanOrEquals, preciseLessThan, preciseLessThanOrEquals, resolveId, setCodeBySystem, stringify };