@medplum/core 2.0.5 → 2.0.6
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 +871 -26
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.min.cjs +1 -1
- package/dist/esm/client.mjs +7 -6
- package/dist/esm/client.mjs.map +1 -1
- package/dist/esm/fhirlexer/tokenize.mjs +13 -4
- package/dist/esm/fhirlexer/tokenize.mjs.map +1 -1
- package/dist/esm/fhirmapper/parse.mjs +317 -0
- package/dist/esm/fhirmapper/parse.mjs.map +1 -0
- package/dist/esm/fhirmapper/tokenize.mjs +15 -0
- package/dist/esm/fhirmapper/tokenize.mjs.map +1 -0
- package/dist/esm/fhirpath/atoms.mjs +2 -2
- package/dist/esm/fhirpath/atoms.mjs.map +1 -1
- package/dist/esm/fhirpath/functions.mjs +2 -2
- package/dist/esm/fhirpath/functions.mjs.map +1 -1
- package/dist/esm/fhirpath/utils.mjs +4 -4
- package/dist/esm/fhirpath/utils.mjs.map +1 -1
- package/dist/esm/filter/parse.mjs +51 -0
- package/dist/esm/filter/parse.mjs.map +1 -0
- package/dist/esm/filter/tokenize.mjs +18 -0
- package/dist/esm/filter/tokenize.mjs.map +1 -0
- package/dist/esm/filter/types.mjs +34 -0
- package/dist/esm/filter/types.mjs.map +1 -0
- package/dist/esm/index.min.mjs +1 -1
- package/dist/esm/index.mjs +8 -2
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/node_modules/tslib/tslib.es6.mjs.map +1 -1
- package/dist/esm/outcomes.mjs +15 -1
- package/dist/esm/outcomes.mjs.map +1 -1
- package/dist/esm/schema.mjs +397 -0
- package/dist/esm/schema.mjs.map +1 -0
- package/dist/esm/types.mjs +34 -8
- package/dist/esm/types.mjs.map +1 -1
- package/dist/types/client.d.ts +20 -8
- package/dist/types/fhirlexer/tokenize.d.ts +5 -1
- package/dist/types/fhirmapper/index.d.ts +1 -0
- package/dist/types/filter/index.d.ts +2 -0
- package/dist/types/filter/parse.d.ts +7 -0
- package/dist/types/filter/tokenize.d.ts +2 -0
- package/dist/types/filter/types.d.ts +31 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/outcomes.d.ts +1 -0
- package/dist/types/schema.d.ts +120 -0
- package/dist/types/types.d.ts +19 -5
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -1301,6 +1301,20 @@
|
|
|
1301
1301
|
],
|
|
1302
1302
|
};
|
|
1303
1303
|
}
|
|
1304
|
+
function validationError(details) {
|
|
1305
|
+
return {
|
|
1306
|
+
resourceType: 'OperationOutcome',
|
|
1307
|
+
issue: [
|
|
1308
|
+
{
|
|
1309
|
+
severity: 'error',
|
|
1310
|
+
code: 'structure',
|
|
1311
|
+
details: {
|
|
1312
|
+
text: details,
|
|
1313
|
+
},
|
|
1314
|
+
},
|
|
1315
|
+
],
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1304
1318
|
function isOperationOutcome(value) {
|
|
1305
1319
|
return typeof value === 'object' && value !== null && value.resourceType === 'OperationOutcome';
|
|
1306
1320
|
}
|
|
@@ -6066,7 +6080,7 @@
|
|
|
6066
6080
|
// First pass, build types
|
|
6067
6081
|
elements.forEach((element) => indexType(structureDefinition, element));
|
|
6068
6082
|
// Second pass, build properties
|
|
6069
|
-
elements.forEach((element) => indexProperty(element));
|
|
6083
|
+
elements.forEach((element) => indexProperty(structureDefinition, element));
|
|
6070
6084
|
}
|
|
6071
6085
|
}
|
|
6072
6086
|
/**
|
|
@@ -6084,6 +6098,9 @@
|
|
|
6084
6098
|
return;
|
|
6085
6099
|
}
|
|
6086
6100
|
const parts = path.split('.');
|
|
6101
|
+
// Force the first part to be the type name
|
|
6102
|
+
// This is necessary for "SimpleQuantity" and "MoneyQuantity"
|
|
6103
|
+
parts[0] = structureDefinition.name;
|
|
6087
6104
|
const typeName = buildTypeName(parts);
|
|
6088
6105
|
let typeSchema = globalSchema.types[typeName];
|
|
6089
6106
|
if (!typeSchema) {
|
|
@@ -6101,12 +6118,15 @@
|
|
|
6101
6118
|
* @param element The input ElementDefinition.
|
|
6102
6119
|
* @see {@link IndexedStructureDefinition} for more details on indexed StructureDefinitions.
|
|
6103
6120
|
*/
|
|
6104
|
-
function indexProperty(element) {
|
|
6121
|
+
function indexProperty(structureDefinition, element) {
|
|
6105
6122
|
const path = element.path;
|
|
6106
6123
|
const parts = path.split('.');
|
|
6107
6124
|
if (parts.length === 1) {
|
|
6108
6125
|
return;
|
|
6109
6126
|
}
|
|
6127
|
+
// Force the first part to be the type name
|
|
6128
|
+
// This is necessary for "SimpleQuantity" and "MoneyQuantity"
|
|
6129
|
+
parts[0] = structureDefinition.name;
|
|
6110
6130
|
const typeName = buildTypeName(parts.slice(0, parts.length - 1));
|
|
6111
6131
|
const typeSchema = globalSchema.types[typeName];
|
|
6112
6132
|
if (!typeSchema) {
|
|
@@ -6210,12 +6230,16 @@
|
|
|
6210
6230
|
return components.map(capitalize).join('');
|
|
6211
6231
|
}
|
|
6212
6232
|
/**
|
|
6213
|
-
* Returns true if the type schema is a
|
|
6233
|
+
* Returns true if the type schema is a non-abstract FHIR resource.
|
|
6214
6234
|
* @param typeSchema The type schema to check.
|
|
6215
|
-
* @returns True if the type schema is a
|
|
6235
|
+
* @returns True if the type schema is a non-abstract FHIR resource.
|
|
6216
6236
|
*/
|
|
6217
|
-
function
|
|
6218
|
-
|
|
6237
|
+
function isResourceTypeSchema(typeSchema) {
|
|
6238
|
+
const structureDefinition = typeSchema.structureDefinition;
|
|
6239
|
+
return (structureDefinition &&
|
|
6240
|
+
structureDefinition.name === typeSchema.elementDefinition?.path &&
|
|
6241
|
+
structureDefinition.kind === 'resource' &&
|
|
6242
|
+
!structureDefinition.abstract);
|
|
6219
6243
|
}
|
|
6220
6244
|
/**
|
|
6221
6245
|
* Returns an array of all resource types.
|
|
@@ -6225,7 +6249,7 @@
|
|
|
6225
6249
|
function getResourceTypes() {
|
|
6226
6250
|
const result = [];
|
|
6227
6251
|
for (const [resourceType, typeSchema] of Object.entries(globalSchema.types)) {
|
|
6228
|
-
if (
|
|
6252
|
+
if (isResourceTypeSchema(typeSchema)) {
|
|
6229
6253
|
result.push(resourceType);
|
|
6230
6254
|
}
|
|
6231
6255
|
}
|
|
@@ -6304,6 +6328,22 @@
|
|
|
6304
6328
|
}
|
|
6305
6329
|
return property;
|
|
6306
6330
|
}
|
|
6331
|
+
/**
|
|
6332
|
+
* Typeguard to validate that an object is a FHIR resource
|
|
6333
|
+
* @param value The object to check
|
|
6334
|
+
* @returns True if the input is of type 'object' and contains property 'resourceType'
|
|
6335
|
+
*/
|
|
6336
|
+
function isResource(value) {
|
|
6337
|
+
return !!(value && typeof value === 'object' && 'resourceType' in value);
|
|
6338
|
+
}
|
|
6339
|
+
/**
|
|
6340
|
+
* Typeguard to validate that an object is a FHIR resource
|
|
6341
|
+
* @param value The object to check
|
|
6342
|
+
* @returns True if the input is of type 'object' and contains property 'reference'
|
|
6343
|
+
*/
|
|
6344
|
+
function isReference(value) {
|
|
6345
|
+
return !!(value && typeof value === 'object' && 'reference' in value);
|
|
6346
|
+
}
|
|
6307
6347
|
/**
|
|
6308
6348
|
* Global schema singleton.
|
|
6309
6349
|
*/
|
|
@@ -6312,7 +6352,7 @@
|
|
|
6312
6352
|
// PKCE auth based on:
|
|
6313
6353
|
// https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/
|
|
6314
6354
|
var _MedplumClient_instances, _MedplumClient_fetch, _MedplumClient_createPdf, _MedplumClient_storage, _MedplumClient_requestCache, _MedplumClient_cacheTime, _MedplumClient_baseUrl, _MedplumClient_fhirBaseUrl, _MedplumClient_authorizeUrl, _MedplumClient_tokenUrl, _MedplumClient_logoutUrl, _MedplumClient_onUnauthenticated, _MedplumClient_autoBatchTime, _MedplumClient_autoBatchQueue, _MedplumClient_clientId, _MedplumClient_clientSecret, _MedplumClient_autoBatchTimerId, _MedplumClient_accessToken, _MedplumClient_refreshToken, _MedplumClient_refreshPromise, _MedplumClient_profilePromise, _MedplumClient_profile, _MedplumClient_config, _MedplumClient_addLogin, _MedplumClient_refreshProfile, _MedplumClient_getCacheEntry, _MedplumClient_setCacheEntry, _MedplumClient_cacheResource, _MedplumClient_deleteCacheEntry, _MedplumClient_request, _MedplumClient_fetchWithRetry, _MedplumClient_executeAutoBatch, _MedplumClient_addFetchOptionsDefaults, _MedplumClient_setRequestContentType, _MedplumClient_setRequestBody, _MedplumClient_handleUnauthenticated, _MedplumClient_requestAuthorization, _MedplumClient_refresh, _MedplumClient_fetchTokens, _MedplumClient_verifyTokens, _MedplumClient_setupStorageListener;
|
|
6315
|
-
const MEDPLUM_VERSION = "2.0.
|
|
6355
|
+
const MEDPLUM_VERSION = "2.0.6-c4b403f5";
|
|
6316
6356
|
const DEFAULT_BASE_URL = 'https://api.medplum.com/';
|
|
6317
6357
|
const DEFAULT_RESOURCE_CACHE_SIZE = 1000;
|
|
6318
6358
|
const DEFAULT_CACHE_TIME = 60000; // 60 seconds
|
|
@@ -6769,13 +6809,14 @@
|
|
|
6769
6809
|
* Builds a FHIR search URL from a search query or structured query object.
|
|
6770
6810
|
* @category HTTP
|
|
6771
6811
|
* @category Search
|
|
6772
|
-
* @param
|
|
6812
|
+
* @param resourceType The FHIR resource type.
|
|
6813
|
+
* @param query The FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
6773
6814
|
* @returns The well-formed FHIR URL.
|
|
6774
6815
|
*/
|
|
6775
6816
|
fhirSearchUrl(resourceType, query) {
|
|
6776
6817
|
const url = this.fhirUrl(resourceType);
|
|
6777
6818
|
if (query) {
|
|
6778
|
-
url.search = query.toString();
|
|
6819
|
+
url.search = new URLSearchParams(query).toString();
|
|
6779
6820
|
}
|
|
6780
6821
|
return url;
|
|
6781
6822
|
}
|
|
@@ -6823,7 +6864,7 @@
|
|
|
6823
6864
|
*
|
|
6824
6865
|
* @category Search
|
|
6825
6866
|
* @param resourceType The FHIR resource type.
|
|
6826
|
-
* @param query
|
|
6867
|
+
* @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
6827
6868
|
* @param options Optional fetch options.
|
|
6828
6869
|
* @returns Promise to the search result bundle.
|
|
6829
6870
|
*/
|
|
@@ -6864,7 +6905,7 @@
|
|
|
6864
6905
|
*
|
|
6865
6906
|
* @category Search
|
|
6866
6907
|
* @param resourceType The FHIR resource type.
|
|
6867
|
-
* @param query
|
|
6908
|
+
* @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
6868
6909
|
* @param options Optional fetch options.
|
|
6869
6910
|
* @returns Promise to the search result bundle.
|
|
6870
6911
|
*/
|
|
@@ -6899,7 +6940,7 @@
|
|
|
6899
6940
|
*
|
|
6900
6941
|
* @category Search
|
|
6901
6942
|
* @param resourceType The FHIR resource type.
|
|
6902
|
-
* @param query
|
|
6943
|
+
* @param query Optional FHIR search query or structured query object. Can be any valid input to the URLSearchParams() constructor.
|
|
6903
6944
|
* @param options Optional fetch options.
|
|
6904
6945
|
* @returns Promise to the search result bundle.
|
|
6905
6946
|
*/
|
|
@@ -8177,7 +8218,7 @@
|
|
|
8177
8218
|
}
|
|
8178
8219
|
_Parser_tokens = new WeakMap(), _Parser_prefixParselets = new WeakMap(), _Parser_infixParselets = new WeakMap();
|
|
8179
8220
|
|
|
8180
|
-
var _Tokenizer_instances, _Tokenizer_str, _Tokenizer_keywords, _Tokenizer_operators, _Tokenizer_result, _Tokenizer_pos, _Tokenizer_markStack, _Tokenizer_prevToken, _Tokenizer_peekToken, _Tokenizer_consumeToken, _Tokenizer_consumeWhitespace, _Tokenizer_consumeMultiLineComment, _Tokenizer_consumeSingleLineComment, _Tokenizer_consumeString, _Tokenizer_consumeBacktickSymbol, _Tokenizer_consumeDateTime, _Tokenizer_consumeNumber, _Tokenizer_consumeSymbol, _Tokenizer_consumeOperator, _Tokenizer_consumeWhile, _Tokenizer_curr, _Tokenizer_prev, _Tokenizer_peek, _Tokenizer_mark, _Tokenizer_reset, _Tokenizer_advance, _Tokenizer_buildToken;
|
|
8221
|
+
var _Tokenizer_instances, _Tokenizer_str, _Tokenizer_keywords, _Tokenizer_operators, _Tokenizer_dateTimeLiterals, _Tokenizer_symbolRegex, _Tokenizer_result, _Tokenizer_pos, _Tokenizer_markStack, _Tokenizer_prevToken, _Tokenizer_peekToken, _Tokenizer_consumeToken, _Tokenizer_consumeWhitespace, _Tokenizer_consumeMultiLineComment, _Tokenizer_consumeSingleLineComment, _Tokenizer_consumeString, _Tokenizer_consumeBacktickSymbol, _Tokenizer_consumeDateTime, _Tokenizer_consumeNumber, _Tokenizer_consumeSymbol, _Tokenizer_consumeOperator, _Tokenizer_consumeWhile, _Tokenizer_curr, _Tokenizer_prev, _Tokenizer_peek, _Tokenizer_mark, _Tokenizer_reset, _Tokenizer_advance, _Tokenizer_buildToken;
|
|
8181
8222
|
const STANDARD_UNITS = [
|
|
8182
8223
|
'year',
|
|
8183
8224
|
'years',
|
|
@@ -8197,17 +8238,21 @@
|
|
|
8197
8238
|
'milliseconds',
|
|
8198
8239
|
];
|
|
8199
8240
|
class Tokenizer {
|
|
8200
|
-
constructor(str, keywords, operators) {
|
|
8241
|
+
constructor(str, keywords, operators, options) {
|
|
8201
8242
|
_Tokenizer_instances.add(this);
|
|
8202
8243
|
_Tokenizer_str.set(this, void 0);
|
|
8203
8244
|
_Tokenizer_keywords.set(this, void 0);
|
|
8204
8245
|
_Tokenizer_operators.set(this, void 0);
|
|
8246
|
+
_Tokenizer_dateTimeLiterals.set(this, void 0);
|
|
8247
|
+
_Tokenizer_symbolRegex.set(this, void 0);
|
|
8205
8248
|
_Tokenizer_result.set(this, []);
|
|
8206
8249
|
_Tokenizer_pos.set(this, { index: 0, line: 1, column: 0 });
|
|
8207
8250
|
_Tokenizer_markStack.set(this, []);
|
|
8208
8251
|
__classPrivateFieldSet(this, _Tokenizer_str, str, "f");
|
|
8209
8252
|
__classPrivateFieldSet(this, _Tokenizer_keywords, keywords, "f");
|
|
8210
8253
|
__classPrivateFieldSet(this, _Tokenizer_operators, operators, "f");
|
|
8254
|
+
__classPrivateFieldSet(this, _Tokenizer_dateTimeLiterals, !!options?.dateTimeLiterals, "f");
|
|
8255
|
+
__classPrivateFieldSet(this, _Tokenizer_symbolRegex, options?.symbolRegex ?? /[$\w]/, "f");
|
|
8211
8256
|
}
|
|
8212
8257
|
tokenize() {
|
|
8213
8258
|
while (__classPrivateFieldGet(this, _Tokenizer_pos, "f").index < __classPrivateFieldGet(this, _Tokenizer_str, "f").length) {
|
|
@@ -8219,7 +8264,7 @@
|
|
|
8219
8264
|
return __classPrivateFieldGet(this, _Tokenizer_result, "f");
|
|
8220
8265
|
}
|
|
8221
8266
|
}
|
|
8222
|
-
_Tokenizer_str = new WeakMap(), _Tokenizer_keywords = new WeakMap(), _Tokenizer_operators = new WeakMap(), _Tokenizer_result = new WeakMap(), _Tokenizer_pos = new WeakMap(), _Tokenizer_markStack = new WeakMap(), _Tokenizer_instances = new WeakSet(), _Tokenizer_prevToken = function _Tokenizer_prevToken() {
|
|
8267
|
+
_Tokenizer_str = new WeakMap(), _Tokenizer_keywords = new WeakMap(), _Tokenizer_operators = new WeakMap(), _Tokenizer_dateTimeLiterals = new WeakMap(), _Tokenizer_symbolRegex = new WeakMap(), _Tokenizer_result = new WeakMap(), _Tokenizer_pos = new WeakMap(), _Tokenizer_markStack = new WeakMap(), _Tokenizer_instances = new WeakSet(), _Tokenizer_prevToken = function _Tokenizer_prevToken() {
|
|
8223
8268
|
return __classPrivateFieldGet(this, _Tokenizer_result, "f").slice(-1)[0];
|
|
8224
8269
|
}, _Tokenizer_peekToken = function _Tokenizer_peekToken() {
|
|
8225
8270
|
__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_mark).call(this);
|
|
@@ -8307,6 +8352,11 @@
|
|
|
8307
8352
|
__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_advance).call(this);
|
|
8308
8353
|
__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this).match(/\d/));
|
|
8309
8354
|
}
|
|
8355
|
+
if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) === '-' && __classPrivateFieldGet(this, _Tokenizer_dateTimeLiterals, "f")) {
|
|
8356
|
+
// Rewind to one character before the start, and then treat as dateTime literal.
|
|
8357
|
+
__classPrivateFieldGet(this, _Tokenizer_pos, "f").index = start - 1;
|
|
8358
|
+
return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeDateTime).call(this);
|
|
8359
|
+
}
|
|
8310
8360
|
if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this) === ' ') {
|
|
8311
8361
|
if (isUnitToken(__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_peekToken).call(this))) {
|
|
8312
8362
|
id = 'Quantity';
|
|
@@ -8315,7 +8365,7 @@
|
|
|
8315
8365
|
}
|
|
8316
8366
|
return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, id, __classPrivateFieldGet(this, _Tokenizer_str, "f").substring(start, __classPrivateFieldGet(this, _Tokenizer_pos, "f").index));
|
|
8317
8367
|
}, _Tokenizer_consumeSymbol = function _Tokenizer_consumeSymbol() {
|
|
8318
|
-
const value = __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this).match(
|
|
8368
|
+
const value = __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_consumeWhile).call(this, () => __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_curr).call(this).match(__classPrivateFieldGet(this, _Tokenizer_symbolRegex, "f")));
|
|
8319
8369
|
if (__classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_prevToken).call(this)?.value !== '.' && __classPrivateFieldGet(this, _Tokenizer_keywords, "f").includes(value)) {
|
|
8320
8370
|
return __classPrivateFieldGet(this, _Tokenizer_instances, "m", _Tokenizer_buildToken).call(this, value, value);
|
|
8321
8371
|
}
|
|
@@ -8439,7 +8489,7 @@
|
|
|
8439
8489
|
else if (isQuantity(value)) {
|
|
8440
8490
|
return { type: exports.PropertyType.Quantity, value };
|
|
8441
8491
|
}
|
|
8442
|
-
else if (
|
|
8492
|
+
else if (isResource(value)) {
|
|
8443
8493
|
return { type: value.resourceType, value };
|
|
8444
8494
|
}
|
|
8445
8495
|
else {
|
|
@@ -8521,7 +8571,7 @@
|
|
|
8521
8571
|
}
|
|
8522
8572
|
}
|
|
8523
8573
|
function toTypedValueWithType(value, type) {
|
|
8524
|
-
if (type === 'Resource' &&
|
|
8574
|
+
if (type === 'Resource' && isResource(value)) {
|
|
8525
8575
|
type = value.resourceType;
|
|
8526
8576
|
}
|
|
8527
8577
|
return { type, value };
|
|
@@ -8548,7 +8598,7 @@
|
|
|
8548
8598
|
// Examples:
|
|
8549
8599
|
// value + valueString = ok, because "string" is valid
|
|
8550
8600
|
// value + valueDecimal = ok, because "decimal" is valid
|
|
8551
|
-
// id +
|
|
8601
|
+
// id + identifier = not ok, because "entifier" is not a valid type
|
|
8552
8602
|
// resource + resourceType = not ok, because "type" is not a valid type
|
|
8553
8603
|
for (const propertyType in exports.PropertyType) {
|
|
8554
8604
|
const propertyName = path + capitalize(propertyType);
|
|
@@ -10203,7 +10253,7 @@
|
|
|
10203
10253
|
if (typeof value === 'number') {
|
|
10204
10254
|
return { type: exports.PropertyType.BackboneElement, value: { namespace: 'System', name: 'Integer' } };
|
|
10205
10255
|
}
|
|
10206
|
-
if (value
|
|
10256
|
+
if (isResource(value)) {
|
|
10207
10257
|
return {
|
|
10208
10258
|
type: exports.PropertyType.BackboneElement,
|
|
10209
10259
|
value: { namespace: 'FHIR', name: value.resourceType },
|
|
@@ -10332,7 +10382,7 @@
|
|
|
10332
10382
|
if (!input || typeof input !== 'object') {
|
|
10333
10383
|
return undefined;
|
|
10334
10384
|
}
|
|
10335
|
-
if (
|
|
10385
|
+
if (isResource(input) && input.resourceType === this.name) {
|
|
10336
10386
|
return typedValue;
|
|
10337
10387
|
}
|
|
10338
10388
|
return getTypedPropertyValue(typedValue, this.name);
|
|
@@ -10611,7 +10661,7 @@
|
|
|
10611
10661
|
|
|
10612
10662
|
const FHIRPATH_KEYWORDS = ['true', 'false'];
|
|
10613
10663
|
const FHIRPATH_OPERATORS = ['!=', '!~', '<=', '>=', '{}', '->'];
|
|
10614
|
-
function tokenize(str) {
|
|
10664
|
+
function tokenize$2(str) {
|
|
10615
10665
|
return new Tokenizer(str, FHIRPATH_KEYWORDS, FHIRPATH_OPERATORS).tokenize();
|
|
10616
10666
|
}
|
|
10617
10667
|
|
|
@@ -10708,7 +10758,7 @@
|
|
|
10708
10758
|
.infixLeft('or', 6 /* OperatorPrecedence.Is */, (left, _, right) => new OrAtom(left, right))
|
|
10709
10759
|
.infixLeft('xor', 6 /* OperatorPrecedence.Is */, (left, _, right) => new XorAtom(left, right));
|
|
10710
10760
|
}
|
|
10711
|
-
const fhirPathParserBuilder = initFhirPathParserBuilder();
|
|
10761
|
+
const fhirPathParserBuilder$2 = initFhirPathParserBuilder();
|
|
10712
10762
|
/**
|
|
10713
10763
|
* Parses a FHIRPath expression into an AST.
|
|
10714
10764
|
* The result can be used to evaluate the expression against a resource or other object.
|
|
@@ -10718,7 +10768,7 @@
|
|
|
10718
10768
|
* @returns The AST representing the expression.
|
|
10719
10769
|
*/
|
|
10720
10770
|
function parseFhirPath(input) {
|
|
10721
|
-
return new FhirPathAtom(input, fhirPathParserBuilder.construct(tokenize(input)).consumeAndParse());
|
|
10771
|
+
return new FhirPathAtom(input, fhirPathParserBuilder$2.construct(tokenize$2(input)).consumeAndParse());
|
|
10722
10772
|
}
|
|
10723
10773
|
/**
|
|
10724
10774
|
* Evaluates a FHIRPath expression against a resource or other object.
|
|
@@ -10748,6 +10798,397 @@
|
|
|
10748
10798
|
return parseFhirPath(expression).eval(input);
|
|
10749
10799
|
}
|
|
10750
10800
|
|
|
10801
|
+
const MAPPING_LANGUAGE_OPERATORS$1 = [...FHIRPATH_OPERATORS, '->', '<<', '>>'];
|
|
10802
|
+
function tokenize$1(str) {
|
|
10803
|
+
return new Tokenizer(str, FHIRPATH_KEYWORDS, MAPPING_LANGUAGE_OPERATORS$1).tokenize();
|
|
10804
|
+
}
|
|
10805
|
+
|
|
10806
|
+
var _StructureMapParser_instances, _StructureMapParser_parseUses, _StructureMapParser_parseImport, _StructureMapParser_parseGroup, _StructureMapParser_parseParameters, _StructureMapParser_parseParameter, _StructureMapParser_parseRules, _StructureMapParser_parseRule, _StructureMapParser_parseRuleSources, _StructureMapParser_parseRuleSource, _StructureMapParser_parseRuleTargets, _StructureMapParser_parseRuleTarget, _StructureMapParser_parseRuleTargetTransform, _StructureMapParser_parseRuleTargetSymbol, _StructureMapParser_parseRuleTargetFunction, _StructureMapParser_parseRuleTargetLiteral, _StructureMapParser_parseRuleContext, _StructureMapParser_parseRuleDependents, _StructureMapParser_parseConceptMap;
|
|
10807
|
+
class StructureMapParser {
|
|
10808
|
+
constructor(parser) {
|
|
10809
|
+
this.parser = parser;
|
|
10810
|
+
_StructureMapParser_instances.add(this);
|
|
10811
|
+
this.structureMap = { resourceType: 'StructureMap' };
|
|
10812
|
+
}
|
|
10813
|
+
parse() {
|
|
10814
|
+
// 'map' url '=' identifier
|
|
10815
|
+
// map "http://hl7.org/fhir/StructureMap/tutorial" = tutorial
|
|
10816
|
+
this.parser.consume('Symbol', 'map');
|
|
10817
|
+
this.structureMap.url = this.parser.consume('String').value;
|
|
10818
|
+
this.parser.consume('=');
|
|
10819
|
+
this.structureMap.name = this.parser.consume().value;
|
|
10820
|
+
while (this.parser.hasMore()) {
|
|
10821
|
+
const next = this.parser.peek()?.value;
|
|
10822
|
+
switch (next) {
|
|
10823
|
+
case 'uses':
|
|
10824
|
+
__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseUses).call(this);
|
|
10825
|
+
break;
|
|
10826
|
+
case 'imports':
|
|
10827
|
+
__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseImport).call(this);
|
|
10828
|
+
break;
|
|
10829
|
+
case 'group':
|
|
10830
|
+
__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseGroup).call(this);
|
|
10831
|
+
break;
|
|
10832
|
+
case 'conceptmap':
|
|
10833
|
+
__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseConceptMap).call(this);
|
|
10834
|
+
break;
|
|
10835
|
+
default:
|
|
10836
|
+
throw new Error(`Unexpected token: ${next}`);
|
|
10837
|
+
}
|
|
10838
|
+
}
|
|
10839
|
+
return this.structureMap;
|
|
10840
|
+
}
|
|
10841
|
+
}
|
|
10842
|
+
_StructureMapParser_instances = new WeakSet(), _StructureMapParser_parseUses = function _StructureMapParser_parseUses() {
|
|
10843
|
+
// 'uses' url structureAlias? 'as' modelMode
|
|
10844
|
+
// uses "http://hl7.org/fhir/StructureDefinition/tutorial-left" as source
|
|
10845
|
+
this.parser.consume('Symbol', 'uses');
|
|
10846
|
+
const result = {};
|
|
10847
|
+
result.url = this.parser.consume('String').value;
|
|
10848
|
+
if (this.parser.peek()?.value === 'alias') {
|
|
10849
|
+
this.parser.consume('Symbol', 'alias');
|
|
10850
|
+
result.alias = this.parser.consume('Symbol').value;
|
|
10851
|
+
}
|
|
10852
|
+
this.parser.consume('Symbol', 'as');
|
|
10853
|
+
result.mode = this.parser.consume().value;
|
|
10854
|
+
if (!this.structureMap.structure) {
|
|
10855
|
+
this.structureMap.structure = [];
|
|
10856
|
+
}
|
|
10857
|
+
this.structureMap.structure.push(result);
|
|
10858
|
+
}, _StructureMapParser_parseImport = function _StructureMapParser_parseImport() {
|
|
10859
|
+
this.parser.consume('Symbol', 'imports');
|
|
10860
|
+
if (!this.structureMap.import) {
|
|
10861
|
+
this.structureMap.import = [];
|
|
10862
|
+
}
|
|
10863
|
+
this.structureMap.import.push(this.parser.consume('String').value);
|
|
10864
|
+
}, _StructureMapParser_parseGroup = function _StructureMapParser_parseGroup() {
|
|
10865
|
+
// 'group' identifier parameters extends? typeMode? rules
|
|
10866
|
+
// group tutorial(source src : TLeft, target tgt : TRight) {
|
|
10867
|
+
const result = {};
|
|
10868
|
+
this.parser.consume('Symbol', 'group');
|
|
10869
|
+
result.name = this.parser.consume('Symbol').value;
|
|
10870
|
+
result.input = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseParameters).call(this);
|
|
10871
|
+
if (this.parser.peek()?.value === 'extends') {
|
|
10872
|
+
this.parser.consume('Symbol', 'extends');
|
|
10873
|
+
result.extends = this.parser.consume('Symbol').value;
|
|
10874
|
+
}
|
|
10875
|
+
if (this.parser.peek()?.value === '<<') {
|
|
10876
|
+
this.parser.consume('<<');
|
|
10877
|
+
result.typeMode = this.parser.consume().value;
|
|
10878
|
+
if (this.parser.peek()?.value === '+') {
|
|
10879
|
+
this.parser.consume('+');
|
|
10880
|
+
result.typeMode = 'type-and-types';
|
|
10881
|
+
}
|
|
10882
|
+
this.parser.consume('>>');
|
|
10883
|
+
}
|
|
10884
|
+
else {
|
|
10885
|
+
result.typeMode = 'none';
|
|
10886
|
+
}
|
|
10887
|
+
result.rule = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRules).call(this);
|
|
10888
|
+
if (!this.structureMap.group) {
|
|
10889
|
+
this.structureMap.group = [];
|
|
10890
|
+
}
|
|
10891
|
+
this.structureMap.group.push(result);
|
|
10892
|
+
}, _StructureMapParser_parseParameters = function _StructureMapParser_parseParameters() {
|
|
10893
|
+
const parameters = [];
|
|
10894
|
+
this.parser.consume('(');
|
|
10895
|
+
while (this.parser.hasMore() && this.parser.peek()?.value !== ')') {
|
|
10896
|
+
parameters.push(__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseParameter).call(this));
|
|
10897
|
+
if (this.parser.peek()?.value === ',') {
|
|
10898
|
+
this.parser.consume(',');
|
|
10899
|
+
}
|
|
10900
|
+
}
|
|
10901
|
+
this.parser.consume(')');
|
|
10902
|
+
return parameters;
|
|
10903
|
+
}, _StructureMapParser_parseParameter = function _StructureMapParser_parseParameter() {
|
|
10904
|
+
// inputMode identifier type?
|
|
10905
|
+
// ':' identifier
|
|
10906
|
+
// source src : TLeft
|
|
10907
|
+
const result = {};
|
|
10908
|
+
result.mode = this.parser.consume().value;
|
|
10909
|
+
result.name = this.parser.consume('Symbol').value;
|
|
10910
|
+
if (this.parser.peek()?.value === ':') {
|
|
10911
|
+
this.parser.consume(':');
|
|
10912
|
+
result.type = this.parser.consume('Symbol').value;
|
|
10913
|
+
}
|
|
10914
|
+
return result;
|
|
10915
|
+
}, _StructureMapParser_parseRules = function _StructureMapParser_parseRules() {
|
|
10916
|
+
const rules = [];
|
|
10917
|
+
this.parser.consume('{');
|
|
10918
|
+
while (this.parser.hasMore() && this.parser.peek()?.value !== '}') {
|
|
10919
|
+
rules.push(__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRule).call(this));
|
|
10920
|
+
}
|
|
10921
|
+
this.parser.consume('}');
|
|
10922
|
+
return rules;
|
|
10923
|
+
}, _StructureMapParser_parseRule = function _StructureMapParser_parseRule() {
|
|
10924
|
+
const result = {
|
|
10925
|
+
source: __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleSources).call(this),
|
|
10926
|
+
};
|
|
10927
|
+
if (this.parser.peek()?.value === '->') {
|
|
10928
|
+
this.parser.consume('->');
|
|
10929
|
+
result.target = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTargets).call(this);
|
|
10930
|
+
}
|
|
10931
|
+
if (this.parser.peek()?.value === 'then') {
|
|
10932
|
+
this.parser.consume('Symbol', 'then');
|
|
10933
|
+
if (this.parser.peek()?.id === '{') {
|
|
10934
|
+
result.rule = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRules).call(this);
|
|
10935
|
+
}
|
|
10936
|
+
else {
|
|
10937
|
+
result.dependent = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleDependents).call(this);
|
|
10938
|
+
}
|
|
10939
|
+
}
|
|
10940
|
+
if (this.parser.peek()?.id === 'String') {
|
|
10941
|
+
result.name = this.parser.consume().value;
|
|
10942
|
+
}
|
|
10943
|
+
else {
|
|
10944
|
+
result.name = result.source?.[0]?.element;
|
|
10945
|
+
}
|
|
10946
|
+
this.parser.consume(';');
|
|
10947
|
+
return result;
|
|
10948
|
+
}, _StructureMapParser_parseRuleSources = function _StructureMapParser_parseRuleSources() {
|
|
10949
|
+
const sources = [__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleSource).call(this)];
|
|
10950
|
+
while (this.parser.hasMore() && this.parser.peek()?.value === ',') {
|
|
10951
|
+
this.parser.consume(',');
|
|
10952
|
+
sources.push(__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleSource).call(this));
|
|
10953
|
+
}
|
|
10954
|
+
return sources;
|
|
10955
|
+
}, _StructureMapParser_parseRuleSource = function _StructureMapParser_parseRuleSource() {
|
|
10956
|
+
const result = {};
|
|
10957
|
+
const context = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleContext).call(this);
|
|
10958
|
+
if (context.includes('.')) {
|
|
10959
|
+
const parts = context.split('.');
|
|
10960
|
+
result.context = parts[0];
|
|
10961
|
+
result.element = parts[1];
|
|
10962
|
+
}
|
|
10963
|
+
else {
|
|
10964
|
+
result.context = context;
|
|
10965
|
+
}
|
|
10966
|
+
if (this.parser.hasMore() && this.parser.peek()?.value === ':') {
|
|
10967
|
+
this.parser.consume(':');
|
|
10968
|
+
result.type = this.parser.consume().value;
|
|
10969
|
+
}
|
|
10970
|
+
if (this.parser.hasMore() && this.parser.peek()?.value === 'default') {
|
|
10971
|
+
this.parser.consume('default');
|
|
10972
|
+
this.parser.consumeAndParse();
|
|
10973
|
+
}
|
|
10974
|
+
if (this.parser.peek()?.value === 'first' ||
|
|
10975
|
+
this.parser.peek()?.value === 'not_first' ||
|
|
10976
|
+
this.parser.peek()?.value === 'last' ||
|
|
10977
|
+
this.parser.peek()?.value === 'not_last' ||
|
|
10978
|
+
this.parser.peek()?.value === 'only_one') {
|
|
10979
|
+
result.listMode = this.parser.consume().value;
|
|
10980
|
+
}
|
|
10981
|
+
if (this.parser.peek()?.value === 'as') {
|
|
10982
|
+
this.parser.consume('Symbol', 'as');
|
|
10983
|
+
result.variable = this.parser.consume().value;
|
|
10984
|
+
}
|
|
10985
|
+
if (this.parser.peek()?.value === 'where') {
|
|
10986
|
+
this.parser.consume('Symbol', 'where');
|
|
10987
|
+
const whereFhirPath = this.parser.consumeAndParse(100 /* OperatorPrecedence.Arrow */);
|
|
10988
|
+
result.condition = whereFhirPath.toString();
|
|
10989
|
+
}
|
|
10990
|
+
if (this.parser.peek()?.value === 'check') {
|
|
10991
|
+
this.parser.consume('Symbol', 'check');
|
|
10992
|
+
const checkFhirPath = this.parser.consumeAndParse(100 /* OperatorPrecedence.Arrow */);
|
|
10993
|
+
result.check = checkFhirPath.toString();
|
|
10994
|
+
}
|
|
10995
|
+
return result;
|
|
10996
|
+
}, _StructureMapParser_parseRuleTargets = function _StructureMapParser_parseRuleTargets() {
|
|
10997
|
+
const targets = [__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTarget).call(this)];
|
|
10998
|
+
while (this.parser.hasMore() && this.parser.peek()?.value === ',') {
|
|
10999
|
+
this.parser.consume(',');
|
|
11000
|
+
targets.push(__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTarget).call(this));
|
|
11001
|
+
}
|
|
11002
|
+
return targets;
|
|
11003
|
+
}, _StructureMapParser_parseRuleTarget = function _StructureMapParser_parseRuleTarget() {
|
|
11004
|
+
const result = {};
|
|
11005
|
+
const context = __classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleContext).call(this);
|
|
11006
|
+
if (context.includes('.')) {
|
|
11007
|
+
const parts = context.split('.');
|
|
11008
|
+
result.contextType = 'variable';
|
|
11009
|
+
result.context = parts[0];
|
|
11010
|
+
result.element = parts[1];
|
|
11011
|
+
}
|
|
11012
|
+
else {
|
|
11013
|
+
result.context = context;
|
|
11014
|
+
}
|
|
11015
|
+
if (this.parser.peek()?.value === '=') {
|
|
11016
|
+
this.parser.consume('=');
|
|
11017
|
+
__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTargetTransform).call(this, result);
|
|
11018
|
+
}
|
|
11019
|
+
if (this.parser.peek()?.value === 'as') {
|
|
11020
|
+
this.parser.consume('Symbol', 'as');
|
|
11021
|
+
result.variable = this.parser.consume().value;
|
|
11022
|
+
}
|
|
11023
|
+
if (this.parser.peek()?.value === 'first' ||
|
|
11024
|
+
this.parser.peek()?.value === 'share' ||
|
|
11025
|
+
this.parser.peek()?.value === 'last' ||
|
|
11026
|
+
this.parser.peek()?.value === 'collate') {
|
|
11027
|
+
result.listMode = [this.parser.consume().value];
|
|
11028
|
+
}
|
|
11029
|
+
return result;
|
|
11030
|
+
}, _StructureMapParser_parseRuleTargetTransform = function _StructureMapParser_parseRuleTargetTransform(result) {
|
|
11031
|
+
result.transform = 'copy';
|
|
11032
|
+
const transformFhirPath = this.parser.consumeAndParse(6 /* OperatorPrecedence.As */);
|
|
11033
|
+
if (transformFhirPath instanceof SymbolAtom) {
|
|
11034
|
+
__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTargetSymbol).call(this, result, transformFhirPath);
|
|
11035
|
+
}
|
|
11036
|
+
else if (transformFhirPath instanceof FunctionAtom) {
|
|
11037
|
+
__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTargetFunction).call(this, result, transformFhirPath);
|
|
11038
|
+
}
|
|
11039
|
+
else if (transformFhirPath instanceof LiteralAtom) {
|
|
11040
|
+
__classPrivateFieldGet(this, _StructureMapParser_instances, "m", _StructureMapParser_parseRuleTargetLiteral).call(this, result, transformFhirPath);
|
|
11041
|
+
}
|
|
11042
|
+
else {
|
|
11043
|
+
throw new Error(`Unexpected FHIRPath: ${transformFhirPath}`);
|
|
11044
|
+
}
|
|
11045
|
+
}, _StructureMapParser_parseRuleTargetSymbol = function _StructureMapParser_parseRuleTargetSymbol(result, literalAtom) {
|
|
11046
|
+
result.parameter = [{ valueId: literalAtom.name }];
|
|
11047
|
+
}, _StructureMapParser_parseRuleTargetFunction = function _StructureMapParser_parseRuleTargetFunction(result, functionAtom) {
|
|
11048
|
+
const functionName = functionAtom.name;
|
|
11049
|
+
switch (functionName) {
|
|
11050
|
+
case 'create':
|
|
11051
|
+
result.parameter = [
|
|
11052
|
+
{
|
|
11053
|
+
valueString: (functionAtom.args?.[0]).value.value,
|
|
11054
|
+
},
|
|
11055
|
+
];
|
|
11056
|
+
break;
|
|
11057
|
+
case 'translate':
|
|
11058
|
+
result.parameter = [{}];
|
|
11059
|
+
break;
|
|
11060
|
+
default:
|
|
11061
|
+
throw new Error('Unknown target function: ' + functionName);
|
|
11062
|
+
}
|
|
11063
|
+
}, _StructureMapParser_parseRuleTargetLiteral = function _StructureMapParser_parseRuleTargetLiteral(result, literalAtom) {
|
|
11064
|
+
switch (literalAtom.value.type) {
|
|
11065
|
+
case 'boolean':
|
|
11066
|
+
result.parameter = [{ valueBoolean: literalAtom.value.value }];
|
|
11067
|
+
break;
|
|
11068
|
+
case 'decimal':
|
|
11069
|
+
result.parameter = [{ valueDecimal: literalAtom.value.value }];
|
|
11070
|
+
break;
|
|
11071
|
+
case 'string':
|
|
11072
|
+
result.parameter = [{ valueString: literalAtom.value.value }];
|
|
11073
|
+
break;
|
|
11074
|
+
default:
|
|
11075
|
+
throw new Error('Unknown target literal type: ' + literalAtom.value.type);
|
|
11076
|
+
}
|
|
11077
|
+
}, _StructureMapParser_parseRuleContext = function _StructureMapParser_parseRuleContext() {
|
|
11078
|
+
let identifier = this.parser.consume().value;
|
|
11079
|
+
while (this.parser.peek()?.value === '.') {
|
|
11080
|
+
this.parser.consume('.');
|
|
11081
|
+
identifier += '.' + this.parser.consume().value;
|
|
11082
|
+
}
|
|
11083
|
+
return identifier;
|
|
11084
|
+
}, _StructureMapParser_parseRuleDependents = function _StructureMapParser_parseRuleDependents() {
|
|
11085
|
+
const atom = this.parser.consumeAndParse(100 /* OperatorPrecedence.Arrow */);
|
|
11086
|
+
return [
|
|
11087
|
+
{
|
|
11088
|
+
name: atom.name,
|
|
11089
|
+
variable: atom.args.map((arg) => arg.name),
|
|
11090
|
+
},
|
|
11091
|
+
];
|
|
11092
|
+
}, _StructureMapParser_parseConceptMap = function _StructureMapParser_parseConceptMap() {
|
|
11093
|
+
while (this.parser.peek()?.value !== '}') {
|
|
11094
|
+
this.parser.consume();
|
|
11095
|
+
}
|
|
11096
|
+
this.parser.consume('}');
|
|
11097
|
+
};
|
|
11098
|
+
const fhirPathParserBuilder$1 = initFhirPathParserBuilder()
|
|
11099
|
+
.registerInfix('->', { precedence: 100 /* OperatorPrecedence.Arrow */ })
|
|
11100
|
+
.registerInfix(';', { precedence: 200 /* OperatorPrecedence.Semicolon */ });
|
|
11101
|
+
/**
|
|
11102
|
+
* Parses a FHIR Mapping Language document into an AST.
|
|
11103
|
+
* @param input The FHIR Mapping Language document to parse.
|
|
11104
|
+
* @returns The AST representing the document.
|
|
11105
|
+
*/
|
|
11106
|
+
function parseMappingLanguage(input) {
|
|
11107
|
+
const parser = fhirPathParserBuilder$1.construct(tokenize$1(input));
|
|
11108
|
+
parser.removeComments();
|
|
11109
|
+
return new StructureMapParser(parser).parse();
|
|
11110
|
+
}
|
|
11111
|
+
|
|
11112
|
+
const MAPPING_LANGUAGE_OPERATORS = [...FHIRPATH_OPERATORS, 'eq', 'ne', 'co'];
|
|
11113
|
+
function tokenize(str) {
|
|
11114
|
+
return new Tokenizer(str, FHIRPATH_KEYWORDS, MAPPING_LANGUAGE_OPERATORS, {
|
|
11115
|
+
dateTimeLiterals: true,
|
|
11116
|
+
symbolRegex: /[^\s\])]/,
|
|
11117
|
+
}).tokenize();
|
|
11118
|
+
}
|
|
11119
|
+
|
|
11120
|
+
// See: https://hl7.org/fhir/search_filter.html
|
|
11121
|
+
/**
|
|
11122
|
+
* The FhirFilterComparison class represents a comparison expression.
|
|
11123
|
+
*/
|
|
11124
|
+
class FhirFilterComparison {
|
|
11125
|
+
constructor(path, operator, value) {
|
|
11126
|
+
this.path = path;
|
|
11127
|
+
this.operator = operator;
|
|
11128
|
+
this.value = value;
|
|
11129
|
+
}
|
|
11130
|
+
}
|
|
11131
|
+
/**
|
|
11132
|
+
* The FhirFilterNegation class represents a negation expression.
|
|
11133
|
+
* It contains a single child expression.
|
|
11134
|
+
*/
|
|
11135
|
+
class FhirFilterNegation {
|
|
11136
|
+
constructor(child) {
|
|
11137
|
+
this.child = child;
|
|
11138
|
+
}
|
|
11139
|
+
}
|
|
11140
|
+
/**
|
|
11141
|
+
* The FhirFilterConnective class represents a connective expression.
|
|
11142
|
+
* It contains a list of child expressions.
|
|
11143
|
+
*/
|
|
11144
|
+
class FhirFilterConnective {
|
|
11145
|
+
constructor(keyword, left, right) {
|
|
11146
|
+
this.keyword = keyword;
|
|
11147
|
+
this.left = left;
|
|
11148
|
+
this.right = right;
|
|
11149
|
+
}
|
|
11150
|
+
}
|
|
11151
|
+
|
|
11152
|
+
class FilterParameterParser {
|
|
11153
|
+
constructor(parser) {
|
|
11154
|
+
this.parser = parser;
|
|
11155
|
+
}
|
|
11156
|
+
parse() {
|
|
11157
|
+
let result;
|
|
11158
|
+
if (this.parser.peek()?.value === '(') {
|
|
11159
|
+
this.parser.consume('(');
|
|
11160
|
+
result = this.parse();
|
|
11161
|
+
this.parser.consume(')');
|
|
11162
|
+
}
|
|
11163
|
+
else if (this.parser.peek()?.value === 'not') {
|
|
11164
|
+
this.parser.consume('Symbol', 'not');
|
|
11165
|
+
this.parser.consume('(');
|
|
11166
|
+
result = new FhirFilterNegation(this.parse());
|
|
11167
|
+
this.parser.consume(')');
|
|
11168
|
+
}
|
|
11169
|
+
else {
|
|
11170
|
+
result = new FhirFilterComparison(this.parser.consume('Symbol').value, this.parser.consume('Symbol').value, this.parser.consume().value);
|
|
11171
|
+
}
|
|
11172
|
+
const next = this.parser.peek()?.value;
|
|
11173
|
+
if (next === 'and' || next === 'or') {
|
|
11174
|
+
this.parser.consume('Symbol', next);
|
|
11175
|
+
return new FhirFilterConnective(next, result, this.parse());
|
|
11176
|
+
}
|
|
11177
|
+
return result;
|
|
11178
|
+
}
|
|
11179
|
+
}
|
|
11180
|
+
const fhirPathParserBuilder = initFhirPathParserBuilder();
|
|
11181
|
+
/**
|
|
11182
|
+
* Parses a FHIR _filter parameter expression into an AST.
|
|
11183
|
+
* @param input The FHIR _filter parameter expression.
|
|
11184
|
+
* @returns The AST representing the filters.
|
|
11185
|
+
*/
|
|
11186
|
+
function parseFilterParameter(input) {
|
|
11187
|
+
const parser = fhirPathParserBuilder.construct(tokenize(input));
|
|
11188
|
+
parser.removeComments();
|
|
11189
|
+
return new FilterParameterParser(parser).parse();
|
|
11190
|
+
}
|
|
11191
|
+
|
|
10751
11192
|
/**
|
|
10752
11193
|
* The Hl7Context class represents the parsing context for an HL7 message.
|
|
10753
11194
|
*
|
|
@@ -10964,6 +11405,391 @@
|
|
|
10964
11405
|
}
|
|
10965
11406
|
}
|
|
10966
11407
|
|
|
11408
|
+
var _FhirSchemaValidator_instances, _FhirSchemaValidator_issues, _FhirSchemaValidator_root, _FhirSchemaValidator_validateObject, _FhirSchemaValidator_checkProperties, _FhirSchemaValidator_checkProperty, _FhirSchemaValidator_checkPropertyValue, _FhirSchemaValidator_validatePrimitiveType, _FhirSchemaValidator_validateString, _FhirSchemaValidator_validateNumber, _FhirSchemaValidator_checkAdditionalProperties, _FhirSchemaValidator_checkAdditionalProperty, _FhirSchemaValidator_checkPrimitiveElement, _FhirSchemaValidator_createIssue;
|
|
11409
|
+
/*
|
|
11410
|
+
* This file provides schema validation utilities for FHIR JSON objects.
|
|
11411
|
+
*
|
|
11412
|
+
* See: [JSON Representation of Resources](https://hl7.org/fhir/json.html)
|
|
11413
|
+
* See: [FHIR Data Types](https://www.hl7.org/fhir/datatypes.html)
|
|
11414
|
+
*/
|
|
11415
|
+
const fhirTypeToJsType = {
|
|
11416
|
+
base64Binary: 'string',
|
|
11417
|
+
boolean: 'boolean',
|
|
11418
|
+
canonical: 'string',
|
|
11419
|
+
code: 'string',
|
|
11420
|
+
date: 'string',
|
|
11421
|
+
dateTime: 'string',
|
|
11422
|
+
decimal: 'number',
|
|
11423
|
+
id: 'string',
|
|
11424
|
+
instant: 'string',
|
|
11425
|
+
integer: 'number',
|
|
11426
|
+
markdown: 'string',
|
|
11427
|
+
oid: 'string',
|
|
11428
|
+
positiveInt: 'number',
|
|
11429
|
+
string: 'string',
|
|
11430
|
+
time: 'string',
|
|
11431
|
+
unsignedInt: 'number',
|
|
11432
|
+
uri: 'string',
|
|
11433
|
+
url: 'string',
|
|
11434
|
+
uuid: 'string',
|
|
11435
|
+
xhtml: 'string',
|
|
11436
|
+
'http://hl7.org/fhirpath/System.String': 'string',
|
|
11437
|
+
};
|
|
11438
|
+
const baseResourceProperties = new Set([
|
|
11439
|
+
// Resource
|
|
11440
|
+
'resourceType',
|
|
11441
|
+
'id',
|
|
11442
|
+
'meta',
|
|
11443
|
+
'implicitRules',
|
|
11444
|
+
'language',
|
|
11445
|
+
// DomainResource
|
|
11446
|
+
'text',
|
|
11447
|
+
'contained',
|
|
11448
|
+
'extension',
|
|
11449
|
+
'modifierExtension',
|
|
11450
|
+
]);
|
|
11451
|
+
/**
|
|
11452
|
+
* Returns true if the given string is a valid FHIR resource type.
|
|
11453
|
+
*
|
|
11454
|
+
* ```ts
|
|
11455
|
+
* isResourceType('Patient'); // true
|
|
11456
|
+
* isResourceType('XYZ'); // false
|
|
11457
|
+
* ```
|
|
11458
|
+
*
|
|
11459
|
+
* Note that this depends on globalSchema, which is populated by the StructureDefinition loader.
|
|
11460
|
+
*
|
|
11461
|
+
* In a server context, you can load all schema definitions:
|
|
11462
|
+
*
|
|
11463
|
+
* ```ts
|
|
11464
|
+
* import { indexStructureDefinitionBundle } from '@medplum/core';
|
|
11465
|
+
* import { readJson } from '@medplum/definitions';
|
|
11466
|
+
* import { Bundle } from '@medplum/fhirtypes';
|
|
11467
|
+
*
|
|
11468
|
+
* indexStructureDefinitionBundle(readJson('fhir/r4/profiles-resources.json') as Bundle);
|
|
11469
|
+
* ```
|
|
11470
|
+
*
|
|
11471
|
+
* In a client context, you can load the schema definitions using MedplumClient:
|
|
11472
|
+
*
|
|
11473
|
+
* ```ts
|
|
11474
|
+
* import { MedplumClient } from '@medplum/core';
|
|
11475
|
+
*
|
|
11476
|
+
* const medplum = new MedplumClient();
|
|
11477
|
+
* await medplum.requestSchema('Patient');
|
|
11478
|
+
* ```
|
|
11479
|
+
*
|
|
11480
|
+
* @param resourceType The candidate resource type string.
|
|
11481
|
+
* @returns True if the resource type is a valid FHIR resource type.
|
|
11482
|
+
*/
|
|
11483
|
+
function isResourceType(resourceType) {
|
|
11484
|
+
const typeSchema = globalSchema.types[resourceType];
|
|
11485
|
+
return (typeSchema &&
|
|
11486
|
+
typeSchema.structureDefinition.id === resourceType &&
|
|
11487
|
+
typeSchema.structureDefinition.kind === 'resource');
|
|
11488
|
+
}
|
|
11489
|
+
/**
|
|
11490
|
+
* Validates that the given string is a valid FHIR resource type.
|
|
11491
|
+
* On success, silently returns void.
|
|
11492
|
+
* On failure, throws an OperationOutcomeError.
|
|
11493
|
+
*
|
|
11494
|
+
* ```ts
|
|
11495
|
+
* validateResourceType('Patient'); // nothing
|
|
11496
|
+
* validateResourceType('XYZ'); // throws OperationOutcomeError
|
|
11497
|
+
* ```
|
|
11498
|
+
*
|
|
11499
|
+
* Note that this depends on globalSchema, which is populated by the StructureDefinition loader.
|
|
11500
|
+
*
|
|
11501
|
+
* In a server context, you can load all schema definitions:
|
|
11502
|
+
*
|
|
11503
|
+
* ```ts
|
|
11504
|
+
* import { indexStructureDefinitionBundle } from '@medplum/core';
|
|
11505
|
+
* import { readJson } from '@medplum/definitions';
|
|
11506
|
+
* import { Bundle } from '@medplum/fhirtypes';
|
|
11507
|
+
*
|
|
11508
|
+
* indexStructureDefinitionBundle(readJson('fhir/r4/profiles-resources.json') as Bundle);
|
|
11509
|
+
* ```
|
|
11510
|
+
*
|
|
11511
|
+
* In a client context, you can load the schema definitions using MedplumClient:
|
|
11512
|
+
*
|
|
11513
|
+
* ```ts
|
|
11514
|
+
* import { MedplumClient } from '@medplum/core';
|
|
11515
|
+
*
|
|
11516
|
+
* const medplum = new MedplumClient();
|
|
11517
|
+
* await medplum.requestSchema('Patient');
|
|
11518
|
+
* ```
|
|
11519
|
+
*
|
|
11520
|
+
* @param resourceType The candidate resource type string.
|
|
11521
|
+
* @returns True if the resource type is a valid FHIR resource type.
|
|
11522
|
+
*/
|
|
11523
|
+
function validateResourceType(resourceType) {
|
|
11524
|
+
if (!resourceType) {
|
|
11525
|
+
throw new OperationOutcomeError(validationError('Resource type is null'));
|
|
11526
|
+
}
|
|
11527
|
+
if (!isResourceType(resourceType)) {
|
|
11528
|
+
throw new OperationOutcomeError(validationError('Unknown resource type'));
|
|
11529
|
+
}
|
|
11530
|
+
}
|
|
11531
|
+
/**
|
|
11532
|
+
* Validates a candidate FHIR resource object.
|
|
11533
|
+
* On success, silently returns void.
|
|
11534
|
+
* On failure, throws an OperationOutcomeError with issues for each violation.
|
|
11535
|
+
*
|
|
11536
|
+
* ```ts
|
|
11537
|
+
* validateResource({ resourceType: 'Patient' }); // nothing
|
|
11538
|
+
* validateResource({ resourceType: 'XYZ' }); // throws OperationOutcomeError
|
|
11539
|
+
* ```
|
|
11540
|
+
*
|
|
11541
|
+
* Note that this depends on globalSchema, which is populated by the StructureDefinition loader.
|
|
11542
|
+
*
|
|
11543
|
+
* In a server context, you can load all schema definitions:
|
|
11544
|
+
*
|
|
11545
|
+
* ```ts
|
|
11546
|
+
* import { indexStructureDefinitionBundle } from '@medplum/core';
|
|
11547
|
+
* import { readJson } from '@medplum/definitions';
|
|
11548
|
+
* import { Bundle } from '@medplum/fhirtypes';
|
|
11549
|
+
*
|
|
11550
|
+
* indexStructureDefinitionBundle(readJson('fhir/r4/profiles-resources.json') as Bundle);
|
|
11551
|
+
* ```
|
|
11552
|
+
*
|
|
11553
|
+
* In a client context, you can load the schema definitions using MedplumClient:
|
|
11554
|
+
*
|
|
11555
|
+
* ```ts
|
|
11556
|
+
* import { MedplumClient } from '@medplum/core';
|
|
11557
|
+
*
|
|
11558
|
+
* const medplum = new MedplumClient();
|
|
11559
|
+
* await medplum.requestSchema('Patient');
|
|
11560
|
+
* ```
|
|
11561
|
+
*
|
|
11562
|
+
* @param resourceType The candidate resource type string.
|
|
11563
|
+
* @returns True if the resource type is a valid FHIR resource type.
|
|
11564
|
+
*/
|
|
11565
|
+
function validateResource(resource) {
|
|
11566
|
+
new FhirSchemaValidator(resource).validate();
|
|
11567
|
+
}
|
|
11568
|
+
class FhirSchemaValidator {
|
|
11569
|
+
constructor(root) {
|
|
11570
|
+
_FhirSchemaValidator_instances.add(this);
|
|
11571
|
+
_FhirSchemaValidator_issues.set(this, void 0);
|
|
11572
|
+
_FhirSchemaValidator_root.set(this, void 0);
|
|
11573
|
+
__classPrivateFieldSet(this, _FhirSchemaValidator_issues, [], "f");
|
|
11574
|
+
__classPrivateFieldSet(this, _FhirSchemaValidator_root, root, "f");
|
|
11575
|
+
}
|
|
11576
|
+
validate() {
|
|
11577
|
+
const resource = __classPrivateFieldGet(this, _FhirSchemaValidator_root, "f");
|
|
11578
|
+
if (!resource) {
|
|
11579
|
+
throw new OperationOutcomeError(validationError('Resource is null'));
|
|
11580
|
+
}
|
|
11581
|
+
const resourceType = resource.resourceType;
|
|
11582
|
+
if (!resourceType) {
|
|
11583
|
+
throw new OperationOutcomeError(validationError('Missing resource type'));
|
|
11584
|
+
}
|
|
11585
|
+
// Check for "null" once for the entire object hierarchy
|
|
11586
|
+
checkForNull(resource, '', __classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f"));
|
|
11587
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateObject).call(this, toTypedValue(resource), resourceType);
|
|
11588
|
+
if (__classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").length > 0) {
|
|
11589
|
+
throw new OperationOutcomeError({
|
|
11590
|
+
resourceType: 'OperationOutcome',
|
|
11591
|
+
issue: __classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f"),
|
|
11592
|
+
});
|
|
11593
|
+
}
|
|
11594
|
+
}
|
|
11595
|
+
}
|
|
11596
|
+
_FhirSchemaValidator_issues = new WeakMap(), _FhirSchemaValidator_root = new WeakMap(), _FhirSchemaValidator_instances = new WeakSet(), _FhirSchemaValidator_validateObject = function _FhirSchemaValidator_validateObject(typedValue, path) {
|
|
11597
|
+
const definition = globalSchema.types[typedValue.type];
|
|
11598
|
+
if (!definition) {
|
|
11599
|
+
throw new OperationOutcomeError(validationError('Unknown type: ' + typedValue.type));
|
|
11600
|
+
}
|
|
11601
|
+
const propertyDefinitions = definition.properties;
|
|
11602
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkProperties).call(this, path, propertyDefinitions, typedValue);
|
|
11603
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkAdditionalProperties).call(this, path, typedValue, propertyDefinitions);
|
|
11604
|
+
}, _FhirSchemaValidator_checkProperties = function _FhirSchemaValidator_checkProperties(path, propertyDefinitions, typedValue) {
|
|
11605
|
+
for (const [key, elementDefinition] of Object.entries(propertyDefinitions)) {
|
|
11606
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkProperty).call(this, path + '.' + key, elementDefinition, typedValue);
|
|
11607
|
+
}
|
|
11608
|
+
}, _FhirSchemaValidator_checkProperty = function _FhirSchemaValidator_checkProperty(path, elementDefinition, typedValue) {
|
|
11609
|
+
const propertyName = path.split('.').pop();
|
|
11610
|
+
const value = getTypedPropertyValue(typedValue, propertyName);
|
|
11611
|
+
if (isEmpty(value)) {
|
|
11612
|
+
if (elementDefinition.min !== undefined && elementDefinition.min > 0) {
|
|
11613
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(path, 'Missing required property'));
|
|
11614
|
+
}
|
|
11615
|
+
return;
|
|
11616
|
+
}
|
|
11617
|
+
if (elementDefinition.max === '*') {
|
|
11618
|
+
if (!Array.isArray(value)) {
|
|
11619
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(path, 'Expected array for property'));
|
|
11620
|
+
return;
|
|
11621
|
+
}
|
|
11622
|
+
for (const item of value) {
|
|
11623
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkPropertyValue).call(this, path, elementDefinition, item);
|
|
11624
|
+
}
|
|
11625
|
+
}
|
|
11626
|
+
else {
|
|
11627
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkPropertyValue).call(this, path, elementDefinition, value);
|
|
11628
|
+
}
|
|
11629
|
+
}, _FhirSchemaValidator_checkPropertyValue = function _FhirSchemaValidator_checkPropertyValue(path, elementDefinition, typedValue) {
|
|
11630
|
+
if (typedValue.value === null) {
|
|
11631
|
+
// Null handled separately
|
|
11632
|
+
return;
|
|
11633
|
+
}
|
|
11634
|
+
if (isLowerCase(typedValue.type.charAt(0))) {
|
|
11635
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validatePrimitiveType).call(this, elementDefinition, typedValue);
|
|
11636
|
+
}
|
|
11637
|
+
else {
|
|
11638
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateObject).call(this, typedValue, path);
|
|
11639
|
+
}
|
|
11640
|
+
}, _FhirSchemaValidator_validatePrimitiveType = function _FhirSchemaValidator_validatePrimitiveType(elementDefinition, typedValue) {
|
|
11641
|
+
const { type, value } = typedValue;
|
|
11642
|
+
if (value === null) {
|
|
11643
|
+
// Null handled separately, so this code should never be reached
|
|
11644
|
+
// Leaving this check in place for now, in case we change the null handling
|
|
11645
|
+
return;
|
|
11646
|
+
}
|
|
11647
|
+
// First, make sure the value is the correct JS type
|
|
11648
|
+
const expectedType = fhirTypeToJsType[typedValue.type];
|
|
11649
|
+
if (typeof value !== expectedType) {
|
|
11650
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Invalid type for ' + type);
|
|
11651
|
+
return;
|
|
11652
|
+
}
|
|
11653
|
+
// Then, perform additional checks for specialty types
|
|
11654
|
+
if (expectedType === 'string') {
|
|
11655
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateString).call(this, elementDefinition, type, value);
|
|
11656
|
+
}
|
|
11657
|
+
else if (expectedType === 'number') {
|
|
11658
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateNumber).call(this, elementDefinition, type, value);
|
|
11659
|
+
}
|
|
11660
|
+
}, _FhirSchemaValidator_validateString = function _FhirSchemaValidator_validateString(elementDefinition, type, value) {
|
|
11661
|
+
if (!value.trim()) {
|
|
11662
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Invalid empty string');
|
|
11663
|
+
return;
|
|
11664
|
+
}
|
|
11665
|
+
// Try to get the regex
|
|
11666
|
+
const valueDefinition = globalSchema.types[type]?.properties?.['value'];
|
|
11667
|
+
if (valueDefinition?.type) {
|
|
11668
|
+
const regex = getExtensionValue(valueDefinition.type[0], 'http://hl7.org/fhir/StructureDefinition/regex');
|
|
11669
|
+
if (regex) {
|
|
11670
|
+
if (!value.match(new RegExp(regex))) {
|
|
11671
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Invalid ' + type + ' format');
|
|
11672
|
+
}
|
|
11673
|
+
}
|
|
11674
|
+
}
|
|
11675
|
+
}, _FhirSchemaValidator_validateNumber = function _FhirSchemaValidator_validateNumber(elementDefinition, type, value) {
|
|
11676
|
+
if (isNaN(value) || !isFinite(value)) {
|
|
11677
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Invalid ' + type + ' value');
|
|
11678
|
+
return;
|
|
11679
|
+
}
|
|
11680
|
+
if (isIntegerType(type) && !Number.isInteger(value)) {
|
|
11681
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Number is not an integer');
|
|
11682
|
+
}
|
|
11683
|
+
if (type === exports.PropertyType.positiveInt && value <= 0) {
|
|
11684
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Number is less than or equal to zero');
|
|
11685
|
+
}
|
|
11686
|
+
if (type === exports.PropertyType.unsignedInt && value < 0) {
|
|
11687
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Number is negative');
|
|
11688
|
+
}
|
|
11689
|
+
}, _FhirSchemaValidator_checkAdditionalProperties = function _FhirSchemaValidator_checkAdditionalProperties(path, typedValue, propertyDefinitions) {
|
|
11690
|
+
const object = typedValue.value;
|
|
11691
|
+
for (const key of Object.keys(object)) {
|
|
11692
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkAdditionalProperty).call(this, path, key, typedValue, propertyDefinitions);
|
|
11693
|
+
}
|
|
11694
|
+
}, _FhirSchemaValidator_checkAdditionalProperty = function _FhirSchemaValidator_checkAdditionalProperty(path, key, typedValue, propertyDefinitions) {
|
|
11695
|
+
if (!baseResourceProperties.has(key) &&
|
|
11696
|
+
!(key in propertyDefinitions) &&
|
|
11697
|
+
!isChoiceOfType(key, typedValue, propertyDefinitions) &&
|
|
11698
|
+
!__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkPrimitiveElement).call(this, path, key, typedValue)) {
|
|
11699
|
+
const expression = `${path}.${key}`;
|
|
11700
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(expression, `Invalid additional property "${expression}"`));
|
|
11701
|
+
}
|
|
11702
|
+
}, _FhirSchemaValidator_checkPrimitiveElement = function _FhirSchemaValidator_checkPrimitiveElement(path, key, typedValue) {
|
|
11703
|
+
// Primitive element starts with underscore
|
|
11704
|
+
if (!key.startsWith('_')) {
|
|
11705
|
+
return false;
|
|
11706
|
+
}
|
|
11707
|
+
// Validate the non-underscore property exists
|
|
11708
|
+
const primitiveKey = key.slice(1);
|
|
11709
|
+
if (!(primitiveKey in typedValue.value)) {
|
|
11710
|
+
return false;
|
|
11711
|
+
}
|
|
11712
|
+
// Then validate the element
|
|
11713
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateObject).call(this, { type: 'Element', value: typedValue.value[key] }, path);
|
|
11714
|
+
return true;
|
|
11715
|
+
}, _FhirSchemaValidator_createIssue = function _FhirSchemaValidator_createIssue(elementDefinition, message) {
|
|
11716
|
+
__classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(elementDefinition.path, message));
|
|
11717
|
+
};
|
|
11718
|
+
function isIntegerType(propertyType) {
|
|
11719
|
+
return (propertyType === exports.PropertyType.integer ||
|
|
11720
|
+
propertyType === exports.PropertyType.positiveInt ||
|
|
11721
|
+
propertyType === exports.PropertyType.unsignedInt);
|
|
11722
|
+
}
|
|
11723
|
+
function isChoiceOfType(key, typedValue, propertyDefinitions) {
|
|
11724
|
+
for (const propertyName of Object.keys(propertyDefinitions)) {
|
|
11725
|
+
if (!propertyName.endsWith('[x]')) {
|
|
11726
|
+
continue;
|
|
11727
|
+
}
|
|
11728
|
+
const basePropertyName = propertyName.replace('[x]', '');
|
|
11729
|
+
if (!key.startsWith(basePropertyName)) {
|
|
11730
|
+
continue;
|
|
11731
|
+
}
|
|
11732
|
+
let typedPropertyValue = getTypedPropertyValue(typedValue, propertyName);
|
|
11733
|
+
if (!typedPropertyValue) {
|
|
11734
|
+
continue;
|
|
11735
|
+
}
|
|
11736
|
+
if (Array.isArray(typedPropertyValue)) {
|
|
11737
|
+
// At present, there are no choice types that are arrays in the FHIR spec
|
|
11738
|
+
// Leaving this here to make TypeScript happy, and in case that changes
|
|
11739
|
+
typedPropertyValue = typedPropertyValue[0];
|
|
11740
|
+
}
|
|
11741
|
+
if (typedPropertyValue && key === basePropertyName + capitalize(typedPropertyValue.type)) {
|
|
11742
|
+
return true;
|
|
11743
|
+
}
|
|
11744
|
+
}
|
|
11745
|
+
return false;
|
|
11746
|
+
}
|
|
11747
|
+
/**
|
|
11748
|
+
* Recursively checks for null values in an object.
|
|
11749
|
+
*
|
|
11750
|
+
* Note that "null" is a special value in JSON that is not allowed in FHIR.
|
|
11751
|
+
*
|
|
11752
|
+
* @param value Input value of any type.
|
|
11753
|
+
* @param path Path string to the value for OperationOutcome.
|
|
11754
|
+
* @param issues Output list of issues.
|
|
11755
|
+
*/
|
|
11756
|
+
function checkForNull(value, path, issues) {
|
|
11757
|
+
if (value === null) {
|
|
11758
|
+
issues.push(createStructureIssue(path, 'Invalid null value'));
|
|
11759
|
+
}
|
|
11760
|
+
else if (Array.isArray(value)) {
|
|
11761
|
+
checkArrayForNull(value, path, issues);
|
|
11762
|
+
}
|
|
11763
|
+
else if (typeof value === 'object') {
|
|
11764
|
+
checkObjectForNull(value, path, issues);
|
|
11765
|
+
}
|
|
11766
|
+
}
|
|
11767
|
+
function checkArrayForNull(array, path, issues) {
|
|
11768
|
+
for (let i = 0; i < array.length; i++) {
|
|
11769
|
+
if (array[i] === undefined) {
|
|
11770
|
+
issues.push(createStructureIssue(`${path}[${i}]`, 'Invalid undefined value'));
|
|
11771
|
+
}
|
|
11772
|
+
else {
|
|
11773
|
+
checkForNull(array[i], `${path}[${i}]`, issues);
|
|
11774
|
+
}
|
|
11775
|
+
}
|
|
11776
|
+
}
|
|
11777
|
+
function checkObjectForNull(obj, path, issues) {
|
|
11778
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
11779
|
+
checkForNull(value, `${path}${path ? '.' : ''}${key}`, issues);
|
|
11780
|
+
}
|
|
11781
|
+
}
|
|
11782
|
+
function createStructureIssue(expression, details) {
|
|
11783
|
+
return {
|
|
11784
|
+
severity: 'error',
|
|
11785
|
+
code: 'structure',
|
|
11786
|
+
details: {
|
|
11787
|
+
text: details,
|
|
11788
|
+
},
|
|
11789
|
+
expression: [expression],
|
|
11790
|
+
};
|
|
11791
|
+
}
|
|
11792
|
+
|
|
10967
11793
|
exports.SearchParameterType = void 0;
|
|
10968
11794
|
(function (SearchParameterType) {
|
|
10969
11795
|
SearchParameterType["BOOLEAN"] = "BOOLEAN";
|
|
@@ -11698,7 +12524,11 @@
|
|
|
11698
12524
|
exports.EquivalentAtom = EquivalentAtom;
|
|
11699
12525
|
exports.FHIRPATH_KEYWORDS = FHIRPATH_KEYWORDS;
|
|
11700
12526
|
exports.FHIRPATH_OPERATORS = FHIRPATH_OPERATORS;
|
|
12527
|
+
exports.FhirFilterComparison = FhirFilterComparison;
|
|
12528
|
+
exports.FhirFilterConnective = FhirFilterConnective;
|
|
12529
|
+
exports.FhirFilterNegation = FhirFilterNegation;
|
|
11701
12530
|
exports.FhirPathAtom = FhirPathAtom;
|
|
12531
|
+
exports.FhirSchemaValidator = FhirSchemaValidator;
|
|
11702
12532
|
exports.FunctionAtom = FunctionAtom;
|
|
11703
12533
|
exports.Hl7Context = Hl7Context;
|
|
11704
12534
|
exports.Hl7Field = Hl7Field;
|
|
@@ -11706,6 +12536,7 @@
|
|
|
11706
12536
|
exports.Hl7Segment = Hl7Segment;
|
|
11707
12537
|
exports.InAtom = InAtom;
|
|
11708
12538
|
exports.IndexerAtom = IndexerAtom;
|
|
12539
|
+
exports.InfixOperatorAtom = InfixOperatorAtom;
|
|
11709
12540
|
exports.IsAtom = IsAtom;
|
|
11710
12541
|
exports.LRUCache = LRUCache;
|
|
11711
12542
|
exports.LiteralAtom = LiteralAtom;
|
|
@@ -11715,8 +12546,12 @@
|
|
|
11715
12546
|
exports.NotEquivalentAtom = NotEquivalentAtom;
|
|
11716
12547
|
exports.OperationOutcomeError = OperationOutcomeError;
|
|
11717
12548
|
exports.OrAtom = OrAtom;
|
|
12549
|
+
exports.Parser = Parser;
|
|
12550
|
+
exports.ParserBuilder = ParserBuilder;
|
|
12551
|
+
exports.PrefixOperatorAtom = PrefixOperatorAtom;
|
|
11718
12552
|
exports.ReadablePromise = ReadablePromise;
|
|
11719
12553
|
exports.SymbolAtom = SymbolAtom;
|
|
12554
|
+
exports.Tokenizer = Tokenizer;
|
|
11720
12555
|
exports.UnaryOperatorAtom = UnaryOperatorAtom;
|
|
11721
12556
|
exports.UnionAtom = UnionAtom;
|
|
11722
12557
|
exports.XorAtom = XorAtom;
|
|
@@ -11730,7 +12565,9 @@
|
|
|
11730
12565
|
exports.calculateAge = calculateAge;
|
|
11731
12566
|
exports.calculateAgeString = calculateAgeString;
|
|
11732
12567
|
exports.capitalize = capitalize;
|
|
12568
|
+
exports.checkForNull = checkForNull;
|
|
11733
12569
|
exports.createReference = createReference;
|
|
12570
|
+
exports.createStructureIssue = createStructureIssue;
|
|
11734
12571
|
exports.created = created;
|
|
11735
12572
|
exports.deepClone = deepClone;
|
|
11736
12573
|
exports.deepEquals = deepEquals$1;
|
|
@@ -11798,7 +12635,10 @@
|
|
|
11798
12635
|
exports.isProfileResource = isProfileResource;
|
|
11799
12636
|
exports.isQuantity = isQuantity;
|
|
11800
12637
|
exports.isQuantityEquivalent = isQuantityEquivalent;
|
|
12638
|
+
exports.isReference = isReference;
|
|
12639
|
+
exports.isResource = isResource;
|
|
11801
12640
|
exports.isResourceType = isResourceType;
|
|
12641
|
+
exports.isResourceTypeSchema = isResourceTypeSchema;
|
|
11802
12642
|
exports.isStringArray = isStringArray;
|
|
11803
12643
|
exports.isUUID = isUUID;
|
|
11804
12644
|
exports.isValidDate = isValidDate;
|
|
@@ -11809,7 +12649,9 @@
|
|
|
11809
12649
|
exports.notFound = notFound;
|
|
11810
12650
|
exports.notModified = notModified;
|
|
11811
12651
|
exports.parseFhirPath = parseFhirPath;
|
|
12652
|
+
exports.parseFilterParameter = parseFilterParameter;
|
|
11812
12653
|
exports.parseJWTPayload = parseJWTPayload;
|
|
12654
|
+
exports.parseMappingLanguage = parseMappingLanguage;
|
|
11813
12655
|
exports.parseSearchDefinition = parseSearchDefinition;
|
|
11814
12656
|
exports.parseSearchRequest = parseSearchRequest;
|
|
11815
12657
|
exports.parseSearchUrl = parseSearchUrl;
|
|
@@ -11825,9 +12667,12 @@
|
|
|
11825
12667
|
exports.stringify = stringify;
|
|
11826
12668
|
exports.toJsBoolean = toJsBoolean;
|
|
11827
12669
|
exports.toTypedValue = toTypedValue;
|
|
11828
|
-
exports.tokenize = tokenize;
|
|
12670
|
+
exports.tokenize = tokenize$2;
|
|
11829
12671
|
exports.tooManyRequests = tooManyRequests;
|
|
11830
12672
|
exports.unauthorized = unauthorized;
|
|
12673
|
+
exports.validateResource = validateResource;
|
|
12674
|
+
exports.validateResourceType = validateResourceType;
|
|
12675
|
+
exports.validationError = validationError;
|
|
11831
12676
|
|
|
11832
12677
|
}));
|
|
11833
12678
|
//# sourceMappingURL=index.cjs.map
|