@medplum/core 0.9.25 → 0.9.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +191 -25
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -1
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/esm/base-schema.json.js +4872 -0
- package/dist/esm/base-schema.json.js.map +1 -0
- package/dist/{types → esm}/cache.d.ts +0 -0
- package/dist/esm/cache.js +70 -0
- package/dist/esm/cache.js.map +1 -0
- package/dist/{types → esm}/client.d.ts +21 -13
- package/dist/esm/client.js +1455 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/{types → esm}/crypto.d.ts +0 -0
- package/dist/esm/crypto.js +23 -0
- package/dist/esm/crypto.js.map +1 -0
- package/dist/{types → esm}/eventtarget.d.ts +0 -0
- package/dist/esm/eventtarget.js +41 -0
- package/dist/esm/eventtarget.js.map +1 -0
- package/dist/{types → esm}/fhirpath/atoms.d.ts +0 -0
- package/dist/esm/fhirpath/atoms.js +329 -0
- package/dist/esm/fhirpath/atoms.js.map +1 -0
- package/dist/{types → esm}/fhirpath/date.d.ts +0 -0
- package/dist/esm/fhirpath/date.js +24 -0
- package/dist/esm/fhirpath/date.js.map +1 -0
- package/dist/{types → esm}/fhirpath/functions.d.ts +0 -0
- package/dist/esm/fhirpath/functions.js +1503 -0
- package/dist/esm/fhirpath/functions.js.map +1 -0
- package/dist/{types → esm}/fhirpath/index.d.ts +0 -0
- package/dist/{types → esm}/fhirpath/parse.d.ts +0 -0
- package/dist/esm/fhirpath/parse.js +258 -0
- package/dist/esm/fhirpath/parse.js.map +1 -0
- package/dist/{types → esm}/fhirpath/tokenize.d.ts +0 -0
- package/dist/esm/fhirpath/tokenize.js +185 -0
- package/dist/esm/fhirpath/tokenize.js.map +1 -0
- package/dist/{types → esm}/fhirpath/utils.d.ts +0 -0
- package/dist/esm/fhirpath/utils.js +381 -0
- package/dist/esm/fhirpath/utils.js.map +1 -0
- package/dist/esm/format.d.ts +21 -0
- package/dist/esm/format.js +158 -0
- package/dist/esm/format.js.map +1 -0
- package/dist/{types → esm}/hl7.d.ts +0 -0
- package/dist/esm/hl7.js +111 -0
- package/dist/esm/hl7.js.map +1 -0
- package/dist/{types → esm}/index.d.ts +0 -0
- package/dist/esm/index.js +15 -10763
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/{types → esm}/jwt.d.ts +0 -0
- package/dist/esm/jwt.js +35 -0
- package/dist/esm/jwt.js.map +1 -0
- package/dist/esm/node_modules/tslib/package.json +1 -0
- package/dist/esm/node_modules/tslib/tslib.es6.js +40 -0
- package/dist/esm/node_modules/tslib/tslib.es6.js.map +1 -0
- package/dist/{types → esm}/outcomes.d.ts +7 -0
- package/dist/esm/outcomes.js +190 -0
- package/dist/esm/outcomes.js.map +1 -0
- package/dist/{types → esm}/readablepromise.d.ts +0 -0
- package/dist/esm/readablepromise.js +87 -0
- package/dist/esm/readablepromise.js.map +1 -0
- package/dist/{types → esm}/search.d.ts +0 -0
- package/dist/esm/search.js +207 -0
- package/dist/esm/search.js.map +1 -0
- package/dist/{types → esm}/searchparams.d.ts +0 -0
- package/dist/esm/searchparams.js +145 -0
- package/dist/esm/searchparams.js.map +1 -0
- package/dist/{types → esm}/storage.d.ts +0 -0
- package/dist/esm/storage.js +94 -0
- package/dist/esm/storage.js.map +1 -0
- package/dist/{types → esm}/types.d.ts +0 -0
- package/dist/esm/types.js +223 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/{types → esm}/utils.d.ts +0 -0
- package/dist/esm/utils.js +590 -0
- package/dist/esm/utils.js.map +1 -0
- package/package.json +5 -5
- package/stats.html +4034 -0
- package/cody-pdf-test.js +0 -32
- package/dist/types/format.d.ts +0 -15
- package/wget-log +0 -6
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
const DEFAULT_SEARCH_COUNT = 20;
|
|
2
|
+
/**
|
|
3
|
+
* Search operators.
|
|
4
|
+
* These operators represent "modifiers" and "prefixes" in FHIR search.
|
|
5
|
+
* See: https://www.hl7.org/fhir/search.html
|
|
6
|
+
*/
|
|
7
|
+
var Operator;
|
|
8
|
+
(function (Operator) {
|
|
9
|
+
Operator["EQUALS"] = "eq";
|
|
10
|
+
Operator["NOT_EQUALS"] = "ne";
|
|
11
|
+
// Numbers
|
|
12
|
+
Operator["GREATER_THAN"] = "gt";
|
|
13
|
+
Operator["LESS_THAN"] = "lt";
|
|
14
|
+
Operator["GREATER_THAN_OR_EQUALS"] = "ge";
|
|
15
|
+
Operator["LESS_THAN_OR_EQUALS"] = "le";
|
|
16
|
+
// Dates
|
|
17
|
+
Operator["STARTS_AFTER"] = "sa";
|
|
18
|
+
Operator["ENDS_BEFORE"] = "eb";
|
|
19
|
+
Operator["APPROXIMATELY"] = "ap";
|
|
20
|
+
// String
|
|
21
|
+
Operator["CONTAINS"] = "contains";
|
|
22
|
+
Operator["EXACT"] = "exact";
|
|
23
|
+
// Token
|
|
24
|
+
Operator["TEXT"] = "text";
|
|
25
|
+
Operator["NOT"] = "not";
|
|
26
|
+
Operator["ABOVE"] = "above";
|
|
27
|
+
Operator["BELOW"] = "below";
|
|
28
|
+
Operator["IN"] = "in";
|
|
29
|
+
Operator["NOT_IN"] = "not-in";
|
|
30
|
+
Operator["OF_TYPE"] = "of-type";
|
|
31
|
+
// All
|
|
32
|
+
Operator["MISSING"] = "missing";
|
|
33
|
+
})(Operator || (Operator = {}));
|
|
34
|
+
const MODIFIER_OPERATORS = [
|
|
35
|
+
Operator.CONTAINS,
|
|
36
|
+
Operator.EXACT,
|
|
37
|
+
Operator.TEXT,
|
|
38
|
+
Operator.NOT,
|
|
39
|
+
Operator.ABOVE,
|
|
40
|
+
Operator.BELOW,
|
|
41
|
+
Operator.IN,
|
|
42
|
+
Operator.NOT_IN,
|
|
43
|
+
Operator.OF_TYPE,
|
|
44
|
+
Operator.MISSING,
|
|
45
|
+
];
|
|
46
|
+
const PREFIX_OPERATORS = [
|
|
47
|
+
Operator.NOT_EQUALS,
|
|
48
|
+
Operator.GREATER_THAN,
|
|
49
|
+
Operator.LESS_THAN,
|
|
50
|
+
Operator.GREATER_THAN_OR_EQUALS,
|
|
51
|
+
Operator.LESS_THAN_OR_EQUALS,
|
|
52
|
+
Operator.STARTS_AFTER,
|
|
53
|
+
Operator.ENDS_BEFORE,
|
|
54
|
+
Operator.APPROXIMATELY,
|
|
55
|
+
];
|
|
56
|
+
/**
|
|
57
|
+
* Parses a URL into a SearchRequest.
|
|
58
|
+
*
|
|
59
|
+
* See the FHIR search spec: http://hl7.org/fhir/r4/search.html
|
|
60
|
+
*
|
|
61
|
+
* @param url The URL to parse.
|
|
62
|
+
* @returns Parsed search definition.
|
|
63
|
+
*/
|
|
64
|
+
function parseSearchDefinition(url) {
|
|
65
|
+
const location = new URL(url, 'https://example.com/');
|
|
66
|
+
const resourceType = location.pathname
|
|
67
|
+
.replace(/(^\/)|(\/$)/g, '') // Remove leading and trailing slashes
|
|
68
|
+
.split('/')
|
|
69
|
+
.pop();
|
|
70
|
+
const params = new URLSearchParams(location.search);
|
|
71
|
+
let filters = undefined;
|
|
72
|
+
let sortRules = undefined;
|
|
73
|
+
let fields = undefined;
|
|
74
|
+
let offset = undefined;
|
|
75
|
+
let count = undefined;
|
|
76
|
+
let total = undefined;
|
|
77
|
+
params.forEach((value, key) => {
|
|
78
|
+
if (key === '_fields') {
|
|
79
|
+
fields = value.split(',');
|
|
80
|
+
}
|
|
81
|
+
else if (key === '_offset') {
|
|
82
|
+
offset = parseInt(value);
|
|
83
|
+
}
|
|
84
|
+
else if (key === '_count') {
|
|
85
|
+
count = parseInt(value);
|
|
86
|
+
}
|
|
87
|
+
else if (key === '_total') {
|
|
88
|
+
total = value;
|
|
89
|
+
}
|
|
90
|
+
else if (key === '_sort') {
|
|
91
|
+
sortRules = sortRules || [];
|
|
92
|
+
sortRules.push(parseSortRule(value));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
filters = filters || [];
|
|
96
|
+
filters.push(parseSearchFilter(key, value));
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
return {
|
|
100
|
+
resourceType,
|
|
101
|
+
filters,
|
|
102
|
+
fields,
|
|
103
|
+
offset,
|
|
104
|
+
count,
|
|
105
|
+
total,
|
|
106
|
+
sortRules,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Parses a URL query parameter into a sort rule.
|
|
111
|
+
*
|
|
112
|
+
* By default, the sort rule is the field name.
|
|
113
|
+
*
|
|
114
|
+
* Sort rules can be reversed into descending order by prefixing the field name with a minus sign.
|
|
115
|
+
*
|
|
116
|
+
* See sorting: http://hl7.org/fhir/r4/search.html#_sort
|
|
117
|
+
*
|
|
118
|
+
* @param value The URL parameter value.
|
|
119
|
+
* @returns The parsed sort rule.
|
|
120
|
+
*/
|
|
121
|
+
function parseSortRule(value) {
|
|
122
|
+
if (value.startsWith('-')) {
|
|
123
|
+
return { code: value.substring(1), descending: true };
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
return { code: value };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Parses a URL query parameter into a search filter.
|
|
131
|
+
*
|
|
132
|
+
* FHIR search filters can be specified as modifiers or prefixes.
|
|
133
|
+
*
|
|
134
|
+
* For string properties, modifiers are appended to the key, e.g. "name:contains=eve".
|
|
135
|
+
*
|
|
136
|
+
* For date and numeric properties, prefixes are prepended to the value, e.g. "birthdate=gt2000".
|
|
137
|
+
*
|
|
138
|
+
* See the FHIR search spec: http://hl7.org/fhir/r4/search.html
|
|
139
|
+
*
|
|
140
|
+
* @param key The URL parameter key.
|
|
141
|
+
* @param value The URL parameter value.
|
|
142
|
+
* @returns The parsed search filter.
|
|
143
|
+
*/
|
|
144
|
+
function parseSearchFilter(key, value) {
|
|
145
|
+
let code = key;
|
|
146
|
+
let operator = Operator.EQUALS;
|
|
147
|
+
for (const modifier of MODIFIER_OPERATORS) {
|
|
148
|
+
const modifierIndex = code.indexOf(':' + modifier);
|
|
149
|
+
if (modifierIndex !== -1) {
|
|
150
|
+
operator = modifier;
|
|
151
|
+
code = code.substring(0, modifierIndex);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
for (const prefix of PREFIX_OPERATORS) {
|
|
155
|
+
if (value.match(new RegExp('^' + prefix + '\\d'))) {
|
|
156
|
+
operator = prefix;
|
|
157
|
+
value = value.substring(prefix.length);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return { code, operator, value };
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Formats a search definition object into a query string.
|
|
164
|
+
* Note: The return value does not include the resource type.
|
|
165
|
+
* @param {!SearchRequest} definition The search definition.
|
|
166
|
+
* @returns Formatted URL.
|
|
167
|
+
*/
|
|
168
|
+
function formatSearchQuery(definition) {
|
|
169
|
+
const params = [];
|
|
170
|
+
if (definition.fields) {
|
|
171
|
+
params.push('_fields=' + definition.fields.join(','));
|
|
172
|
+
}
|
|
173
|
+
if (definition.filters) {
|
|
174
|
+
definition.filters.forEach((filter) => params.push(formatFilter(filter)));
|
|
175
|
+
}
|
|
176
|
+
if (definition.sortRules && definition.sortRules.length > 0) {
|
|
177
|
+
params.push(formatSortRules(definition.sortRules));
|
|
178
|
+
}
|
|
179
|
+
if (definition.offset !== undefined) {
|
|
180
|
+
params.push('_offset=' + definition.offset);
|
|
181
|
+
}
|
|
182
|
+
if (definition.count !== undefined) {
|
|
183
|
+
params.push('_count=' + definition.count);
|
|
184
|
+
}
|
|
185
|
+
if (definition.total !== undefined) {
|
|
186
|
+
params.push('_total=' + definition.total);
|
|
187
|
+
}
|
|
188
|
+
if (params.length === 0) {
|
|
189
|
+
return '';
|
|
190
|
+
}
|
|
191
|
+
params.sort();
|
|
192
|
+
return '?' + params.join('&');
|
|
193
|
+
}
|
|
194
|
+
function formatFilter(filter) {
|
|
195
|
+
const modifier = MODIFIER_OPERATORS.includes(filter.operator) ? ':' + filter.operator : '';
|
|
196
|
+
const prefix = PREFIX_OPERATORS.includes(filter.operator) ? filter.operator : '';
|
|
197
|
+
return `${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`;
|
|
198
|
+
}
|
|
199
|
+
function formatSortRules(sortRules) {
|
|
200
|
+
if (!sortRules || sortRules.length === 0) {
|
|
201
|
+
return '';
|
|
202
|
+
}
|
|
203
|
+
return '_sort=' + sortRules.map((sr) => (sr.descending ? '-' + sr.code : sr.code)).join(',');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export { DEFAULT_SEARCH_COUNT, Operator, formatSearchQuery, parseSearchDefinition };
|
|
207
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sources":["../../src/search.ts"],"sourcesContent":["import { ResourceType } from '@medplum/fhirtypes';\n\nexport const DEFAULT_SEARCH_COUNT = 20;\n\nexport interface SearchRequest {\n readonly resourceType: string;\n filters?: Filter[];\n sortRules?: SortRule[];\n offset?: number;\n count?: number;\n fields?: string[];\n name?: string;\n total?: 'none' | 'estimate' | 'accurate';\n}\n\nexport interface Filter {\n code: string;\n operator: Operator;\n value: string;\n unitSystem?: string;\n unitCode?: string;\n}\n\nexport interface SortRule {\n code: string;\n descending?: boolean;\n}\n\n/**\n * Search operators.\n * These operators represent \"modifiers\" and \"prefixes\" in FHIR search.\n * See: https://www.hl7.org/fhir/search.html\n */\nexport enum Operator {\n EQUALS = 'eq',\n NOT_EQUALS = 'ne',\n\n // Numbers\n GREATER_THAN = 'gt',\n LESS_THAN = 'lt',\n GREATER_THAN_OR_EQUALS = 'ge',\n LESS_THAN_OR_EQUALS = 'le',\n\n // Dates\n STARTS_AFTER = 'sa',\n ENDS_BEFORE = 'eb',\n APPROXIMATELY = 'ap',\n\n // String\n CONTAINS = 'contains',\n EXACT = 'exact',\n\n // Token\n TEXT = 'text',\n 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\nconst MODIFIER_OPERATORS: Operator[] = [\n Operator.CONTAINS,\n Operator.EXACT,\n Operator.TEXT,\n Operator.NOT,\n Operator.ABOVE,\n Operator.BELOW,\n Operator.IN,\n Operator.NOT_IN,\n Operator.OF_TYPE,\n Operator.MISSING,\n];\n\nconst PREFIX_OPERATORS: Operator[] = [\n Operator.NOT_EQUALS,\n Operator.GREATER_THAN,\n Operator.LESS_THAN,\n Operator.GREATER_THAN_OR_EQUALS,\n Operator.LESS_THAN_OR_EQUALS,\n Operator.STARTS_AFTER,\n Operator.ENDS_BEFORE,\n Operator.APPROXIMATELY,\n];\n\n/**\n * Parses a URL into a SearchRequest.\n *\n * See the FHIR search spec: http://hl7.org/fhir/r4/search.html\n *\n * @param url The URL to parse.\n * @returns Parsed search definition.\n */\nexport function parseSearchDefinition(url: string): SearchRequest {\n const location = new URL(url, 'https://example.com/');\n const resourceType = location.pathname\n .replace(/(^\\/)|(\\/$)/g, '') // Remove leading and trailing slashes\n .split('/')\n .pop() as ResourceType;\n const params = new URLSearchParams(location.search);\n let filters: Filter[] | undefined = undefined;\n let sortRules: SortRule[] | undefined = undefined;\n let fields: string[] | undefined = undefined;\n let offset = undefined;\n let count = undefined;\n let total = undefined;\n\n params.forEach((value, key) => {\n if (key === '_fields') {\n fields = value.split(',');\n } else if (key === '_offset') {\n offset = parseInt(value);\n } else if (key === '_count') {\n count = parseInt(value);\n } else if (key === '_total') {\n total = value;\n } else if (key === '_sort') {\n sortRules = sortRules || [];\n sortRules.push(parseSortRule(value));\n } else {\n filters = filters || [];\n filters.push(parseSearchFilter(key, value));\n }\n });\n\n return {\n resourceType,\n filters,\n fields,\n offset,\n count,\n total,\n sortRules,\n };\n}\n\n/**\n * Parses a URL query parameter into a sort rule.\n *\n * By default, the sort rule is the field name.\n *\n * Sort rules can be reversed into descending order by prefixing the field name with a minus sign.\n *\n * See sorting: http://hl7.org/fhir/r4/search.html#_sort\n *\n * @param value The URL parameter value.\n * @returns The parsed sort rule.\n */\nfunction parseSortRule(value: string): SortRule {\n if (value.startsWith('-')) {\n return { code: value.substring(1), descending: true };\n } else {\n return { code: value };\n }\n}\n\n/**\n * Parses a URL query parameter into a search filter.\n *\n * FHIR search filters can be specified as modifiers or prefixes.\n *\n * For string properties, modifiers are appended to the key, e.g. \"name:contains=eve\".\n *\n * For date and numeric properties, prefixes are prepended to the value, e.g. \"birthdate=gt2000\".\n *\n * See the FHIR search spec: http://hl7.org/fhir/r4/search.html\n *\n * @param key The URL parameter key.\n * @param value The URL parameter value.\n * @returns The parsed search filter.\n */\nfunction parseSearchFilter(key: string, value: string): Filter {\n let code = key;\n let operator = Operator.EQUALS;\n\n for (const modifier of MODIFIER_OPERATORS) {\n const modifierIndex = code.indexOf(':' + modifier);\n if (modifierIndex !== -1) {\n operator = modifier;\n code = code.substring(0, modifierIndex);\n }\n }\n\n for (const prefix of PREFIX_OPERATORS) {\n if (value.match(new RegExp('^' + prefix + '\\\\d'))) {\n operator = prefix;\n value = value.substring(prefix.length);\n }\n }\n\n return { code, operator, value };\n}\n\n/**\n * Formats a search definition object into a query string.\n * Note: The return value does not include the resource type.\n * @param {!SearchRequest} definition The search definition.\n * @returns Formatted URL.\n */\nexport function formatSearchQuery(definition: SearchRequest): string {\n const params: string[] = [];\n\n if (definition.fields) {\n params.push('_fields=' + definition.fields.join(','));\n }\n\n if (definition.filters) {\n definition.filters.forEach((filter) => params.push(formatFilter(filter)));\n }\n\n if (definition.sortRules && definition.sortRules.length > 0) {\n params.push(formatSortRules(definition.sortRules));\n }\n\n if (definition.offset !== undefined) {\n params.push('_offset=' + definition.offset);\n }\n\n if (definition.count !== undefined) {\n params.push('_count=' + definition.count);\n }\n\n if (definition.total !== undefined) {\n params.push('_total=' + definition.total);\n }\n\n if (params.length === 0) {\n return '';\n }\n\n params.sort();\n return '?' + params.join('&');\n}\n\nfunction formatFilter(filter: Filter): string {\n const modifier = MODIFIER_OPERATORS.includes(filter.operator) ? ':' + filter.operator : '';\n const prefix = PREFIX_OPERATORS.includes(filter.operator) ? filter.operator : '';\n return `${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`;\n}\n\nfunction formatSortRules(sortRules: SortRule[] | undefined): string {\n if (!sortRules || sortRules.length === 0) {\n return '';\n }\n return '_sort=' + sortRules.map((sr) => (sr.descending ? '-' + sr.code : sr.code)).join(',');\n}\n"],"names":[],"mappings":"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"}
|
|
File without changes
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { PropertyType } from './types.js';
|
|
2
|
+
import { capitalize } from './utils.js';
|
|
3
|
+
|
|
4
|
+
var SearchParameterType;
|
|
5
|
+
(function (SearchParameterType) {
|
|
6
|
+
SearchParameterType["BOOLEAN"] = "BOOLEAN";
|
|
7
|
+
SearchParameterType["NUMBER"] = "NUMBER";
|
|
8
|
+
SearchParameterType["QUANTITY"] = "QUANTITY";
|
|
9
|
+
SearchParameterType["TEXT"] = "TEXT";
|
|
10
|
+
SearchParameterType["REFERENCE"] = "REFERENCE";
|
|
11
|
+
SearchParameterType["DATE"] = "DATE";
|
|
12
|
+
SearchParameterType["DATETIME"] = "DATETIME";
|
|
13
|
+
SearchParameterType["PERIOD"] = "PERIOD";
|
|
14
|
+
})(SearchParameterType || (SearchParameterType = {}));
|
|
15
|
+
/**
|
|
16
|
+
* Returns the type details of a SearchParameter.
|
|
17
|
+
*
|
|
18
|
+
* The SearchParameter resource has a "type" parameter, but that is missing some critical information.
|
|
19
|
+
*
|
|
20
|
+
* For example:
|
|
21
|
+
* 1) The "date" type includes "date", "datetime", and "period".
|
|
22
|
+
* 2) The "token" type includes enums and booleans.
|
|
23
|
+
* 3) Arrays/multiple values are not reflected at all.
|
|
24
|
+
*
|
|
25
|
+
* @param structureDefinitions Collection of StructureDefinition resources indexed by name.
|
|
26
|
+
* @param resourceType The root resource type.
|
|
27
|
+
* @param searchParam The search parameter.
|
|
28
|
+
* @returns The search parameter type details.
|
|
29
|
+
*/
|
|
30
|
+
function getSearchParameterDetails(structureDefinitions, resourceType, searchParam) {
|
|
31
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
32
|
+
if (searchParam.code === '_lastUpdated') {
|
|
33
|
+
return { columnName: 'lastUpdated', type: SearchParameterType.DATETIME };
|
|
34
|
+
}
|
|
35
|
+
const columnName = convertCodeToColumnName(searchParam.code);
|
|
36
|
+
const expression = (_a = getExpressionForResourceType(resourceType, searchParam.expression)) === null || _a === void 0 ? void 0 : _a.split('.');
|
|
37
|
+
if (!expression) {
|
|
38
|
+
// This happens on compound types
|
|
39
|
+
// In the future, explore returning multiple column definitions
|
|
40
|
+
return { columnName, type: SearchParameterType.TEXT };
|
|
41
|
+
}
|
|
42
|
+
const defaultType = getSearchParameterType(searchParam);
|
|
43
|
+
let baseType = resourceType;
|
|
44
|
+
let elementDefinition = undefined;
|
|
45
|
+
let propertyType = undefined;
|
|
46
|
+
let array = false;
|
|
47
|
+
for (let i = 1; i < expression.length; i++) {
|
|
48
|
+
const propertyName = expression[i];
|
|
49
|
+
elementDefinition =
|
|
50
|
+
(_d = (_c = (_b = structureDefinitions.types[baseType]) === null || _b === void 0 ? void 0 : _b.properties) === null || _c === void 0 ? void 0 : _c[propertyName]) !== null && _d !== void 0 ? _d : (_f = (_e = structureDefinitions.types[baseType]) === null || _e === void 0 ? void 0 : _e.properties) === null || _f === void 0 ? void 0 : _f[propertyName + '[x]'];
|
|
51
|
+
if (!elementDefinition) {
|
|
52
|
+
throw new Error(`Element definition not found for ${resourceType} ${searchParam.code}`);
|
|
53
|
+
}
|
|
54
|
+
if (elementDefinition.max === '*') {
|
|
55
|
+
array = true;
|
|
56
|
+
}
|
|
57
|
+
propertyType = (_g = elementDefinition.type) === null || _g === void 0 ? void 0 : _g[0].code;
|
|
58
|
+
if (!propertyType) {
|
|
59
|
+
// This happens when one of parent properties uses contentReference
|
|
60
|
+
// In the future, explore following the reference
|
|
61
|
+
return { columnName, type: defaultType, array };
|
|
62
|
+
}
|
|
63
|
+
if (i < expression.length - 1) {
|
|
64
|
+
if (propertyType === 'Element' || propertyType === 'BackboneElement') {
|
|
65
|
+
baseType = baseType + capitalize(propertyName);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
baseType = propertyType;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const type = getSearchParameterType(searchParam, propertyType);
|
|
73
|
+
return { columnName, type, elementDefinition, array };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Converts a hyphen-delimited code to camelCase string.
|
|
77
|
+
* @param code The search parameter code.
|
|
78
|
+
* @returns The SQL column name.
|
|
79
|
+
*/
|
|
80
|
+
function convertCodeToColumnName(code) {
|
|
81
|
+
return code.split('-').reduce((result, word, index) => result + (index ? capitalize(word) : word), '');
|
|
82
|
+
}
|
|
83
|
+
function getSearchParameterType(searchParam, propertyType) {
|
|
84
|
+
let type = SearchParameterType.TEXT;
|
|
85
|
+
switch (searchParam.type) {
|
|
86
|
+
case 'date':
|
|
87
|
+
if (propertyType === PropertyType.dateTime || propertyType === PropertyType.instant) {
|
|
88
|
+
type = SearchParameterType.DATETIME;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
type = SearchParameterType.DATE;
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
case 'number':
|
|
95
|
+
type = SearchParameterType.NUMBER;
|
|
96
|
+
break;
|
|
97
|
+
case 'quantity':
|
|
98
|
+
type = SearchParameterType.QUANTITY;
|
|
99
|
+
break;
|
|
100
|
+
case 'reference':
|
|
101
|
+
type = SearchParameterType.REFERENCE;
|
|
102
|
+
break;
|
|
103
|
+
case 'token':
|
|
104
|
+
if (propertyType === 'boolean') {
|
|
105
|
+
type = SearchParameterType.BOOLEAN;
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
return type;
|
|
110
|
+
}
|
|
111
|
+
function getExpressionForResourceType(resourceType, expression) {
|
|
112
|
+
const expressions = expression.split(' | ');
|
|
113
|
+
for (const e of expressions) {
|
|
114
|
+
if (isIgnoredExpression(e)) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const simplified = simplifyExpression(e);
|
|
118
|
+
if (simplified.startsWith(resourceType + '.')) {
|
|
119
|
+
return simplified;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
function isIgnoredExpression(input) {
|
|
125
|
+
return input.includes(' as Period') || input.includes(' as SampledDate');
|
|
126
|
+
}
|
|
127
|
+
function simplifyExpression(input) {
|
|
128
|
+
let result = input.trim();
|
|
129
|
+
if (result.startsWith('(') && result.endsWith(')')) {
|
|
130
|
+
result = result.substring(1, result.length - 1);
|
|
131
|
+
}
|
|
132
|
+
if (result.includes('[0]')) {
|
|
133
|
+
result = result.replaceAll('[0]', '');
|
|
134
|
+
}
|
|
135
|
+
const stopStrings = [' != ', ' as ', '.as(', '.exists(', '.where('];
|
|
136
|
+
for (const stopString of stopStrings) {
|
|
137
|
+
if (result.includes(stopString)) {
|
|
138
|
+
result = result.substring(0, result.indexOf(stopString));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export { SearchParameterType, getExpressionForResourceType, getSearchParameterDetails };
|
|
145
|
+
//# sourceMappingURL=searchparams.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchparams.js","sources":["../../src/searchparams.ts"],"sourcesContent":["import { ElementDefinition, SearchParameter } from '@medplum/fhirtypes';\nimport { IndexedStructureDefinition, 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 DATE = 'DATE',\n DATETIME = 'DATETIME',\n PERIOD = 'PERIOD',\n}\n\nexport interface SearchParameterDetails {\n readonly columnName: string;\n readonly type: SearchParameterType;\n readonly elementDefinition?: ElementDefinition;\n readonly array?: boolean;\n}\n\n/**\n * Returns the type details of a SearchParameter.\n *\n * The SearchParameter resource has a \"type\" parameter, but that is missing some critical information.\n *\n * For example:\n * 1) The \"date\" type includes \"date\", \"datetime\", and \"period\".\n * 2) The \"token\" type includes enums and booleans.\n * 3) Arrays/multiple values are not reflected at all.\n *\n * @param structureDefinitions Collection of StructureDefinition resources indexed by name.\n * @param resourceType The root resource type.\n * @param searchParam The search parameter.\n * @returns The search parameter type details.\n */\nexport function getSearchParameterDetails(\n structureDefinitions: IndexedStructureDefinition,\n resourceType: string,\n searchParam: SearchParameter\n): SearchParameterDetails {\n if (searchParam.code === '_lastUpdated') {\n return { columnName: 'lastUpdated', type: SearchParameterType.DATETIME };\n }\n\n const columnName = convertCodeToColumnName(searchParam.code as string);\n const expression = getExpressionForResourceType(resourceType, searchParam.expression as string)?.split('.');\n if (!expression) {\n // This happens on compound types\n // In the future, explore returning multiple column definitions\n return { columnName, type: SearchParameterType.TEXT };\n }\n\n 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 =\n structureDefinitions.types[baseType]?.properties?.[propertyName] ??\n structureDefinitions.types[baseType]?.properties?.[propertyName + '[x]'];\n if (!elementDefinition) {\n throw new Error(`Element definition not found for ${resourceType} ${searchParam.code}`);\n }\n\n if (elementDefinition.max === '*') {\n array = true;\n }\n\n propertyType = elementDefinition.type?.[0].code;\n if (!propertyType) {\n // This happens when one of parent properties uses contentReference\n // In the future, explore following the reference\n return { columnName, type: defaultType, array };\n }\n\n if (i < expression.length - 1) {\n if (propertyType === 'Element' || propertyType === 'BackboneElement') {\n baseType = baseType + capitalize(propertyName);\n } else {\n baseType = propertyType;\n }\n }\n }\n\n const type = getSearchParameterType(searchParam, propertyType as PropertyType);\n return { columnName, type, elementDefinition, array };\n}\n\n/**\n * Converts a hyphen-delimited code to camelCase string.\n * @param code The search parameter code.\n * @returns The SQL column name.\n */\nfunction convertCodeToColumnName(code: string): string {\n return code.split('-').reduce((result, word, index) => result + (index ? capitalize(word) : word), '');\n}\n\nfunction getSearchParameterType(searchParam: SearchParameter, propertyType?: PropertyType): SearchParameterType {\n let type = SearchParameterType.TEXT;\n switch (searchParam.type) {\n case 'date':\n if (propertyType === PropertyType.dateTime || propertyType === PropertyType.instant) {\n type = SearchParameterType.DATETIME;\n } else {\n type = SearchParameterType.DATE;\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 type = SearchParameterType.REFERENCE;\n break;\n case 'token':\n if (propertyType === 'boolean') {\n type = SearchParameterType.BOOLEAN;\n }\n break;\n }\n return type;\n}\n\nexport function getExpressionForResourceType(resourceType: string, expression: string): string | undefined {\n const expressions = expression.split(' | ');\n for (const e of expressions) {\n 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(', '.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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"}
|
|
File without changes
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { __classPrivateFieldSet, __classPrivateFieldGet } from './node_modules/tslib/tslib.es6.js';
|
|
2
|
+
import { stringify } from './utils.js';
|
|
3
|
+
|
|
4
|
+
var _ClientStorage_storage, _MemoryStorage_data;
|
|
5
|
+
/**
|
|
6
|
+
* The ClientStorage class is a utility class for storing strings and objects.
|
|
7
|
+
*
|
|
8
|
+
* When using MedplumClient in the browser, it will be backed by browser localStorage.
|
|
9
|
+
*
|
|
10
|
+
* When Using MedplumClient in the server, it will be backed by the MemoryStorage class.
|
|
11
|
+
*/
|
|
12
|
+
class ClientStorage {
|
|
13
|
+
constructor() {
|
|
14
|
+
_ClientStorage_storage.set(this, void 0);
|
|
15
|
+
__classPrivateFieldSet(this, _ClientStorage_storage, typeof localStorage !== 'undefined' ? localStorage : new MemoryStorage(), "f");
|
|
16
|
+
}
|
|
17
|
+
clear() {
|
|
18
|
+
__classPrivateFieldGet(this, _ClientStorage_storage, "f").clear();
|
|
19
|
+
}
|
|
20
|
+
getString(key) {
|
|
21
|
+
return __classPrivateFieldGet(this, _ClientStorage_storage, "f").getItem(key) || undefined;
|
|
22
|
+
}
|
|
23
|
+
setString(key, value) {
|
|
24
|
+
if (value) {
|
|
25
|
+
__classPrivateFieldGet(this, _ClientStorage_storage, "f").setItem(key, value);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
__classPrivateFieldGet(this, _ClientStorage_storage, "f").removeItem(key);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
getObject(key) {
|
|
32
|
+
const str = this.getString(key);
|
|
33
|
+
return str ? JSON.parse(str) : undefined;
|
|
34
|
+
}
|
|
35
|
+
setObject(key, value) {
|
|
36
|
+
this.setString(key, value ? stringify(value) : undefined);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
_ClientStorage_storage = new WeakMap();
|
|
40
|
+
/**
|
|
41
|
+
* The MemoryStorage class is a minimal in-memory implementation of the Storage interface.
|
|
42
|
+
*/
|
|
43
|
+
class MemoryStorage {
|
|
44
|
+
constructor() {
|
|
45
|
+
_MemoryStorage_data.set(this, void 0);
|
|
46
|
+
__classPrivateFieldSet(this, _MemoryStorage_data, new Map(), "f");
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Returns the number of key/value pairs.
|
|
50
|
+
*/
|
|
51
|
+
get length() {
|
|
52
|
+
return __classPrivateFieldGet(this, _MemoryStorage_data, "f").size;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Removes all key/value pairs, if there are any.
|
|
56
|
+
*/
|
|
57
|
+
clear() {
|
|
58
|
+
__classPrivateFieldGet(this, _MemoryStorage_data, "f").clear();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Returns the current value associated with the given key, or null if the given key does not exist.
|
|
62
|
+
*/
|
|
63
|
+
getItem(key) {
|
|
64
|
+
var _a;
|
|
65
|
+
return (_a = __classPrivateFieldGet(this, _MemoryStorage_data, "f").get(key)) !== null && _a !== void 0 ? _a : null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
|
|
69
|
+
*/
|
|
70
|
+
setItem(key, value) {
|
|
71
|
+
if (value) {
|
|
72
|
+
__classPrivateFieldGet(this, _MemoryStorage_data, "f").set(key, value);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
__classPrivateFieldGet(this, _MemoryStorage_data, "f").delete(key);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Removes the key/value pair with the given key, if a key/value pair with the given key exists.
|
|
80
|
+
*/
|
|
81
|
+
removeItem(key) {
|
|
82
|
+
__classPrivateFieldGet(this, _MemoryStorage_data, "f").delete(key);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Returns the name of the nth key, or null if n is greater than or equal to the number of key/value pairs.
|
|
86
|
+
*/
|
|
87
|
+
key(index) {
|
|
88
|
+
return Array.from(__classPrivateFieldGet(this, _MemoryStorage_data, "f").keys())[index];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
_MemoryStorage_data = new WeakMap();
|
|
92
|
+
|
|
93
|
+
export { ClientStorage, MemoryStorage };
|
|
94
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sources":["../../src/storage.ts"],"sourcesContent":["import { stringify } from './utils';\n\n/**\n * The ClientStorage class is a utility class for storing strings and objects.\n *\n * When using MedplumClient in the browser, it will be backed by browser localStorage.\n *\n * When Using MedplumClient in the server, it will be backed by the MemoryStorage class.\n */\nexport class ClientStorage {\n readonly #storage: Storage;\n\n constructor() {\n this.#storage = typeof localStorage !== 'undefined' ? localStorage : new MemoryStorage();\n }\n\n clear(): void {\n this.#storage.clear();\n }\n\n getString(key: string): string | undefined {\n return this.#storage.getItem(key) || undefined;\n }\n\n setString(key: string, value: string | undefined): void {\n if (value) {\n this.#storage.setItem(key, value);\n } else {\n this.#storage.removeItem(key);\n }\n }\n\n getObject<T>(key: string): T | undefined {\n const str = this.getString(key);\n return str ? (JSON.parse(str) as T) : undefined;\n }\n\n setObject<T>(key: string, value: T): void {\n this.setString(key, value ? stringify(value) : undefined);\n }\n}\n\n/**\n * The MemoryStorage class is a minimal in-memory implementation of the Storage interface.\n */\nexport class MemoryStorage implements Storage {\n #data: Map<string, string>;\n\n constructor() {\n this.#data = new Map<string, string>();\n }\n\n /**\n * Returns the number of key/value pairs.\n */\n get length(): number {\n return this.#data.size;\n }\n\n /**\n * Removes all key/value pairs, if there are any.\n */\n clear(): void {\n this.#data.clear();\n }\n\n /**\n * Returns the current value associated with the given key, or null if the given key does not exist.\n */\n getItem(key: string): string | null {\n return this.#data.get(key) ?? null;\n }\n\n /**\n * Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.\n */\n setItem(key: string, value: string | null): void {\n if (value) {\n this.#data.set(key, value);\n } else {\n this.#data.delete(key);\n }\n }\n\n /**\n * Removes the key/value pair with the given key, if a key/value pair with the given key exists.\n */\n removeItem(key: string): void {\n this.#data.delete(key);\n }\n\n /**\n * Returns the name of the nth key, or null if n is greater than or equal to the number of key/value pairs.\n */\n key(index: number): string | null {\n return Array.from(this.#data.keys())[index];\n }\n}\n"],"names":[],"mappings":"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"}
|
|
File without changes
|