@medplum/core 2.0.24 → 2.0.26
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.cjs +28 -14114
- package/dist/cjs/index.cjs.map +7 -1
- package/dist/esm/index.mjs +31 -29
- package/dist/esm/index.mjs.map +7 -1
- package/dist/types/client.d.ts +42 -10
- package/dist/types/fhirpath/atoms.d.ts +25 -11
- package/dist/types/fhirpath/parse.d.ts +33 -33
- package/dist/types/index.d.ts +1 -1
- package/dist/types/jwt.d.ts +6 -0
- package/dist/types/schema.d.ts +1 -0
- package/dist/types/search/details.d.ts +3 -1
- package/dist/types/types.d.ts +2 -2
- package/dist/types/typeschema/validation.d.ts +1 -1
- package/dist/types/utils.d.ts +15 -0
- package/package.json +5 -2
- package/dist/cjs/index.min.cjs +0 -1
- package/dist/esm/access.mjs +0 -142
- package/dist/esm/access.mjs.map +0 -1
- package/dist/esm/base-schema.json.mjs +0 -4408
- package/dist/esm/base-schema.json.mjs.map +0 -1
- package/dist/esm/base64.mjs +0 -33
- package/dist/esm/base64.mjs.map +0 -1
- package/dist/esm/bundle.mjs +0 -36
- package/dist/esm/bundle.mjs.map +0 -1
- package/dist/esm/cache.mjs +0 -64
- package/dist/esm/cache.mjs.map +0 -1
- package/dist/esm/client.mjs +0 -2168
- package/dist/esm/client.mjs.map +0 -1
- package/dist/esm/crypto.mjs +0 -22
- package/dist/esm/crypto.mjs.map +0 -1
- package/dist/esm/eventtarget.mjs +0 -36
- package/dist/esm/eventtarget.mjs.map +0 -1
- package/dist/esm/fhirlexer/parse.mjs +0 -122
- package/dist/esm/fhirlexer/parse.mjs.map +0 -1
- package/dist/esm/fhirlexer/tokenize.mjs +0 -231
- package/dist/esm/fhirlexer/tokenize.mjs.map +0 -1
- package/dist/esm/fhirmapper/parse.mjs +0 -329
- package/dist/esm/fhirmapper/parse.mjs.map +0 -1
- package/dist/esm/fhirmapper/tokenize.mjs +0 -13
- package/dist/esm/fhirmapper/tokenize.mjs.map +0 -1
- package/dist/esm/fhirpath/atoms.mjs +0 -347
- package/dist/esm/fhirpath/atoms.mjs.map +0 -1
- package/dist/esm/fhirpath/date.mjs +0 -24
- package/dist/esm/fhirpath/date.mjs.map +0 -1
- package/dist/esm/fhirpath/functions.mjs +0 -1626
- package/dist/esm/fhirpath/functions.mjs.map +0 -1
- package/dist/esm/fhirpath/parse.mjs +0 -145
- package/dist/esm/fhirpath/parse.mjs.map +0 -1
- package/dist/esm/fhirpath/tokenize.mjs +0 -10
- package/dist/esm/fhirpath/tokenize.mjs.map +0 -1
- package/dist/esm/fhirpath/utils.mjs +0 -377
- package/dist/esm/fhirpath/utils.mjs.map +0 -1
- package/dist/esm/filter/parse.mjs +0 -101
- package/dist/esm/filter/parse.mjs.map +0 -1
- package/dist/esm/filter/tokenize.mjs +0 -16
- package/dist/esm/filter/tokenize.mjs.map +0 -1
- package/dist/esm/filter/types.mjs +0 -34
- package/dist/esm/filter/types.mjs.map +0 -1
- package/dist/esm/format.mjs +0 -390
- package/dist/esm/format.mjs.map +0 -1
- package/dist/esm/hl7.mjs +0 -242
- package/dist/esm/hl7.mjs.map +0 -1
- package/dist/esm/index.min.mjs +0 -1
- package/dist/esm/jwt.mjs +0 -30
- package/dist/esm/jwt.mjs.map +0 -1
- package/dist/esm/node_modules/tslib/package.json +0 -1
- package/dist/esm/outcomes.mjs +0 -295
- package/dist/esm/outcomes.mjs.map +0 -1
- package/dist/esm/readablepromise.mjs +0 -82
- package/dist/esm/readablepromise.mjs.map +0 -1
- package/dist/esm/schema.mjs +0 -417
- package/dist/esm/schema.mjs.map +0 -1
- package/dist/esm/search/details.mjs +0 -162
- package/dist/esm/search/details.mjs.map +0 -1
- package/dist/esm/search/match.mjs +0 -166
- package/dist/esm/search/match.mjs.map +0 -1
- package/dist/esm/search/search.mjs +0 -378
- package/dist/esm/search/search.mjs.map +0 -1
- package/dist/esm/sftp.mjs +0 -24
- package/dist/esm/sftp.mjs.map +0 -1
- package/dist/esm/storage.mjs +0 -95
- package/dist/esm/storage.mjs.map +0 -1
- package/dist/esm/types.mjs +0 -370
- package/dist/esm/types.mjs.map +0 -1
- package/dist/esm/typeschema/types.mjs +0 -278
- package/dist/esm/typeschema/types.mjs.map +0 -1
- package/dist/esm/typeschema/validation.mjs +0 -262
- package/dist/esm/typeschema/validation.mjs.map +0 -1
- package/dist/esm/utils.mjs +0 -632
- package/dist/esm/utils.mjs.map +0 -1
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { globalSchema } from '../types.mjs';
|
|
2
|
-
import '../utils.mjs';
|
|
3
|
-
import { evalFhirPath } from '../fhirpath/parse.mjs';
|
|
4
|
-
import { getSearchParameterDetails, SearchParameterType } from './details.mjs';
|
|
5
|
-
import { Operator } from './search.mjs';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Determines if the resource matches the search request.
|
|
9
|
-
* @param resource The resource that was created or updated.
|
|
10
|
-
* @param searchRequest The subscription criteria as a search request.
|
|
11
|
-
* @returns True if the resource satisfies the search request.
|
|
12
|
-
*/
|
|
13
|
-
function matchesSearchRequest(resource, searchRequest) {
|
|
14
|
-
if (searchRequest.resourceType !== resource.resourceType) {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
if (searchRequest.filters) {
|
|
18
|
-
for (const filter of searchRequest.filters) {
|
|
19
|
-
if (!matchesSearchFilter(resource, searchRequest, filter)) {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Determines if the resource matches the search filter.
|
|
28
|
-
* @param resource The resource that was created or updated.
|
|
29
|
-
* @param searchRequest The search request.
|
|
30
|
-
* @param filter One of the filters of a subscription criteria.
|
|
31
|
-
* @returns True if the resource satisfies the search filter.
|
|
32
|
-
*/
|
|
33
|
-
function matchesSearchFilter(resource, searchRequest, filter) {
|
|
34
|
-
const searchParam = globalSchema.types[searchRequest.resourceType].searchParams?.[filter.code];
|
|
35
|
-
switch (searchParam?.type) {
|
|
36
|
-
case 'reference':
|
|
37
|
-
return matchesReferenceFilter(resource, filter, searchParam);
|
|
38
|
-
case 'string':
|
|
39
|
-
case 'uri':
|
|
40
|
-
return matchesStringFilter(resource, filter, searchParam);
|
|
41
|
-
case 'token':
|
|
42
|
-
return matchesTokenFilter(resource, filter, searchParam);
|
|
43
|
-
case 'date':
|
|
44
|
-
return matchesDateFilter(resource, filter, searchParam);
|
|
45
|
-
default:
|
|
46
|
-
// Unknown search parameter or search parameter type
|
|
47
|
-
// Default fail the check
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function matchesReferenceFilter(resource, filter, searchParam) {
|
|
52
|
-
const values = evalFhirPath(searchParam.expression, resource);
|
|
53
|
-
const negated = isNegated(filter.operator);
|
|
54
|
-
if (filter.value === '' && values.length === 0) {
|
|
55
|
-
// If the filter operator is "equals", then the filter matches.
|
|
56
|
-
// If the filter operator is "not equals", then the filter does not match.
|
|
57
|
-
return filter.operator === Operator.EQUALS;
|
|
58
|
-
}
|
|
59
|
-
// Normalize the values array into reference strings
|
|
60
|
-
const references = values.map((value) => (typeof value === 'string' ? value : value.reference));
|
|
61
|
-
for (const filterValue of filter.value.split(',')) {
|
|
62
|
-
let match = references.includes(filterValue);
|
|
63
|
-
if (!match && filter.code === '_compartment') {
|
|
64
|
-
// Backwards compability for compartment search parameter
|
|
65
|
-
// In previous versions, the resource type was not required in compartment values
|
|
66
|
-
// So, "123" would match "Patient/123"
|
|
67
|
-
// We need to maintain this behavior for backwards compatibility
|
|
68
|
-
match = references.some((reference) => reference?.endsWith('/' + filterValue));
|
|
69
|
-
}
|
|
70
|
-
if (match) {
|
|
71
|
-
return !negated;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// If "not equals" and no matches, then return true
|
|
75
|
-
// If "equals" and no matches, then return false
|
|
76
|
-
return negated;
|
|
77
|
-
}
|
|
78
|
-
function matchesTokenFilter(resource, filter, searchParam) {
|
|
79
|
-
const details = getSearchParameterDetails(resource.resourceType, searchParam);
|
|
80
|
-
if (details.type === SearchParameterType.BOOLEAN) {
|
|
81
|
-
return matchesBooleanFilter(resource, filter, searchParam);
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
return matchesStringFilter(resource, filter, searchParam, true);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
function matchesBooleanFilter(resource, filter, searchParam) {
|
|
88
|
-
const values = evalFhirPath(searchParam.expression, resource);
|
|
89
|
-
const expected = filter.value === 'true';
|
|
90
|
-
const result = values.includes(expected);
|
|
91
|
-
return isNegated(filter.operator) ? !result : result;
|
|
92
|
-
}
|
|
93
|
-
function matchesStringFilter(resource, filter, searchParam, asToken) {
|
|
94
|
-
const resourceValues = evalFhirPath(searchParam.expression, resource);
|
|
95
|
-
const filterValues = filter.value.split(',');
|
|
96
|
-
const negated = isNegated(filter.operator);
|
|
97
|
-
for (const resourceValue of resourceValues) {
|
|
98
|
-
for (const filterValue of filterValues) {
|
|
99
|
-
const match = matchesStringValue(resourceValue, filter.operator, filterValue, asToken);
|
|
100
|
-
if (match) {
|
|
101
|
-
return !negated;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
// If "not equals" and no matches, then return true
|
|
106
|
-
// If "equals" and no matches, then return false
|
|
107
|
-
return negated;
|
|
108
|
-
}
|
|
109
|
-
function matchesStringValue(resourceValue, operator, filterValue, asToken) {
|
|
110
|
-
if (asToken && filterValue.includes('|')) {
|
|
111
|
-
const [system, code] = filterValue.split('|');
|
|
112
|
-
return (matchesStringValue(resourceValue, operator, system, false) &&
|
|
113
|
-
(!code || matchesStringValue(resourceValue, operator, code, false)));
|
|
114
|
-
}
|
|
115
|
-
let str = '';
|
|
116
|
-
if (resourceValue) {
|
|
117
|
-
if (typeof resourceValue === 'string') {
|
|
118
|
-
str = resourceValue;
|
|
119
|
-
}
|
|
120
|
-
else if (typeof resourceValue === 'object') {
|
|
121
|
-
str = JSON.stringify(resourceValue);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return str.toLowerCase().includes(filterValue.toLowerCase());
|
|
125
|
-
}
|
|
126
|
-
function matchesDateFilter(resource, filter, searchParam) {
|
|
127
|
-
const resourceValues = evalFhirPath(searchParam.expression, resource);
|
|
128
|
-
const filterValues = filter.value.split(',');
|
|
129
|
-
const negated = isNegated(filter.operator);
|
|
130
|
-
for (const resourceValue of resourceValues) {
|
|
131
|
-
for (const filterValue of filterValues) {
|
|
132
|
-
const match = matchesDateValue(resourceValue, filter.operator, filterValue);
|
|
133
|
-
if (match) {
|
|
134
|
-
return !negated;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
// If "not equals" and no matches, then return true
|
|
139
|
-
// If "equals" and no matches, then return false
|
|
140
|
-
return negated;
|
|
141
|
-
}
|
|
142
|
-
function matchesDateValue(resourceValue, operator, filterValue) {
|
|
143
|
-
switch (operator) {
|
|
144
|
-
case Operator.STARTS_AFTER:
|
|
145
|
-
case Operator.GREATER_THAN:
|
|
146
|
-
return resourceValue > filterValue;
|
|
147
|
-
case Operator.GREATER_THAN_OR_EQUALS:
|
|
148
|
-
return resourceValue >= filterValue;
|
|
149
|
-
case Operator.ENDS_BEFORE:
|
|
150
|
-
case Operator.LESS_THAN:
|
|
151
|
-
return resourceValue < filterValue;
|
|
152
|
-
case Operator.LESS_THAN_OR_EQUALS:
|
|
153
|
-
return resourceValue <= filterValue;
|
|
154
|
-
case Operator.EQUALS:
|
|
155
|
-
case Operator.NOT_EQUALS:
|
|
156
|
-
return resourceValue === filterValue;
|
|
157
|
-
default:
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
function isNegated(operator) {
|
|
162
|
-
return operator === Operator.NOT_EQUALS || operator === Operator.NOT;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export { matchesSearchRequest };
|
|
166
|
-
//# sourceMappingURL=match.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"match.mjs","sources":["../../../src/search/match.ts"],"sourcesContent":["import { Reference, Resource, SearchParameter } from '@medplum/fhirtypes';\nimport { evalFhirPath } from '../fhirpath';\nimport { globalSchema } from '../types';\nimport { SearchParameterType, getSearchParameterDetails } from './details';\nimport { Filter, Operator, SearchRequest } from './search';\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 searchRequest The search request.\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 case 'uri':\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 default:\n // Unknown search parameter or search parameter type\n // Default fail the check\n return false;\n }\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, true);\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(\n resource: Resource,\n filter: Filter,\n searchParam: SearchParameter,\n asToken?: boolean\n): 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, asToken);\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(\n resourceValue: unknown,\n operator: Operator,\n filterValue: string,\n asToken?: boolean\n): boolean {\n if (asToken && filterValue.includes('|')) {\n const [system, code] = filterValue.split('|');\n return (\n matchesStringValue(resourceValue, operator, system, false) &&\n (!code || matchesStringValue(resourceValue, operator, code, false))\n );\n }\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 default:\n return false;\n }\n}\n\nfunction isNegated(operator: Operator): boolean {\n return operator === Operator.NOT_EQUALS || operator === Operator.NOT;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
import { globalSchema } from '../types.mjs';
|
|
2
|
-
import { OperationOutcomeError, badRequest } from '../outcomes.mjs';
|
|
3
|
-
|
|
4
|
-
const DEFAULT_SEARCH_COUNT = 20;
|
|
5
|
-
/**
|
|
6
|
-
* Search operators.
|
|
7
|
-
* These operators represent "modifiers" and "prefixes" in FHIR search.
|
|
8
|
-
* See: https://www.hl7.org/fhir/search.html
|
|
9
|
-
*/
|
|
10
|
-
var Operator;
|
|
11
|
-
(function (Operator) {
|
|
12
|
-
Operator["EQUALS"] = "eq";
|
|
13
|
-
Operator["NOT_EQUALS"] = "ne";
|
|
14
|
-
// Numbers
|
|
15
|
-
Operator["GREATER_THAN"] = "gt";
|
|
16
|
-
Operator["LESS_THAN"] = "lt";
|
|
17
|
-
Operator["GREATER_THAN_OR_EQUALS"] = "ge";
|
|
18
|
-
Operator["LESS_THAN_OR_EQUALS"] = "le";
|
|
19
|
-
// Dates
|
|
20
|
-
Operator["STARTS_AFTER"] = "sa";
|
|
21
|
-
Operator["ENDS_BEFORE"] = "eb";
|
|
22
|
-
Operator["APPROXIMATELY"] = "ap";
|
|
23
|
-
// String
|
|
24
|
-
Operator["CONTAINS"] = "contains";
|
|
25
|
-
Operator["EXACT"] = "exact";
|
|
26
|
-
// Token
|
|
27
|
-
Operator["TEXT"] = "text";
|
|
28
|
-
Operator["NOT"] = "not";
|
|
29
|
-
Operator["ABOVE"] = "above";
|
|
30
|
-
Operator["BELOW"] = "below";
|
|
31
|
-
Operator["IN"] = "in";
|
|
32
|
-
Operator["NOT_IN"] = "not-in";
|
|
33
|
-
Operator["OF_TYPE"] = "of-type";
|
|
34
|
-
// All
|
|
35
|
-
Operator["MISSING"] = "missing";
|
|
36
|
-
// Reference
|
|
37
|
-
Operator["IDENTIFIER"] = "identifier";
|
|
38
|
-
// _include and _revinclude
|
|
39
|
-
Operator["ITERATE"] = "iterate";
|
|
40
|
-
})(Operator || (Operator = {}));
|
|
41
|
-
/**
|
|
42
|
-
* Parameter names may specify a modifier as a suffix.
|
|
43
|
-
* The modifiers are separated from the parameter name by a colon.
|
|
44
|
-
* See: https://www.hl7.org/fhir/search.html#modifiers
|
|
45
|
-
*/
|
|
46
|
-
const MODIFIER_OPERATORS = {
|
|
47
|
-
contains: Operator.CONTAINS,
|
|
48
|
-
exact: Operator.EXACT,
|
|
49
|
-
above: Operator.ABOVE,
|
|
50
|
-
below: Operator.BELOW,
|
|
51
|
-
text: Operator.TEXT,
|
|
52
|
-
not: Operator.NOT,
|
|
53
|
-
in: Operator.IN,
|
|
54
|
-
'not-in': Operator.NOT_IN,
|
|
55
|
-
'of-type': Operator.OF_TYPE,
|
|
56
|
-
missing: Operator.MISSING,
|
|
57
|
-
identifier: Operator.IDENTIFIER,
|
|
58
|
-
iterate: Operator.ITERATE,
|
|
59
|
-
};
|
|
60
|
-
/**
|
|
61
|
-
* For the ordered parameter types of number, date, and quantity,
|
|
62
|
-
* a prefix to the parameter value may be used to control the nature
|
|
63
|
-
* of the matching.
|
|
64
|
-
* See: https://www.hl7.org/fhir/search.html#prefix
|
|
65
|
-
*/
|
|
66
|
-
const PREFIX_OPERATORS = {
|
|
67
|
-
eq: Operator.EQUALS,
|
|
68
|
-
ne: Operator.NOT_EQUALS,
|
|
69
|
-
lt: Operator.LESS_THAN,
|
|
70
|
-
le: Operator.LESS_THAN_OR_EQUALS,
|
|
71
|
-
gt: Operator.GREATER_THAN,
|
|
72
|
-
ge: Operator.GREATER_THAN_OR_EQUALS,
|
|
73
|
-
sa: Operator.STARTS_AFTER,
|
|
74
|
-
eb: Operator.ENDS_BEFORE,
|
|
75
|
-
ap: Operator.APPROXIMATELY,
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Parses a search URL into a search request.
|
|
79
|
-
* @param resourceType The FHIR resource type.
|
|
80
|
-
* @param query The collection of query string parameters.
|
|
81
|
-
* @returns A parsed SearchRequest.
|
|
82
|
-
*/
|
|
83
|
-
function parseSearchRequest(resourceType, query) {
|
|
84
|
-
const queryArray = [];
|
|
85
|
-
for (const [key, value] of Object.entries(query)) {
|
|
86
|
-
if (Array.isArray(value)) {
|
|
87
|
-
for (const v of value) {
|
|
88
|
-
queryArray.push([key, v]);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
queryArray.push([key, value || '']);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return parseSearchImpl(resourceType, queryArray);
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Parses a search URL into a search request.
|
|
99
|
-
* @param url The search URL.
|
|
100
|
-
* @returns A parsed SearchRequest.
|
|
101
|
-
*/
|
|
102
|
-
function parseSearchUrl(url) {
|
|
103
|
-
const resourceType = url.pathname.split('/').filter(Boolean).pop();
|
|
104
|
-
return parseSearchImpl(resourceType, url.searchParams.entries());
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Parses a URL string into a SearchRequest.
|
|
108
|
-
* @param url The URL to parse.
|
|
109
|
-
* @returns Parsed search definition.
|
|
110
|
-
*/
|
|
111
|
-
function parseSearchDefinition(url) {
|
|
112
|
-
return parseSearchUrl(new URL(url, 'https://example.com/'));
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Parses a FHIR criteria string into a SearchRequest.
|
|
116
|
-
* FHIR criteria strings are found on resources such as Subscription.
|
|
117
|
-
* @param criteria The FHIR criteria string.
|
|
118
|
-
* @returns Parsed search definition.
|
|
119
|
-
*/
|
|
120
|
-
function parseCriteriaAsSearchRequest(criteria) {
|
|
121
|
-
return parseSearchUrl(new URL(criteria, 'https://api.medplum.com/'));
|
|
122
|
-
}
|
|
123
|
-
function parseSearchImpl(resourceType, query) {
|
|
124
|
-
const searchRequest = {
|
|
125
|
-
resourceType,
|
|
126
|
-
};
|
|
127
|
-
for (const [key, value] of query) {
|
|
128
|
-
parseKeyValue(searchRequest, key, value);
|
|
129
|
-
}
|
|
130
|
-
return searchRequest;
|
|
131
|
-
}
|
|
132
|
-
function parseKeyValue(searchRequest, key, value) {
|
|
133
|
-
let code;
|
|
134
|
-
let modifier;
|
|
135
|
-
const colonIndex = key.indexOf(':');
|
|
136
|
-
if (colonIndex >= 0) {
|
|
137
|
-
code = key.substring(0, colonIndex);
|
|
138
|
-
modifier = key.substring(colonIndex + 1);
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
code = key;
|
|
142
|
-
modifier = '';
|
|
143
|
-
}
|
|
144
|
-
switch (code) {
|
|
145
|
-
case '_sort':
|
|
146
|
-
parseSortRule(searchRequest, value);
|
|
147
|
-
break;
|
|
148
|
-
case '_count':
|
|
149
|
-
searchRequest.count = parseInt(value, 10);
|
|
150
|
-
break;
|
|
151
|
-
case '_offset':
|
|
152
|
-
searchRequest.offset = parseInt(value, 10);
|
|
153
|
-
break;
|
|
154
|
-
case '_total':
|
|
155
|
-
searchRequest.total = value;
|
|
156
|
-
break;
|
|
157
|
-
case '_summary':
|
|
158
|
-
searchRequest.total = 'accurate';
|
|
159
|
-
searchRequest.count = 0;
|
|
160
|
-
break;
|
|
161
|
-
case '_include': {
|
|
162
|
-
const target = parseIncludeTarget(value);
|
|
163
|
-
if (modifier === 'iterate') {
|
|
164
|
-
target.modifier = Operator.ITERATE;
|
|
165
|
-
}
|
|
166
|
-
if (searchRequest.include) {
|
|
167
|
-
searchRequest.include.push(target);
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
searchRequest.include = [target];
|
|
171
|
-
}
|
|
172
|
-
break;
|
|
173
|
-
}
|
|
174
|
-
case '_revinclude': {
|
|
175
|
-
const target = parseIncludeTarget(value);
|
|
176
|
-
if (modifier === 'iterate') {
|
|
177
|
-
target.modifier = Operator.ITERATE;
|
|
178
|
-
}
|
|
179
|
-
if (searchRequest.revInclude) {
|
|
180
|
-
searchRequest.revInclude.push(target);
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
searchRequest.revInclude = [target];
|
|
184
|
-
}
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
case '_fields':
|
|
188
|
-
searchRequest.fields = value.split(',');
|
|
189
|
-
break;
|
|
190
|
-
default: {
|
|
191
|
-
const param = globalSchema.types[searchRequest.resourceType]?.searchParams?.[code];
|
|
192
|
-
if (param) {
|
|
193
|
-
parseParameter(searchRequest, param, modifier, value);
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
parseUnknownParameter(searchRequest, code, modifier, value);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
function parseSortRule(searchRequest, value) {
|
|
202
|
-
for (const field of value.split(',')) {
|
|
203
|
-
let code;
|
|
204
|
-
let descending = false;
|
|
205
|
-
if (field.startsWith('-')) {
|
|
206
|
-
code = field.substring(1);
|
|
207
|
-
descending = true;
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
code = field;
|
|
211
|
-
}
|
|
212
|
-
if (!searchRequest.sortRules) {
|
|
213
|
-
searchRequest.sortRules = [];
|
|
214
|
-
}
|
|
215
|
-
searchRequest.sortRules.push({ code, descending });
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
function parseParameter(searchRequest, searchParam, modifier, value) {
|
|
219
|
-
if (modifier === 'missing') {
|
|
220
|
-
addFilter(searchRequest, {
|
|
221
|
-
code: searchParam.code,
|
|
222
|
-
operator: Operator.MISSING,
|
|
223
|
-
value,
|
|
224
|
-
});
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
switch (searchParam.type) {
|
|
228
|
-
case 'number':
|
|
229
|
-
case 'date':
|
|
230
|
-
parsePrefixType(searchRequest, searchParam, value);
|
|
231
|
-
break;
|
|
232
|
-
case 'reference':
|
|
233
|
-
case 'string':
|
|
234
|
-
case 'token':
|
|
235
|
-
case 'uri':
|
|
236
|
-
parseModifierType(searchRequest, searchParam, modifier, value);
|
|
237
|
-
break;
|
|
238
|
-
case 'quantity':
|
|
239
|
-
parseQuantity(searchRequest, searchParam, value);
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
function parsePrefixType(searchRequest, param, input) {
|
|
244
|
-
const { operator, value } = parsePrefix(input);
|
|
245
|
-
addFilter(searchRequest, {
|
|
246
|
-
code: param.code,
|
|
247
|
-
operator,
|
|
248
|
-
value,
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
function parseModifierType(searchRequest, param, modifier, value) {
|
|
252
|
-
addFilter(searchRequest, {
|
|
253
|
-
code: param.code,
|
|
254
|
-
operator: parseModifier(modifier),
|
|
255
|
-
value,
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
function parseQuantity(searchRequest, param, input) {
|
|
259
|
-
const [prefixNumber, unitSystem, unitCode] = input.split('|');
|
|
260
|
-
const { operator, value } = parsePrefix(prefixNumber);
|
|
261
|
-
addFilter(searchRequest, {
|
|
262
|
-
code: param.code,
|
|
263
|
-
operator,
|
|
264
|
-
value,
|
|
265
|
-
unitSystem,
|
|
266
|
-
unitCode,
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
function parseUnknownParameter(searchRequest, code, modifier, value) {
|
|
270
|
-
let operator = Operator.EQUALS;
|
|
271
|
-
if (modifier) {
|
|
272
|
-
operator = modifier;
|
|
273
|
-
}
|
|
274
|
-
else if (value.length >= 2) {
|
|
275
|
-
const prefix = value.substring(0, 2);
|
|
276
|
-
if (prefix in PREFIX_OPERATORS) {
|
|
277
|
-
if (value.length === 2 || value.at(2)?.match(/\d/)) {
|
|
278
|
-
operator = prefix;
|
|
279
|
-
value = value.substring(prefix.length);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
addFilter(searchRequest, {
|
|
284
|
-
code,
|
|
285
|
-
operator,
|
|
286
|
-
value,
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
function parsePrefix(input) {
|
|
290
|
-
const prefix = input.substring(0, 2);
|
|
291
|
-
const prefixOperator = PREFIX_OPERATORS[prefix];
|
|
292
|
-
if (prefixOperator) {
|
|
293
|
-
return { operator: prefixOperator, value: input.substring(2) };
|
|
294
|
-
}
|
|
295
|
-
return { operator: Operator.EQUALS, value: input };
|
|
296
|
-
}
|
|
297
|
-
function parseModifier(modifier) {
|
|
298
|
-
return MODIFIER_OPERATORS[modifier] || Operator.EQUALS;
|
|
299
|
-
}
|
|
300
|
-
function parseIncludeTarget(input) {
|
|
301
|
-
const parts = input.split(':');
|
|
302
|
-
parts.forEach((p) => {
|
|
303
|
-
if (p === '*') {
|
|
304
|
-
throw new OperationOutcomeError(badRequest(`'*' is not supported as a value for search inclusion parameters`));
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
if (parts.length === 1) {
|
|
308
|
-
// Full wildcard, not currently supported
|
|
309
|
-
throw new OperationOutcomeError(badRequest(`Invalid include value '${input}': must be of the form ResourceType:search-parameter`));
|
|
310
|
-
}
|
|
311
|
-
else if (parts.length === 2) {
|
|
312
|
-
return {
|
|
313
|
-
resourceType: parts[0],
|
|
314
|
-
searchParam: parts[1],
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
else if (parts.length === 3) {
|
|
318
|
-
return {
|
|
319
|
-
resourceType: parts[0],
|
|
320
|
-
searchParam: parts[1],
|
|
321
|
-
targetType: parts[2],
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
else {
|
|
325
|
-
throw new OperationOutcomeError(badRequest(`Invalid include value '${input}'`));
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
function addFilter(searchRequest, filter) {
|
|
329
|
-
if (searchRequest.filters) {
|
|
330
|
-
searchRequest.filters.push(filter);
|
|
331
|
-
}
|
|
332
|
-
else {
|
|
333
|
-
searchRequest.filters = [filter];
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Formats a search definition object into a query string.
|
|
338
|
-
* Note: The return value does not include the resource type.
|
|
339
|
-
* @param definition The search definition.
|
|
340
|
-
* @returns Formatted URL.
|
|
341
|
-
*/
|
|
342
|
-
function formatSearchQuery(definition) {
|
|
343
|
-
const params = [];
|
|
344
|
-
if (definition.fields) {
|
|
345
|
-
params.push('_fields=' + definition.fields.join(','));
|
|
346
|
-
}
|
|
347
|
-
if (definition.filters) {
|
|
348
|
-
definition.filters.forEach((filter) => params.push(formatFilter(filter)));
|
|
349
|
-
}
|
|
350
|
-
if (definition.sortRules && definition.sortRules.length > 0) {
|
|
351
|
-
params.push(formatSortRules(definition.sortRules));
|
|
352
|
-
}
|
|
353
|
-
if (definition.offset !== undefined) {
|
|
354
|
-
params.push('_offset=' + definition.offset);
|
|
355
|
-
}
|
|
356
|
-
if (definition.count !== undefined) {
|
|
357
|
-
params.push('_count=' + definition.count);
|
|
358
|
-
}
|
|
359
|
-
if (definition.total !== undefined) {
|
|
360
|
-
params.push('_total=' + definition.total);
|
|
361
|
-
}
|
|
362
|
-
if (params.length === 0) {
|
|
363
|
-
return '';
|
|
364
|
-
}
|
|
365
|
-
params.sort();
|
|
366
|
-
return '?' + params.join('&');
|
|
367
|
-
}
|
|
368
|
-
function formatFilter(filter) {
|
|
369
|
-
const modifier = filter.operator in MODIFIER_OPERATORS ? ':' + filter.operator : '';
|
|
370
|
-
const prefix = filter.operator !== Operator.EQUALS && filter.operator in PREFIX_OPERATORS ? filter.operator : '';
|
|
371
|
-
return `${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`;
|
|
372
|
-
}
|
|
373
|
-
function formatSortRules(sortRules) {
|
|
374
|
-
return '_sort=' + sortRules.map((sr) => (sr.descending ? '-' + sr.code : sr.code)).join(',');
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
export { DEFAULT_SEARCH_COUNT, Operator, formatSearchQuery, parseCriteriaAsSearchRequest, parseSearchDefinition, parseSearchRequest, parseSearchUrl };
|
|
378
|
-
//# sourceMappingURL=search.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
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 (const v of value) {\n queryArray.push([key, v]);\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\n/**\n * Parses a FHIR criteria string into a SearchRequest.\n * FHIR criteria strings are found on resources such as Subscription.\n * @param criteria The FHIR criteria string.\n * @returns Parsed search definition.\n */\nexport function parseCriteriaAsSearchRequest(criteria: string): SearchRequest {\n return parseSearchUrl(new URL(criteria, 'https://api.medplum.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, 10);\n break;\n\n case '_offset':\n searchRequest.offset = parseInt(value, 10);\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 default:\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 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
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reads data from a Readable stream and returns a Promise that resolves with a Buffer containing all the data.
|
|
3
|
-
* @param stream - The Readable stream to read from.
|
|
4
|
-
* @returns A Promise that resolves with a Buffer containing all the data from the Readable stream.
|
|
5
|
-
*/
|
|
6
|
-
function streamToBuffer(stream) {
|
|
7
|
-
const chunks = [];
|
|
8
|
-
return new Promise((resolve, reject) => {
|
|
9
|
-
stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
|
|
10
|
-
stream.on('error', (err) => {
|
|
11
|
-
stream.destroy();
|
|
12
|
-
reject(err);
|
|
13
|
-
});
|
|
14
|
-
stream.on('end', () => {
|
|
15
|
-
resolve(Buffer.concat(chunks));
|
|
16
|
-
});
|
|
17
|
-
stream.on('close', () => {
|
|
18
|
-
stream.destroy();
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export { streamToBuffer };
|
|
24
|
-
//# sourceMappingURL=sftp.mjs.map
|
package/dist/esm/sftp.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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;;;;"}
|