@haste-health/fhir-validation 0.14.3
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/README.md +4 -0
- package/lib/elements/conformance.d.ts +9 -0
- package/lib/elements/conformance.js +40 -0
- package/lib/elements/conformance.js.map +1 -0
- package/lib/elements/primitive.d.ts +5 -0
- package/lib/elements/primitive.js +102 -0
- package/lib/elements/primitive.js.map +1 -0
- package/lib/elements/validators/cardinality.d.ts +3 -0
- package/lib/elements/validators/cardinality.js +57 -0
- package/lib/elements/validators/cardinality.js.map +1 -0
- package/lib/elements/validators/fixedValue.d.ts +4 -0
- package/lib/elements/validators/fixedValue.js +20 -0
- package/lib/elements/validators/fixedValue.js.map +1 -0
- package/lib/elements/validators/pattern.d.ts +11 -0
- package/lib/elements/validators/pattern.js +53 -0
- package/lib/elements/validators/pattern.js.map +1 -0
- package/lib/elements/validators/value.d.ts +10 -0
- package/lib/elements/validators/value.js +18 -0
- package/lib/elements/validators/value.js.map +1 -0
- package/lib/elements/validators.d.ts +8 -0
- package/lib/elements/validators.js +37 -0
- package/lib/elements/validators.js.map +1 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +13 -0
- package/lib/index.js.map +1 -0
- package/lib/profile/element.d.ts +40 -0
- package/lib/profile/element.js +180 -0
- package/lib/profile/element.js.map +1 -0
- package/lib/profile/index.d.ts +20 -0
- package/lib/profile/index.js +45 -0
- package/lib/profile/index.js.map +1 -0
- package/lib/profile/slicing/index.d.ts +24 -0
- package/lib/profile/slicing/index.js +247 -0
- package/lib/profile/slicing/index.js.map +1 -0
- package/lib/profile/slicing.d.ts +47 -0
- package/lib/profile/slicing.js +195 -0
- package/lib/profile/slicing.js.map +1 -0
- package/lib/profile/utilities.d.ts +14 -0
- package/lib/profile/utilities.js +32 -0
- package/lib/profile/utilities.js.map +1 -0
- package/lib/profile/validators.d.ts +8 -0
- package/lib/profile/validators.js +37 -0
- package/lib/profile/validators.js.map +1 -0
- package/lib/slicing/index.d.ts +47 -0
- package/lib/slicing/index.js +197 -0
- package/lib/slicing/index.js.map +1 -0
- package/lib/structural/index.d.ts +4 -0
- package/lib/structural/index.js +296 -0
- package/lib/structural/index.js.map +1 -0
- package/lib/structural/validate-primitive.d.ts +11 -0
- package/lib/structural/validate-primitive.js +102 -0
- package/lib/structural/validate-primitive.js.map +1 -0
- package/lib/types.d.ts +10 -0
- package/lib/types.js +2 -0
- package/lib/types.js.map +1 -0
- package/lib/utilities.d.ts +34 -0
- package/lib/utilities.js +114 -0
- package/lib/utilities.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If primitive: it must match exactly the pattern value
|
|
3
|
+
* If a complex object: it must match (recursively) the pattern value
|
|
4
|
+
* If an array: it must match (recursively) the pattern value.
|
|
5
|
+
* @param pattern
|
|
6
|
+
* @param value
|
|
7
|
+
*/
|
|
8
|
+
export declare function conformsToPattern(pattern: unknown, value: unknown): boolean;
|
|
9
|
+
export declare function conformsToValue(expectedValue: unknown, foundValue: unknown): boolean;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { isObject } from "@iguhealth/meta-value/utilities";
|
|
2
|
+
/**
|
|
3
|
+
* If primitive: it must match exactly the pattern value
|
|
4
|
+
* If a complex object: it must match (recursively) the pattern value
|
|
5
|
+
* If an array: it must match (recursively) the pattern value.
|
|
6
|
+
* @param pattern
|
|
7
|
+
* @param value
|
|
8
|
+
*/
|
|
9
|
+
export function conformsToPattern(pattern, value) {
|
|
10
|
+
if (isObject(pattern)) {
|
|
11
|
+
if (!isObject(value))
|
|
12
|
+
return false;
|
|
13
|
+
if (Array.isArray(pattern)) {
|
|
14
|
+
if (!Array.isArray(value))
|
|
15
|
+
return false;
|
|
16
|
+
for (const singularPattern of pattern) {
|
|
17
|
+
const valueExists = value.filter((v) => conformsToPattern(singularPattern, v));
|
|
18
|
+
// Per spec as long as a single value matches in the pattern then it's truthy
|
|
19
|
+
if (valueExists.length === 0)
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
const patternKeys = Object.keys(pattern);
|
|
26
|
+
for (const key of patternKeys) {
|
|
27
|
+
if (!conformsToPattern(pattern[key], value[key]))
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return pattern === value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function conformsToValue(expectedValue, foundValue) {
|
|
38
|
+
return JSON.stringify(expectedValue) === JSON.stringify(foundValue);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conformance.js","sourceRoot":"","sources":["../../src/elements/conformance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAE3D;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgB,EAAE,KAAc;IAChE,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACnC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;YACxC,KAAK,MAAM,eAAe,IAAI,OAAO,EAAE,CAAC;gBACtC,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACrC,iBAAiB,CAAC,eAAe,EAAE,CAAC,CAAC,CACtC,CAAC;gBACF,6EAA6E;gBAC7E,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO,KAAK,CAAC;YAC7C,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;aAAM,CAAC;YACN,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzC,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;gBAC9B,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;oBAAE,OAAO,KAAK,CAAC;YACjE,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,OAAO,KAAK,KAAK,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,aAAsB,EACtB,UAAmB;IAEnB,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as fpointer from "@haste-health/fhir-pointer";
|
|
2
|
+
import { ElementDefinition } from "@haste-health/fhir-types/r4/types";
|
|
3
|
+
import { FHIR_VERSION, Resource } from "@haste-health/fhir-types/versions";
|
|
4
|
+
import { ValidationCTX } from "../types.js";
|
|
5
|
+
export declare function validatePrimitive(ctx: ValidationCTX, element: ElementDefinition | undefined, rootValue: unknown, path: fpointer.Loc<object, any, any>, type: string): Promise<Resource<FHIR_VERSION, "OperationOutcome">["issue"]>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import * as fpointer from "@haste-health/fhir-pointer";
|
|
3
|
+
import { isObject } from "@haste-health/meta-value/utilities";
|
|
4
|
+
import { OperationError, issueError, outcomeError, } from "@haste-health/operation-outcomes";
|
|
5
|
+
const REGEX = {
|
|
6
|
+
// base64Binary: /^(\s*([0-9a-zA-Z+=]){4}\s*)+$/,
|
|
7
|
+
uuid: /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/,
|
|
8
|
+
time: /^([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?$/,
|
|
9
|
+
oid: /^urn:oid:[0-2](\.(0|[1-9][0-9]*))+$/,
|
|
10
|
+
unsignedInt: /^([0]|([1-9][0-9]*))$/,
|
|
11
|
+
positiveInt: /^(\+?[1-9][0-9]*)$/,
|
|
12
|
+
instant: /^([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))$/,
|
|
13
|
+
id: /^[A-Za-z0-9\-.]{1,64}$/,
|
|
14
|
+
date: /^([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1]))?)?$/,
|
|
15
|
+
dateTime: /^([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)?$/,
|
|
16
|
+
};
|
|
17
|
+
export async function validatePrimitive(ctx, element, rootValue, path, type) {
|
|
18
|
+
let value;
|
|
19
|
+
if (isObject(rootValue))
|
|
20
|
+
value = fpointer.get(path, rootValue);
|
|
21
|
+
else if (path === fpointer.root(path))
|
|
22
|
+
value = rootValue;
|
|
23
|
+
else {
|
|
24
|
+
return [
|
|
25
|
+
issueError("structure", `Expected primitive type '${type}' at path '${fpointer.toJSONPointer(path)}'`, [fpointer.toJSONPointer(path)]),
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
switch (type) {
|
|
29
|
+
case "http://hl7.org/fhirpath/System.String":
|
|
30
|
+
case "date":
|
|
31
|
+
case "dateTime":
|
|
32
|
+
case "time":
|
|
33
|
+
case "instant":
|
|
34
|
+
case "id":
|
|
35
|
+
case "string":
|
|
36
|
+
case "xhtml":
|
|
37
|
+
case "markdown":
|
|
38
|
+
case "base64Binary":
|
|
39
|
+
case "uri":
|
|
40
|
+
case "uuid":
|
|
41
|
+
case "canonical":
|
|
42
|
+
case "oid":
|
|
43
|
+
case "url": {
|
|
44
|
+
if (typeof value !== "string") {
|
|
45
|
+
return [
|
|
46
|
+
issueError("structure", `Expected primitive type '${type}' at path '${fpointer.toJSONPointer(path)}'`, [fpointer.toJSONPointer(path)]),
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
if (REGEX[type] && !REGEX[type].test(value)) {
|
|
50
|
+
return [
|
|
51
|
+
issueError("value", `Invalid value '${value}' at path '${fpointer.toJSONPointer(path)}'. Value must conform to regex '${REGEX[type]}'`, [fpointer.toJSONPointer(path)]),
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
case "boolean": {
|
|
57
|
+
if (typeof value !== "boolean") {
|
|
58
|
+
return [
|
|
59
|
+
issueError("structure", `Expected primitive type '${type}' at path '${fpointer.toJSONPointer(path)}'`, [fpointer.toJSONPointer(path)]),
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
case "code": {
|
|
65
|
+
const strength = element?.binding?.strength;
|
|
66
|
+
const valueSet = element?.binding?.valueSet;
|
|
67
|
+
if (typeof value !== "string") {
|
|
68
|
+
return [
|
|
69
|
+
issueError("structure", `Expected primitive type '${type}' at path '${fpointer.toJSONPointer(path)}'`, [fpointer.toJSONPointer(path)]),
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
if (strength === "required" && valueSet && ctx.validateCode) {
|
|
73
|
+
const isValid = await ctx.validateCode(valueSet, value);
|
|
74
|
+
if (!isValid) {
|
|
75
|
+
return [
|
|
76
|
+
issueError("structure", `Code '${value}' is not in value set '${valueSet}' at path '${fpointer.toJSONPointer(path)}'`, [fpointer.toJSONPointer(path)]),
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
case "integer":
|
|
83
|
+
case "positiveInt":
|
|
84
|
+
case "unsignedInt":
|
|
85
|
+
case "decimal": {
|
|
86
|
+
if (typeof value !== "number") {
|
|
87
|
+
return [
|
|
88
|
+
issueError("structure", `Expected primitive type '${type}' at path '${fpointer.toJSONPointer(path)}'`, [fpointer.toJSONPointer(path)]),
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
if (REGEX[type] && !REGEX[type].test(value.toString())) {
|
|
92
|
+
return [
|
|
93
|
+
issueError("value", `Invalid value '${value}' at path '${fpointer.toJSONPointer(path)}'. Value must conform to regex '${REGEX[type]}'`, [fpointer.toJSONPointer(path)]),
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
default:
|
|
99
|
+
throw new OperationError(outcomeError("structure", `Unknown primitive type '${type}' at path '${fpointer.toJSONPointer(path)}'`, [fpointer.toJSONPointer(path)]));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=primitive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"primitive.js","sourceRoot":"","sources":["../../src/elements/primitive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Loc } from "@haste-health/fhir-pointer";
|
|
2
|
+
import { ElementDefinition, OperationOutcomeIssue } from "@haste-health/fhir-types/r4/types";
|
|
3
|
+
export declare function validateCardinality(element: ElementDefinition, root: object, path: Loc<any, any, any>): Array<OperationOutcomeIssue>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { get, toJSONPointer } from "@haste-health/fhir-pointer";
|
|
3
|
+
import { issueError } from "@haste-health/operation-outcomes";
|
|
4
|
+
/**
|
|
5
|
+
* Returns whether the value should be respresented as an array given max cardinality
|
|
6
|
+
* @param max either a string number or *
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
function isArray(element) {
|
|
10
|
+
// If base is an array should check that first (because profile could restrict to singular value).
|
|
11
|
+
if (!element.path.includes("."))
|
|
12
|
+
return false;
|
|
13
|
+
const base = element.base?.max ?? "1";
|
|
14
|
+
const max = element.max ?? "1";
|
|
15
|
+
return base === "*" || max === "*" || parseInt(base) > 1 || parseInt(max) > 1;
|
|
16
|
+
}
|
|
17
|
+
function getMin(elementDefinition) {
|
|
18
|
+
return elementDefinition.min ?? 0;
|
|
19
|
+
}
|
|
20
|
+
function getMax(elementDefinition) {
|
|
21
|
+
return elementDefinition.max ?? "1";
|
|
22
|
+
}
|
|
23
|
+
export function validateCardinality(element, root, path) {
|
|
24
|
+
const value = get(path, root);
|
|
25
|
+
const max = getMax(element);
|
|
26
|
+
const min = getMin(element);
|
|
27
|
+
// Value could be undefined if min is allowed to be zero.
|
|
28
|
+
if (value === undefined && min === 0)
|
|
29
|
+
return [];
|
|
30
|
+
const isElementAnArray = isArray(element);
|
|
31
|
+
if (Array.isArray(value) !== isElementAnArray) {
|
|
32
|
+
return [
|
|
33
|
+
issueError("structure", `Element is expected to be ${isElementAnArray ? "an array" : "a singular value"}.`, [toJSONPointer(path)]),
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
if (isElementAnArray) {
|
|
37
|
+
if (value.length < min) {
|
|
38
|
+
return [
|
|
39
|
+
issueError("structure", `Element is expected to have at least ${min} items.`, [toJSONPointer(path)]),
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
if (max !== "*" && value > parseInt(max))
|
|
43
|
+
return [
|
|
44
|
+
issueError("structure", `Element is expected to have at most ${max} items.`, [toJSONPointer(path)]),
|
|
45
|
+
];
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
if (min > 0 && value === undefined) {
|
|
50
|
+
return [
|
|
51
|
+
issueError("structure", `Element is expected to have at least ${min} items.`, [toJSONPointer(path)]),
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=cardinality.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cardinality.js","sourceRoot":"","sources":["../../../src/elements/validators/cardinality.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAO,GAAG,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAKrE,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAE9D;;;;GAIG;AACH,SAAS,OAAO,CAAC,OAA0B;IACzC,kGAAkG;IAClG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,GAAG,CAAC;IACtC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC;IAE/B,OAAO,IAAI,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,MAAM,CAAC,iBAAoC;IAClD,OAAO,iBAAiB,CAAC,GAAG,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,MAAM,CAAC,iBAAoC;IAClD,OAAO,iBAAiB,CAAC,GAAG,IAAI,GAAG,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAA0B,EAC1B,IAAY,EACZ,IAAwB;IAExB,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAE9B,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAE5B,yDAAyD;IACzD,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAChD,MAAM,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE1C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,gBAAgB,EAAE,CAAC;QAC9C,OAAO;YACL,UAAU,CACR,WAAW,EACX,6BACE,gBAAgB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,kBAClC,GAAG,EACH,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CACtB;SACF,CAAC;IACJ,CAAC;IACD,IAAI,gBAAgB,EAAE,CAAC;QACrB,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACvB,OAAO;gBACL,UAAU,CACR,WAAW,EACX,wCAAwC,GAAG,SAAS,EACpD,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CACtB;aACF,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,KAAK,GAAG,IAAI,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC;YACtC,OAAO;gBACL,UAAU,CACR,WAAW,EACX,uCAAuC,GAAG,SAAS,EACnD,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CACtB;aACF,CAAC;QAEJ,OAAO,EAAE,CAAC;IACZ,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACnC,OAAO;gBACL,UAAU,CACR,WAAW,EACX,wCAAwC,GAAG,SAAS,EACpD,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CACtB;aACF,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Loc } from "@haste-health/fhir-pointer";
|
|
2
|
+
import { ElementDefinition, OperationOutcomeIssue } from "@haste-health/fhir-types/r4/types";
|
|
3
|
+
export declare function conformsToValue(expectedValue: unknown, foundValue: unknown): boolean;
|
|
4
|
+
export declare function validateFixedValue(element: ElementDefinition, root: unknown, path: Loc<any, any, any>): Promise<Array<OperationOutcomeIssue>>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { get, toJSONPointer } from "@haste-health/fhir-pointer";
|
|
3
|
+
import * as fp from "@haste-health/fhirpath";
|
|
4
|
+
import { issueError } from "@haste-health/operation-outcomes";
|
|
5
|
+
export function conformsToValue(expectedValue, foundValue) {
|
|
6
|
+
return JSON.stringify(expectedValue) === JSON.stringify(foundValue);
|
|
7
|
+
}
|
|
8
|
+
export async function validateFixedValue(element, root, path) {
|
|
9
|
+
const expectedValue = (await fp.evaluate("value", element, { type: "ElementDefinition" }))[0];
|
|
10
|
+
const value = get(path, root);
|
|
11
|
+
if (!expectedValue)
|
|
12
|
+
return [];
|
|
13
|
+
if (!conformsToValue(expectedValue, value)) {
|
|
14
|
+
return [
|
|
15
|
+
issueError("structure", `Value does not conform to fixed value ${JSON.stringify(expectedValue)}.`, [toJSONPointer(path)]),
|
|
16
|
+
];
|
|
17
|
+
}
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=fixedValue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixedValue.js","sourceRoot":"","sources":["../../../src/elements/validators/fixedValue.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAO,GAAG,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAMrE,OAAO,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAE9D,MAAM,UAAU,eAAe,CAC7B,aAAsB,EACtB,UAAmB;IAEnB,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAA0B,EAC1B,IAAa,EACb,IAAwB;IAExB,MAAM,aAAa,GAAG,CACpB,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,mBAA0B,EAAE,CAAC,CAC1E,CAAC,CAAC,CAAC,CAAC;IAEL,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAE9B,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,UAAU,CACR,WAAW,EACX,yCAAyC,IAAI,CAAC,SAAS,CACrD,aAAa,CACd,GAAG,EACJ,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CACtB;SACF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Loc } from "@haste-health/fhir-pointer";
|
|
2
|
+
import { ElementDefinition, OperationOutcomeIssue } from "@haste-health/fhir-types/r4/types";
|
|
3
|
+
/**
|
|
4
|
+
* If primitive: it must match exactly the pattern value
|
|
5
|
+
* If a complex object: it must match (recursively) the pattern value
|
|
6
|
+
* If an array: it must match (recursively) the pattern value.
|
|
7
|
+
* @param pattern
|
|
8
|
+
* @param value
|
|
9
|
+
*/
|
|
10
|
+
export declare function conformsToPattern(pattern: unknown, value: unknown): boolean;
|
|
11
|
+
export declare function validatePattern(element: ElementDefinition, root: unknown, path: Loc<any, any, any>): Promise<Array<OperationOutcomeIssue>>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { get, toJSONPointer } from "@haste-health/fhir-pointer";
|
|
3
|
+
import * as fp from "@haste-health/fhirpath";
|
|
4
|
+
import { isObject } from "@haste-health/meta-value/utilities";
|
|
5
|
+
import { issueError } from "@haste-health/operation-outcomes";
|
|
6
|
+
/**
|
|
7
|
+
* If primitive: it must match exactly the pattern value
|
|
8
|
+
* If a complex object: it must match (recursively) the pattern value
|
|
9
|
+
* If an array: it must match (recursively) the pattern value.
|
|
10
|
+
* @param pattern
|
|
11
|
+
* @param value
|
|
12
|
+
*/
|
|
13
|
+
export function conformsToPattern(pattern, value) {
|
|
14
|
+
if (isObject(pattern)) {
|
|
15
|
+
if (!isObject(value))
|
|
16
|
+
return false;
|
|
17
|
+
if (Array.isArray(pattern)) {
|
|
18
|
+
if (!Array.isArray(value))
|
|
19
|
+
return false;
|
|
20
|
+
for (const singularPattern of pattern) {
|
|
21
|
+
const valueExists = value.filter((v) => conformsToPattern(singularPattern, v));
|
|
22
|
+
// Per spec as long as a single value matches in the pattern then it's truthy
|
|
23
|
+
if (valueExists.length === 0)
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
const patternKeys = Object.keys(pattern);
|
|
30
|
+
for (const key of patternKeys) {
|
|
31
|
+
if (!conformsToPattern(pattern[key], value[key]))
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return pattern === value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export async function validatePattern(element, root, path) {
|
|
42
|
+
const pattern = (await fp.evaluate("pattern", element, { type: "ElementDefinition" }))[0];
|
|
43
|
+
const value = get(path, root);
|
|
44
|
+
if (!pattern)
|
|
45
|
+
return [];
|
|
46
|
+
if (!conformsToPattern(pattern, value)) {
|
|
47
|
+
return [
|
|
48
|
+
issueError("structure", `Value does not conform to pattern ${JSON.stringify(pattern)}.`, [toJSONPointer(path)]),
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=pattern.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern.js","sourceRoot":"","sources":["../../../src/elements/validators/pattern.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAO,GAAG,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAMrE,OAAO,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgB,EAAE,KAAc;IAChE,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACnC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;YACxC,KAAK,MAAM,eAAe,IAAI,OAAO,EAAE,CAAC;gBACtC,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACrC,iBAAiB,CAAC,eAAe,EAAE,CAAC,CAAC,CACtC,CAAC;gBACF,6EAA6E;gBAC7E,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO,KAAK,CAAC;YAC7C,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;aAAM,CAAC;YACN,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzC,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;gBAC9B,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;oBAAE,OAAO,KAAK,CAAC;YACjE,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,OAAO,KAAK,KAAK,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA0B,EAC1B,IAAa,EACb,IAAwB;IAExB,MAAM,OAAO,GAAG,CACd,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,mBAA0B,EAAE,CAAC,CAC5E,CAAC,CAAC,CAAC,CAAC;IACL,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO;YACL,UAAU,CACR,WAAW,EACX,qCAAqC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,EAC/D,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CACtB;SACF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Loc } from "@oxidized-health/fhir-pointer";
|
|
2
|
+
import {
|
|
3
|
+
ElementDefinition,
|
|
4
|
+
OperationOutcomeIssue,
|
|
5
|
+
} from "@oxidized-health/fhir-types/r4/types";
|
|
6
|
+
export declare function validateValue(
|
|
7
|
+
element: ElementDefinition,
|
|
8
|
+
root: object,
|
|
9
|
+
path: Loc<any, any, any>
|
|
10
|
+
): Promise<Array<OperationOutcomeIssue>>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { get, toJSONPointer } from "@iguhealth/fhir-pointer";
|
|
3
|
+
import * as fp from "@iguhealth/fhirpath";
|
|
4
|
+
import { issueError } from "@iguhealth/operation-outcomes";
|
|
5
|
+
import { conformsToValue } from "../conformance.js";
|
|
6
|
+
export async function validateValue(element, root, path) {
|
|
7
|
+
const expectedValue = (await fp.evaluate("value", element, { type: "ElementDefinition" }))[0];
|
|
8
|
+
const value = get(path, root);
|
|
9
|
+
if (!expectedValue)
|
|
10
|
+
return [];
|
|
11
|
+
if (!conformsToValue(expectedValue, value)) {
|
|
12
|
+
return [
|
|
13
|
+
issueError("structure", `Value does not conform to fixed value ${JSON.stringify(expectedValue)}.`, [toJSONPointer(path)]),
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"value.js","sourceRoot":"","sources":["../../../src/elements/validators/value.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAO,GAAG,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAMlE,OAAO,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAA0B,EAC1B,IAAY,EACZ,IAAwB;IAExB,MAAM,aAAa,GAAG,CACpB,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,mBAA0B,EAAE,CAAC,CAC1E,CAAC,CAAC,CAAC,CAAC;IAEL,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAE9B,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,UAAU,CACR,WAAW,EACX,yCAAyC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,EACzE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CACtB;SACF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If primitive: it must match exactly the pattern value
|
|
3
|
+
* If a complex object: it must match (recursively) the pattern value
|
|
4
|
+
* If an array: it must match (recursively) the pattern value.
|
|
5
|
+
* @param pattern
|
|
6
|
+
* @param value
|
|
7
|
+
*/
|
|
8
|
+
export declare function conformsToPattern(pattern: unknown, value: unknown): boolean;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isObject } from "@iguhealth/meta-value/utilities";
|
|
2
|
+
/**
|
|
3
|
+
* If primitive: it must match exactly the pattern value
|
|
4
|
+
* If a complex object: it must match (recursively) the pattern value
|
|
5
|
+
* If an array: it must match (recursively) the pattern value.
|
|
6
|
+
* @param pattern
|
|
7
|
+
* @param value
|
|
8
|
+
*/
|
|
9
|
+
export function conformsToPattern(pattern, value) {
|
|
10
|
+
if (isObject(pattern)) {
|
|
11
|
+
if (!isObject(value))
|
|
12
|
+
return false;
|
|
13
|
+
if (Array.isArray(pattern)) {
|
|
14
|
+
if (!Array.isArray(value))
|
|
15
|
+
return false;
|
|
16
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
17
|
+
const valueExists = value.filter((v) => conformsToPattern(pattern[i], v));
|
|
18
|
+
// Per spec as long as a single value matches in the pattern then it's truthy
|
|
19
|
+
if (valueExists.length === 0)
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
const patternKeys = Object.keys(pattern);
|
|
26
|
+
for (const key of patternKeys) {
|
|
27
|
+
if (!conformsToPattern(pattern[key], value[key]))
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return pattern === value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/elements/validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAE3D;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgB,EAAE,KAAc;IAChE,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACnC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;YACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACrC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CACjC,CAAC;gBACF,6EAA6E;gBAC7E,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO,KAAK,CAAC;YAC7C,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;aAAM,CAAC;YACN,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzC,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;gBAC9B,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;oBAAE,OAAO,KAAK,CAAC;YACjE,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,OAAO,KAAK,KAAK,CAAC;IAC3B,CAAC;AACH,CAAC"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Loc } from "@haste-health/fhir-pointer";
|
|
2
|
+
import { OperationOutcomeIssue, uri } from "@haste-health/fhir-types/lib/generated/r4/types";
|
|
3
|
+
import { ValidationCTX } from "./types.js";
|
|
4
|
+
export default function validate(ctx: ValidationCTX, type: uri, root: unknown, path_?: Loc<any, any, any>): Promise<OperationOutcomeIssue[]>;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { isObject } from "@haste-health/meta-value/utilities";
|
|
3
|
+
import validateResourceProfiles from "./profile/index.js";
|
|
4
|
+
import structuralValidation from "./structural/index.js";
|
|
5
|
+
export default async function validate(ctx, type, root, path_) {
|
|
6
|
+
let issues = await structuralValidation(ctx, type, root, path_);
|
|
7
|
+
if (isObject(root) && "resourceType" in root) {
|
|
8
|
+
const profileIssues = await validateResourceProfiles(ctx, root, path_);
|
|
9
|
+
issues = issues.concat(profileIssues);
|
|
10
|
+
}
|
|
11
|
+
return issues;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAYvD,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAE9D,OAAO,wBAAwB,MAAM,oBAAoB,CAAC;AAC1D,OAAO,oBAAoB,MAAM,uBAAuB,CAAC;AAGzD,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,QAAQ,CACpC,GAAkB,EAClB,IAAS,EACT,IAAa,EACb,KAA0B;IAE1B,IAAI,MAAM,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAEhE,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;QAC7C,MAAM,aAAa,GAAG,MAAM,wBAAwB,CAClD,GAAG,EACH,IAA2D,EAC3D,KAAK,CACN,CAAC;QACF,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Loc } from "@haste-health/fhir-pointer";
|
|
2
|
+
import { OperationOutcomeIssue, uri } from "@haste-health/fhir-types/r4/types";
|
|
3
|
+
import { FHIR_VERSION, Resource } from "@haste-health/fhir-types/versions";
|
|
4
|
+
import { ElementLoc, ValidationCTX } from "../types.js";
|
|
5
|
+
export declare function validateSingularProfileElement(ctx: ValidationCTX, profile: Resource<FHIR_VERSION, "StructureDefinition">, elementLoc: ElementLoc, root: object, path: Loc<any, any, any>, type: uri): Promise<OperationOutcomeIssue[]>;
|
|
6
|
+
/**
|
|
7
|
+
* Because profile is merely a constraint on the base we only need to validate select pieces.
|
|
8
|
+
*
|
|
9
|
+
* [ALLOWED]:
|
|
10
|
+
* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
11
|
+
* Restricting the cardinality of the element; e.g. the base might allow 0..*, and a particular application might support 1..2
|
|
12
|
+
* Ruling out use of an element by setting its maximum cardinality to 0
|
|
13
|
+
* Restricting the contents of an element to a single fixed value
|
|
14
|
+
* Making additional constraints on the content of nested elements within the resource (expressed as FHIRPath statements)
|
|
15
|
+
* Restricting the types for an element that allows multiple types
|
|
16
|
+
* Requiring a typed element or the target of a resource reference to conform to another structure profile (declared in the same profile, or elsewhere)
|
|
17
|
+
* Specifying a binding to a different terminology value set (see below)
|
|
18
|
+
* Providing refined definitions, comments/usage notes and examples for the elements defined in a Resource to reflect the usage of the element within the context of the Profile
|
|
19
|
+
* Providing more specific or additional mappings (e.g. to HL7 V2 icon or HL7 v3 icon) for the resource when used in a particular context
|
|
20
|
+
* Declaring that one or more elements in the structure must be 'supported' (see below)
|
|
21
|
+
* Restricting / clarifying a mapping by providing a new mapping with the same identity, which means that the new mapping replaces a mapping with the same identity in the element being profiled
|
|
22
|
+
* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
23
|
+
*
|
|
24
|
+
* [DISSALLOWED]:
|
|
25
|
+
* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
26
|
+
* Profiles cannot break the rules established in the base specification (e.g. cardinality as described above)
|
|
27
|
+
* Profiles cannot specify default values or meanings for elements defined in the base specification (note that datatypes and resources do not
|
|
28
|
+
* define default values at all, but default values may be defined for logical models
|
|
29
|
+
* Profiles cannot change the name of elements defined in the base specification, or add new elements
|
|
30
|
+
* It must be safe to process a resource without knowing the profile
|
|
31
|
+
* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
32
|
+
* @param ctx Validation CTX
|
|
33
|
+
* @param profile Profile SD
|
|
34
|
+
* @param elementLoc Current ElementDefinition validating
|
|
35
|
+
* @param root Root value to be validated
|
|
36
|
+
* @param path Path inside of value to validate
|
|
37
|
+
* @param type
|
|
38
|
+
* @returns
|
|
39
|
+
*/
|
|
40
|
+
export declare function validateProfileElement(ctx: ValidationCTX, profile: Resource<FHIR_VERSION, "StructureDefinition">, elementLoc: ElementLoc, root: object, path: Loc<any, any, any>, type: uri): Promise<OperationOutcomeIssue[]>;
|