@medplum/core 2.0.13 → 2.0.15
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 +1259 -1065
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.min.cjs +1 -1
- package/dist/esm/base64.mjs +33 -0
- package/dist/esm/base64.mjs.map +1 -0
- package/dist/esm/bundle.mjs +36 -0
- package/dist/esm/bundle.mjs.map +1 -0
- package/dist/esm/cache.mjs +17 -23
- package/dist/esm/cache.mjs.map +1 -1
- package/dist/esm/client.mjs +523 -385
- package/dist/esm/client.mjs.map +1 -1
- package/dist/esm/eventtarget.mjs +6 -11
- package/dist/esm/eventtarget.mjs.map +1 -1
- package/dist/esm/fhirlexer/parse.mjs +15 -23
- package/dist/esm/fhirlexer/parse.mjs.map +1 -1
- package/dist/esm/fhirlexer/tokenize.mjs +190 -180
- package/dist/esm/fhirlexer/tokenize.mjs.map +1 -1
- package/dist/esm/fhirmapper/parse.mjs +264 -252
- package/dist/esm/fhirmapper/parse.mjs.map +1 -1
- package/dist/esm/fhirmapper/tokenize.mjs +2 -4
- package/dist/esm/fhirmapper/tokenize.mjs.map +1 -1
- package/dist/esm/fhirpath/atoms.mjs +13 -20
- package/dist/esm/fhirpath/atoms.mjs.map +1 -1
- package/dist/esm/fhirpath/parse.mjs +0 -1
- package/dist/esm/fhirpath/parse.mjs.map +1 -1
- package/dist/esm/fhirpath/tokenize.mjs +0 -1
- package/dist/esm/fhirpath/tokenize.mjs.map +1 -1
- package/dist/esm/filter/parse.mjs +1 -4
- package/dist/esm/filter/parse.mjs.map +1 -1
- package/dist/esm/filter/tokenize.mjs +2 -4
- package/dist/esm/filter/tokenize.mjs.map +1 -1
- package/dist/esm/index.min.mjs +1 -1
- package/dist/esm/index.mjs +1 -0
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/jwt.mjs +2 -9
- package/dist/esm/jwt.mjs.map +1 -1
- package/dist/esm/readablepromise.mjs +18 -23
- package/dist/esm/readablepromise.mjs.map +1 -1
- package/dist/esm/schema.mjs +149 -127
- package/dist/esm/schema.mjs.map +1 -1
- package/dist/esm/search/match.mjs +1 -4
- package/dist/esm/search/match.mjs.map +1 -1
- package/dist/esm/storage.mjs +13 -19
- package/dist/esm/storage.mjs.map +1 -1
- package/dist/types/base64.d.ts +14 -0
- package/dist/types/bundle.d.ts +11 -0
- package/dist/types/cache.d.ts +3 -1
- package/dist/types/client.d.ts +164 -1
- package/dist/types/eventtarget.d.ts +1 -1
- package/dist/types/fhirlexer/parse.d.ts +5 -2
- package/dist/types/fhirlexer/tokenize.d.ts +28 -1
- package/dist/types/fhirpath/atoms.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/readablepromise.d.ts +4 -1
- package/dist/types/schema.d.ts +33 -1
- package/dist/types/storage.d.ts +2 -2
- package/package.json +1 -1
- package/dist/esm/node_modules/tslib/tslib.es6.mjs +0 -30
- package/dist/esm/node_modules/tslib/tslib.es6.mjs.map +0 -1
package/dist/esm/index.mjs
CHANGED
package/dist/esm/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/esm/jwt.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { decodeBase64 } from './base64.mjs';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Decodes a section of a JWT.
|
|
3
5
|
* See: https://tools.ietf.org/html/rfc7519
|
|
@@ -13,15 +15,6 @@ function decodePayload(payload) {
|
|
|
13
15
|
const jsonPayload = decodeURIComponent(uriEncodedPayload);
|
|
14
16
|
return JSON.parse(jsonPayload);
|
|
15
17
|
}
|
|
16
|
-
function decodeBase64(data) {
|
|
17
|
-
if (typeof window !== 'undefined') {
|
|
18
|
-
return window.atob(data);
|
|
19
|
-
}
|
|
20
|
-
if (typeof Buffer !== 'undefined') {
|
|
21
|
-
return Buffer.from(data, 'base64').toString('binary');
|
|
22
|
-
}
|
|
23
|
-
throw new Error('Unable to decode base64');
|
|
24
|
-
}
|
|
25
18
|
/**
|
|
26
19
|
* Parses the JWT payload.
|
|
27
20
|
* @param token JWT token
|
package/dist/esm/jwt.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.mjs","sources":["../../src/jwt.ts"],"sourcesContent":["/**\n * Decodes a section of a JWT.\n * See: https://tools.ietf.org/html/rfc7519\n * @param payload\n */\nfunction decodePayload(payload: string): Record<string, number | string> {\n const cleanedPayload = payload.replace(/-/g, '+').replace(/_/g, '/');\n const decodedPayload = decodeBase64(cleanedPayload);\n const uriEncodedPayload = Array.from(decodedPayload).reduce((acc, char) => {\n const uriEncodedChar = ('00' + char.charCodeAt(0).toString(16)).slice(-2);\n return `${acc}%${uriEncodedChar}`;\n }, '');\n const jsonPayload = decodeURIComponent(uriEncodedPayload);\n return JSON.parse(jsonPayload);\n}\n\
|
|
1
|
+
{"version":3,"file":"jwt.mjs","sources":["../../src/jwt.ts"],"sourcesContent":["import { decodeBase64 } from './base64';\n\n/**\n * Decodes a section of a JWT.\n * See: https://tools.ietf.org/html/rfc7519\n * @param payload\n */\nfunction decodePayload(payload: string): Record<string, number | string> {\n const cleanedPayload = payload.replace(/-/g, '+').replace(/_/g, '/');\n const decodedPayload = decodeBase64(cleanedPayload);\n const uriEncodedPayload = Array.from(decodedPayload).reduce((acc, char) => {\n const uriEncodedChar = ('00' + char.charCodeAt(0).toString(16)).slice(-2);\n return `${acc}%${uriEncodedChar}`;\n }, '');\n const jsonPayload = decodeURIComponent(uriEncodedPayload);\n return JSON.parse(jsonPayload);\n}\n\n/**\n * Parses the JWT payload.\n * @param token JWT token\n */\nexport function parseJWTPayload(token: string): Record<string, number | string> {\n const [_header, payload, _signature] = token.split('.');\n return decodePayload(payload);\n}\n"],"names":[],"mappings":";;AAEA;;;;AAIG;AACH,SAAS,aAAa,CAAC,OAAe,EAAA;AACpC,IAAA,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACrE,IAAA,MAAM,cAAc,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;AACpD,IAAA,MAAM,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,KAAI;QACxE,MAAM,cAAc,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1E,QAAA,OAAO,CAAG,EAAA,GAAG,CAAI,CAAA,EAAA,cAAc,EAAE,CAAC;KACnC,EAAE,EAAE,CAAC,CAAC;AACP,IAAA,MAAM,WAAW,GAAG,kBAAkB,CAAC,iBAAiB,CAAC,CAAC;AAC1D,IAAA,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AACjC,CAAC;AAED;;;AAGG;AACG,SAAU,eAAe,CAAC,KAAa,EAAA;AAC3C,IAAA,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACxD,IAAA,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC;AAChC;;;;"}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var _ReadablePromise_suspender, _ReadablePromise_status, _ReadablePromise_response, _ReadablePromise_error, _a;
|
|
1
|
+
var _a;
|
|
4
2
|
/**
|
|
5
3
|
* The ReadablePromise class wraps a request promise suitable for React Suspense.
|
|
6
4
|
* See: https://blog.logrocket.com/react-suspense-data-fetching/#wrappromise-js
|
|
@@ -9,33 +7,30 @@ var _ReadablePromise_suspender, _ReadablePromise_status, _ReadablePromise_respon
|
|
|
9
7
|
class ReadablePromise {
|
|
10
8
|
constructor(requestPromise) {
|
|
11
9
|
this[_a] = 'ReadablePromise';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
__classPrivateFieldSet(this, _ReadablePromise_suspender, requestPromise.then((res) => {
|
|
17
|
-
__classPrivateFieldSet(this, _ReadablePromise_status, 'success', "f");
|
|
18
|
-
__classPrivateFieldSet(this, _ReadablePromise_response, res, "f");
|
|
10
|
+
this.status = 'pending';
|
|
11
|
+
this.suspender = requestPromise.then((res) => {
|
|
12
|
+
this.status = 'success';
|
|
13
|
+
this.response = res;
|
|
19
14
|
return res;
|
|
20
15
|
}, (err) => {
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
this.status = 'error';
|
|
17
|
+
this.error = err;
|
|
23
18
|
throw err;
|
|
24
|
-
})
|
|
19
|
+
});
|
|
25
20
|
}
|
|
26
21
|
/**
|
|
27
22
|
* Returns true if the promise is pending.
|
|
28
23
|
* @returns True if the Promise is pending.
|
|
29
24
|
*/
|
|
30
25
|
isPending() {
|
|
31
|
-
return
|
|
26
|
+
return this.status === 'pending';
|
|
32
27
|
}
|
|
33
28
|
/**
|
|
34
29
|
* Returns true if the promise resolved successfully.
|
|
35
30
|
* @returns True if the Promise resolved successfully.
|
|
36
31
|
*/
|
|
37
32
|
isOk() {
|
|
38
|
-
return
|
|
33
|
+
return this.status === 'success';
|
|
39
34
|
}
|
|
40
35
|
/**
|
|
41
36
|
* Attempts to read the value of the promise.
|
|
@@ -45,13 +40,13 @@ class ReadablePromise {
|
|
|
45
40
|
* @returns The resolved value of the Promise.
|
|
46
41
|
*/
|
|
47
42
|
read() {
|
|
48
|
-
switch (
|
|
43
|
+
switch (this.status) {
|
|
49
44
|
case 'pending':
|
|
50
|
-
throw
|
|
45
|
+
throw this.suspender;
|
|
51
46
|
case 'error':
|
|
52
|
-
throw
|
|
47
|
+
throw this.error;
|
|
53
48
|
default:
|
|
54
|
-
return
|
|
49
|
+
return this.response;
|
|
55
50
|
}
|
|
56
51
|
}
|
|
57
52
|
/**
|
|
@@ -61,7 +56,7 @@ class ReadablePromise {
|
|
|
61
56
|
* @returns A Promise for the completion of which ever callback is executed.
|
|
62
57
|
*/
|
|
63
58
|
then(onfulfilled, onrejected) {
|
|
64
|
-
return
|
|
59
|
+
return this.suspender.then(onfulfilled, onrejected);
|
|
65
60
|
}
|
|
66
61
|
/**
|
|
67
62
|
* Attaches a callback for only the rejection of the Promise.
|
|
@@ -69,7 +64,7 @@ class ReadablePromise {
|
|
|
69
64
|
* @returns A Promise for the completion of the callback.
|
|
70
65
|
*/
|
|
71
66
|
catch(onrejected) {
|
|
72
|
-
return
|
|
67
|
+
return this.suspender.catch(onrejected);
|
|
73
68
|
}
|
|
74
69
|
/**
|
|
75
70
|
* Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The
|
|
@@ -78,10 +73,10 @@ class ReadablePromise {
|
|
|
78
73
|
* @returns A Promise for the completion of the callback.
|
|
79
74
|
*/
|
|
80
75
|
finally(onfinally) {
|
|
81
|
-
return
|
|
76
|
+
return this.suspender.finally(onfinally);
|
|
82
77
|
}
|
|
83
78
|
}
|
|
84
|
-
|
|
79
|
+
_a = Symbol.toStringTag;
|
|
85
80
|
|
|
86
81
|
export { ReadablePromise };
|
|
87
82
|
//# sourceMappingURL=readablepromise.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readablepromise.mjs","sources":["../../src/readablepromise.ts"],"sourcesContent":["/**\n * The ReadablePromise class wraps a request promise suitable for React Suspense.\n * See: https://blog.logrocket.com/react-suspense-data-fetching/#wrappromise-js\n * See: https://github.com/ovieokeh/suspense-data-fetching/blob/master/lib/api/wrapPromise.js\n */\nexport class ReadablePromise<T> implements Promise<T> {\n readonly [Symbol.toStringTag]: string = 'ReadablePromise';\n
|
|
1
|
+
{"version":3,"file":"readablepromise.mjs","sources":["../../src/readablepromise.ts"],"sourcesContent":["/**\n * The ReadablePromise class wraps a request promise suitable for React Suspense.\n * See: https://blog.logrocket.com/react-suspense-data-fetching/#wrappromise-js\n * See: https://github.com/ovieokeh/suspense-data-fetching/blob/master/lib/api/wrapPromise.js\n */\nexport class ReadablePromise<T> implements Promise<T> {\n readonly [Symbol.toStringTag]: string = 'ReadablePromise';\n private suspender: Promise<T>;\n private status: 'pending' | 'error' | 'success' = 'pending';\n private response: T | undefined;\n private error: Error | undefined;\n\n constructor(requestPromise: Promise<T>) {\n this.suspender = requestPromise.then(\n (res: T) => {\n this.status = 'success';\n this.response = res;\n return res;\n },\n (err: any) => {\n this.status = 'error';\n this.error = err;\n throw err;\n }\n );\n }\n\n /**\n * Returns true if the promise is pending.\n * @returns True if the Promise is pending.\n */\n isPending(): boolean {\n return this.status === 'pending';\n }\n\n /**\n * Returns true if the promise resolved successfully.\n * @returns True if the Promise resolved successfully.\n */\n isOk(): boolean {\n return this.status === 'success';\n }\n\n /**\n * Attempts to read the value of the promise.\n * If the promise is pending, this method will throw a promise.\n * If the promise rejected, this method will throw the rejection reason.\n * If the promise resolved, this method will return the resolved value.\n * @returns The resolved value of the Promise.\n */\n read(): T {\n switch (this.status) {\n case 'pending':\n throw this.suspender;\n case 'error':\n throw this.error;\n default:\n return this.response as T;\n }\n }\n\n /**\n * Attaches callbacks for the resolution and/or rejection of the Promise.\n * @param onfulfilled The callback to execute when the Promise is resolved.\n * @param onrejected The callback to execute when the Promise is rejected.\n * @returns A Promise for the completion of which ever callback is executed.\n */\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null\n ): Promise<TResult1 | TResult2> {\n return this.suspender.then(onfulfilled, onrejected);\n }\n\n /**\n * Attaches a callback for only the rejection of the Promise.\n * @param onrejected The callback to execute when the Promise is rejected.\n * @returns A Promise for the completion of the callback.\n */\n catch<TResult = never>(\n onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null\n ): Promise<T | TResult> {\n return this.suspender.catch(onrejected);\n }\n\n /**\n * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The\n * resolved value cannot be modified from the callback.\n * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected).\n * @returns A Promise for the completion of the callback.\n */\n finally(onfinally?: (() => void) | undefined | null): Promise<T> {\n return this.suspender.finally(onfinally);\n }\n}\n"],"names":[],"mappings":";AAAA;;;;AAIG;MACU,eAAe,CAAA;AAO1B,IAAA,WAAA,CAAY,cAA0B,EAAA;QAN7B,IAAoB,CAAA,EAAA,CAAA,GAAW,iBAAiB,CAAC;QAElD,IAAM,CAAA,MAAA,GAAoC,SAAS,CAAC;QAK1D,IAAI,CAAC,SAAS,GAAG,cAAc,CAAC,IAAI,CAClC,CAAC,GAAM,KAAI;AACT,YAAA,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;AACxB,YAAA,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC;AACpB,YAAA,OAAO,GAAG,CAAC;AACb,SAAC,EACD,CAAC,GAAQ,KAAI;AACX,YAAA,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC;AACtB,YAAA,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC;AACjB,YAAA,MAAM,GAAG,CAAC;AACZ,SAAC,CACF,CAAC;KACH;AAED;;;AAGG;IACH,SAAS,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;KAClC;AAED;;;AAGG;IACH,IAAI,GAAA;AACF,QAAA,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;KAClC;AAED;;;;;;AAMG;IACH,IAAI,GAAA;QACF,QAAQ,IAAI,CAAC,MAAM;AACjB,YAAA,KAAK,SAAS;gBACZ,MAAM,IAAI,CAAC,SAAS,CAAC;AACvB,YAAA,KAAK,OAAO;gBACV,MAAM,IAAI,CAAC,KAAK,CAAC;AACnB,YAAA;gBACE,OAAO,IAAI,CAAC,QAAa,CAAC;AAC7B,SAAA;KACF;AAED;;;;;AAKG;IACH,IAAI,CACF,WAAiF,EACjF,UAAmF,EAAA;QAEnF,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;KACrD;AAED;;;;AAIG;AACH,IAAA,KAAK,CACH,UAAiF,EAAA;QAEjF,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;KACzC;AAED;;;;;AAKG;AACH,IAAA,OAAO,CAAC,SAA2C,EAAA;QACjD,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;KAC1C;AACF,CAAA;AAxFW,EAAA,GAAA,MAAM,CAAC,WAAW;;;;"}
|
package/dist/esm/schema.mjs
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import { __classPrivateFieldSet, __classPrivateFieldGet } from './node_modules/tslib/tslib.es6.mjs';
|
|
2
|
-
import './fhirpath/atoms.mjs';
|
|
3
|
-
import './fhirpath/parse.mjs';
|
|
4
|
-
import './fhirlexer/parse.mjs';
|
|
5
|
-
import './fhirlexer/tokenize.mjs';
|
|
6
|
-
import { toTypedValue, getTypedPropertyValue } from './fhirpath/utils.mjs';
|
|
7
|
-
import { OperationOutcomeError, validationError } from './outcomes.mjs';
|
|
8
1
|
import { globalSchema, PropertyType } from './types.mjs';
|
|
9
2
|
import { isEmpty, isLowerCase, getExtensionValue, capitalize } from './utils.mjs';
|
|
3
|
+
import { toTypedValue, getTypedPropertyValue } from './fhirpath/utils.mjs';
|
|
4
|
+
import './fhirpath/parse.mjs';
|
|
5
|
+
import { OperationOutcomeError, validationError } from './outcomes.mjs';
|
|
10
6
|
|
|
11
|
-
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;
|
|
12
7
|
/*
|
|
13
8
|
* This file provides schema validation utilities for FHIR JSON objects.
|
|
14
9
|
*
|
|
@@ -170,14 +165,11 @@ function validateResource(resource) {
|
|
|
170
165
|
}
|
|
171
166
|
class FhirSchemaValidator {
|
|
172
167
|
constructor(root) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
_FhirSchemaValidator_root.set(this, void 0);
|
|
176
|
-
__classPrivateFieldSet(this, _FhirSchemaValidator_issues, [], "f");
|
|
177
|
-
__classPrivateFieldSet(this, _FhirSchemaValidator_root, root, "f");
|
|
168
|
+
this.issues = [];
|
|
169
|
+
this.root = root;
|
|
178
170
|
}
|
|
179
171
|
validate() {
|
|
180
|
-
const resource =
|
|
172
|
+
const resource = this.root;
|
|
181
173
|
if (!resource) {
|
|
182
174
|
throw new OperationOutcomeError(validationError('Resource is null'));
|
|
183
175
|
}
|
|
@@ -186,142 +178,172 @@ class FhirSchemaValidator {
|
|
|
186
178
|
throw new OperationOutcomeError(validationError('Missing resource type'));
|
|
187
179
|
}
|
|
188
180
|
// Check for "null" once for the entire object hierarchy
|
|
189
|
-
checkForNull(resource, '',
|
|
190
|
-
|
|
191
|
-
if (
|
|
181
|
+
checkForNull(resource, '', this.issues);
|
|
182
|
+
this.validateObject(toTypedValue(resource), resourceType);
|
|
183
|
+
if (this.issues.length > 0) {
|
|
192
184
|
throw new OperationOutcomeError({
|
|
193
185
|
resourceType: 'OperationOutcome',
|
|
194
|
-
issue:
|
|
186
|
+
issue: this.issues,
|
|
195
187
|
});
|
|
196
188
|
}
|
|
197
189
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkAdditionalProperties).call(this, path, typedValue, propertyDefinitions);
|
|
207
|
-
}, _FhirSchemaValidator_checkProperties = function _FhirSchemaValidator_checkProperties(path, propertyDefinitions, typedValue) {
|
|
208
|
-
for (const [key, elementDefinition] of Object.entries(propertyDefinitions)) {
|
|
209
|
-
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_checkProperty).call(this, path + '.' + key, elementDefinition, typedValue);
|
|
190
|
+
validateObject(typedValue, path) {
|
|
191
|
+
const definition = globalSchema.types[typedValue.type];
|
|
192
|
+
if (!definition) {
|
|
193
|
+
throw new OperationOutcomeError(validationError('Unknown type: ' + typedValue.type));
|
|
194
|
+
}
|
|
195
|
+
const propertyDefinitions = definition.properties;
|
|
196
|
+
this.checkProperties(path, propertyDefinitions, typedValue);
|
|
197
|
+
this.checkAdditionalProperties(path, typedValue, propertyDefinitions);
|
|
210
198
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (elementDefinition.min !== undefined && elementDefinition.min > 0) {
|
|
216
|
-
__classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(path, 'Missing required property'));
|
|
217
|
-
}
|
|
218
|
-
return;
|
|
199
|
+
checkProperties(path, propertyDefinitions, typedValue) {
|
|
200
|
+
for (const [key, elementDefinition] of Object.entries(propertyDefinitions)) {
|
|
201
|
+
this.checkProperty(path + '.' + key, elementDefinition, typedValue);
|
|
202
|
+
}
|
|
219
203
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
204
|
+
checkProperty(path, elementDefinition, typedValue) {
|
|
205
|
+
const propertyName = path.split('.').pop();
|
|
206
|
+
const value = getTypedPropertyValue(typedValue, propertyName);
|
|
207
|
+
if (isEmpty(value)) {
|
|
208
|
+
if (elementDefinition.min !== undefined && elementDefinition.min > 0) {
|
|
209
|
+
this.issues.push(createStructureIssue(path, 'Missing required property'));
|
|
210
|
+
}
|
|
223
211
|
return;
|
|
224
212
|
}
|
|
225
|
-
|
|
226
|
-
|
|
213
|
+
if (elementDefinition.max === '*') {
|
|
214
|
+
if (!Array.isArray(value)) {
|
|
215
|
+
this.issues.push(createStructureIssue(path, 'Expected array for property'));
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
for (const item of value) {
|
|
219
|
+
this.checkPropertyValue(path, elementDefinition, item);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
if (Array.isArray(value)) {
|
|
224
|
+
this.issues.push(createStructureIssue(path, 'Expected single value for property'));
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
this.checkPropertyValue(path, elementDefinition, value);
|
|
227
228
|
}
|
|
228
229
|
}
|
|
229
|
-
|
|
230
|
-
if (
|
|
231
|
-
|
|
230
|
+
checkPropertyValue(path, elementDefinition, typedValue) {
|
|
231
|
+
if (typedValue.value === null) {
|
|
232
|
+
// Null handled separately
|
|
232
233
|
return;
|
|
233
234
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
if (isLowerCase(typedValue.type.charAt(0))) {
|
|
242
|
-
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validatePrimitiveType).call(this, elementDefinition, typedValue);
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateObject).call(this, typedValue, path);
|
|
246
|
-
}
|
|
247
|
-
}, _FhirSchemaValidator_validatePrimitiveType = function _FhirSchemaValidator_validatePrimitiveType(elementDefinition, typedValue) {
|
|
248
|
-
const { type, value } = typedValue;
|
|
249
|
-
if (value === null) {
|
|
250
|
-
// Null handled separately, so this code should never be reached
|
|
251
|
-
// Leaving this check in place for now, in case we change the null handling
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
// First, make sure the value is the correct JS type
|
|
255
|
-
const expectedType = fhirTypeToJsType[typedValue.type];
|
|
256
|
-
if (typeof value !== expectedType) {
|
|
257
|
-
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_createIssue).call(this, elementDefinition, 'Invalid type for ' + type);
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
// Then, perform additional checks for specialty types
|
|
261
|
-
if (expectedType === 'string') {
|
|
262
|
-
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateString).call(this, elementDefinition, type, value);
|
|
263
|
-
}
|
|
264
|
-
else if (expectedType === 'number') {
|
|
265
|
-
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateNumber).call(this, elementDefinition, type, value);
|
|
235
|
+
if (isLowerCase(typedValue.type.charAt(0))) {
|
|
236
|
+
this.validatePrimitiveType(elementDefinition, typedValue);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
this.validateObject(typedValue, path);
|
|
240
|
+
}
|
|
266
241
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
242
|
+
validatePrimitiveType(elementDefinition, typedValue) {
|
|
243
|
+
const { type, value } = typedValue;
|
|
244
|
+
if (value === null) {
|
|
245
|
+
// Null handled separately, so this code should never be reached
|
|
246
|
+
// Leaving this check in place for now, in case we change the null handling
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
// First, make sure the value is the correct JS type
|
|
250
|
+
const expectedType = fhirTypeToJsType[typedValue.type];
|
|
251
|
+
if (typeof value !== expectedType) {
|
|
252
|
+
this.createIssue(elementDefinition, 'Invalid type for ' + type);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
// Then, perform additional checks for specialty types
|
|
256
|
+
if (expectedType === 'string') {
|
|
257
|
+
this.validateString(elementDefinition, type, value);
|
|
258
|
+
}
|
|
259
|
+
else if (expectedType === 'number') {
|
|
260
|
+
this.validateNumber(elementDefinition, type, value);
|
|
261
|
+
}
|
|
271
262
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
263
|
+
validateString(elementDefinition, type, value) {
|
|
264
|
+
if (!value.trim()) {
|
|
265
|
+
this.createIssue(elementDefinition, 'Invalid empty string');
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
// Try to get the regex
|
|
269
|
+
const valueDefinition = globalSchema.types[type]?.properties?.['value'];
|
|
270
|
+
if (valueDefinition?.type) {
|
|
271
|
+
const regex = getExtensionValue(valueDefinition.type[0], 'http://hl7.org/fhir/StructureDefinition/regex');
|
|
272
|
+
if (regex) {
|
|
273
|
+
if (!value.match(new RegExp(regex))) {
|
|
274
|
+
this.createIssue(elementDefinition, 'Invalid ' + type + ' format');
|
|
275
|
+
}
|
|
279
276
|
}
|
|
280
277
|
}
|
|
281
278
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
279
|
+
validateNumber(elementDefinition, type, value) {
|
|
280
|
+
if (isNaN(value) || !isFinite(value)) {
|
|
281
|
+
this.createIssue(elementDefinition, 'Invalid ' + type + ' value');
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (isIntegerType(type) && !Number.isInteger(value)) {
|
|
285
|
+
this.createIssue(elementDefinition, 'Number is not an integer');
|
|
286
|
+
}
|
|
287
|
+
if (type === PropertyType.positiveInt && value <= 0) {
|
|
288
|
+
this.createIssue(elementDefinition, 'Number is less than or equal to zero');
|
|
289
|
+
}
|
|
290
|
+
if (type === PropertyType.unsignedInt && value < 0) {
|
|
291
|
+
this.createIssue(elementDefinition, 'Number is negative');
|
|
292
|
+
}
|
|
295
293
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
294
|
+
checkAdditionalProperties(path, typedValue, propertyDefinitions) {
|
|
295
|
+
const object = typedValue.value;
|
|
296
|
+
for (const key of Object.keys(object)) {
|
|
297
|
+
this.checkAdditionalProperty(path, key, typedValue, propertyDefinitions);
|
|
298
|
+
}
|
|
300
299
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
300
|
+
/**
|
|
301
|
+
* Checks if the given property is allowed on the given object.
|
|
302
|
+
* @param path The path of the current object.
|
|
303
|
+
* @param key The key of a property to check.
|
|
304
|
+
* @param typedValue The current object.
|
|
305
|
+
* @param propertyDefinitions The property definitions of the current object.
|
|
306
|
+
*/
|
|
307
|
+
checkAdditionalProperty(path, key, typedValue, propertyDefinitions) {
|
|
308
|
+
if (!baseResourceProperties.has(key) &&
|
|
309
|
+
!(key in propertyDefinitions) &&
|
|
310
|
+
!isChoiceOfType(key, typedValue, propertyDefinitions) &&
|
|
311
|
+
!this.checkPrimitiveElement(path, key, typedValue)) {
|
|
312
|
+
const expression = `${path}.${key}`;
|
|
313
|
+
this.issues.push(createStructureIssue(expression, `Invalid additional property "${expression}"`));
|
|
314
|
+
}
|
|
308
315
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
316
|
+
/**
|
|
317
|
+
* Checks the element for a primitive.
|
|
318
|
+
*
|
|
319
|
+
* FHIR elements with primitive data types are represented in two parts:
|
|
320
|
+
* 1) A JSON property with the name of the element, which has a JSON type of number, boolean, or string
|
|
321
|
+
* 2) a JSON property with _ prepended to the name of the element, which, if present, contains the value's id and/or extensions
|
|
322
|
+
*
|
|
323
|
+
* See: https://hl7.org/fhir/json.html#primitive
|
|
324
|
+
*
|
|
325
|
+
* @param path The path to the property
|
|
326
|
+
* @param key
|
|
327
|
+
* @param typedValue
|
|
328
|
+
*/
|
|
329
|
+
checkPrimitiveElement(path, key, typedValue) {
|
|
330
|
+
// Primitive element starts with underscore
|
|
331
|
+
if (!key.startsWith('_')) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
// Validate the non-underscore property exists
|
|
335
|
+
const primitiveKey = key.slice(1);
|
|
336
|
+
if (!(primitiveKey in typedValue.value)) {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
// Then validate the element
|
|
340
|
+
this.validateObject({ type: 'Element', value: typedValue.value[key] }, path);
|
|
341
|
+
return true;
|
|
313
342
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
if (!(primitiveKey in typedValue.value)) {
|
|
317
|
-
return false;
|
|
343
|
+
createIssue(elementDefinition, message) {
|
|
344
|
+
this.issues.push(createStructureIssue(elementDefinition.path, message));
|
|
318
345
|
}
|
|
319
|
-
|
|
320
|
-
__classPrivateFieldGet(this, _FhirSchemaValidator_instances, "m", _FhirSchemaValidator_validateObject).call(this, { type: 'Element', value: typedValue.value[key] }, path);
|
|
321
|
-
return true;
|
|
322
|
-
}, _FhirSchemaValidator_createIssue = function _FhirSchemaValidator_createIssue(elementDefinition, message) {
|
|
323
|
-
__classPrivateFieldGet(this, _FhirSchemaValidator_issues, "f").push(createStructureIssue(elementDefinition.path, message));
|
|
324
|
-
};
|
|
346
|
+
}
|
|
325
347
|
function isIntegerType(propertyType) {
|
|
326
348
|
return (propertyType === PropertyType.integer ||
|
|
327
349
|
propertyType === PropertyType.positiveInt ||
|