@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
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { eleIndexToChildIndices } from "@haste-health/codegen/traversal/structure-definition";
|
|
3
|
+
import { descend, get, toJSONPointer } from "@haste-health/fhir-pointer";
|
|
4
|
+
import { isPrimitiveType } from "@haste-health/meta-value/utilities";
|
|
5
|
+
import { OperationError, issueError, outcomeFatal, } from "@haste-health/operation-outcomes";
|
|
6
|
+
import { validatePrimitive } from "../elements/primitive.js";
|
|
7
|
+
import { validateCardinality } from "../elements/validators/cardinality.js";
|
|
8
|
+
import { validateFixedValue } from "../elements/validators/fixedValue.js";
|
|
9
|
+
import { validatePattern } from "../elements/validators/pattern.js";
|
|
10
|
+
import { ascendElementLoc, getFoundFieldsForElement, isElementRequired, } from "../utilities.js";
|
|
11
|
+
import { validateProfileCanonical } from "./index.js";
|
|
12
|
+
import { getSliceIndices, validateSliceDescriptor } from "./slicing/index.js";
|
|
13
|
+
/**
|
|
14
|
+
* For descendants we want to ignore those slices which are validated seperately.
|
|
15
|
+
* This is done by filtering off sliceName and slicing property.
|
|
16
|
+
*
|
|
17
|
+
* @param elements list of ElementDefinitions to filter
|
|
18
|
+
* @param indices The indices to filter out of the list if they are a part of a lice.
|
|
19
|
+
* @returns Indices that are not a part of a slice.
|
|
20
|
+
*/
|
|
21
|
+
function ignoreSliceElements(elements, indices) {
|
|
22
|
+
return indices.filter((index) => {
|
|
23
|
+
const element = elements[index];
|
|
24
|
+
return element.sliceName === undefined && element.slicing === undefined;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if the element is constrained to profiles type.
|
|
29
|
+
* @param element ElementDefinition to check
|
|
30
|
+
* @param type The type found on the element.
|
|
31
|
+
* @returns true|false as to whether the element is constrained to the type.
|
|
32
|
+
*/
|
|
33
|
+
function validateTypeIfMultipleTypesConstrained(ctx, element, type) {
|
|
34
|
+
if (element.type) {
|
|
35
|
+
if (element.type.find((t) => t.code === type) !== undefined) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
else if (type === "Element" &&
|
|
39
|
+
element.type.find((t) => isPrimitiveType(ctx.fhirVersion, t.code))) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
export async function validateSingularProfileElement(ctx, profile, elementLoc, root, path, type) {
|
|
47
|
+
const { parent: elementsLoc, field: elementIndex } = ascendElementLoc(elementLoc);
|
|
48
|
+
const elements = get(elementsLoc, profile);
|
|
49
|
+
const element = get(elementLoc, profile);
|
|
50
|
+
if (!element) {
|
|
51
|
+
throw new OperationError(outcomeFatal("not-found", `Unable to resolve element at location '${toJSONPointer(elementLoc)}'`, [toJSONPointer(path)]));
|
|
52
|
+
}
|
|
53
|
+
const value = get(path, root);
|
|
54
|
+
const foundFields = profile.kind === "resource" && elementIndex === 0
|
|
55
|
+
? new Set(["resourceType"])
|
|
56
|
+
: new Set([]);
|
|
57
|
+
// Slice Validation
|
|
58
|
+
const sliceIndices = getSliceIndices(profile, elementLoc);
|
|
59
|
+
const sliceIssues = (await Promise.all(sliceIndices.map((sliceIndex) => validateSliceDescriptor(ctx, profile, sliceIndex, root, path)))).flat();
|
|
60
|
+
sliceIndices.forEach((sliceIndex) => {
|
|
61
|
+
const discriminatorElement = elements[sliceIndex.discriminator];
|
|
62
|
+
const fields = getFoundFieldsForElement(ctx, discriminatorElement, value);
|
|
63
|
+
fields.forEach((f) => foundFields.add(f.field));
|
|
64
|
+
});
|
|
65
|
+
if (sliceIssues.length > 0) {
|
|
66
|
+
return sliceIssues;
|
|
67
|
+
}
|
|
68
|
+
// [END] Slice Validation
|
|
69
|
+
const children = ignoreSliceElements(elements, eleIndexToChildIndices(elements, elementIndex));
|
|
70
|
+
const profileUrlsToValidate = element.type?.find((t) => t.code === type)?.profile ?? [];
|
|
71
|
+
for (let i = 0; i < profileUrlsToValidate.length; i++) {
|
|
72
|
+
const profileIssues = await validateProfileCanonical(ctx, profileUrlsToValidate[i], root, path);
|
|
73
|
+
// Only need one profile to be conformant so continue if invalid and break if valid.
|
|
74
|
+
if (profileIssues.length === 0)
|
|
75
|
+
break;
|
|
76
|
+
else if (i === profileUrlsToValidate.length - 1) {
|
|
77
|
+
return profileIssues;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Profile can further constrain typechoices check that here.
|
|
81
|
+
if (!validateTypeIfMultipleTypesConstrained(ctx, element, type)) {
|
|
82
|
+
throw new OperationError(outcomeFatal("invalid", `Valid types: '${element.type
|
|
83
|
+
?.map((t) => t.code)
|
|
84
|
+
.join(",")}' is not constrained to type '${type}'`, [toJSONPointer(path)]));
|
|
85
|
+
}
|
|
86
|
+
const patternIssues = await validatePattern(element, root, path);
|
|
87
|
+
if (patternIssues.length > 0) {
|
|
88
|
+
return patternIssues;
|
|
89
|
+
}
|
|
90
|
+
const fixedValueIssues = await validateFixedValue(element, root, path);
|
|
91
|
+
if (fixedValueIssues.length > 0) {
|
|
92
|
+
return fixedValueIssues;
|
|
93
|
+
}
|
|
94
|
+
let issues = [];
|
|
95
|
+
if (children.length > 0) {
|
|
96
|
+
for (const childIndex of children) {
|
|
97
|
+
const childElement = elements[childIndex];
|
|
98
|
+
const childElementLoc = descend(elementsLoc, childIndex);
|
|
99
|
+
const fields = getFoundFieldsForElement(ctx, childElement, value);
|
|
100
|
+
fields.forEach((f) => foundFields.add(f.field));
|
|
101
|
+
// Confirm if no fields are found and the element is required then issue an error.
|
|
102
|
+
if (isElementRequired(childElement) && fields.length === 0) {
|
|
103
|
+
issues = issues.concat([
|
|
104
|
+
issueError("structure", `Missing required field '${childElement.path}' at path '${toJSONPointer(path)}'`, [toJSONPointer(path)]),
|
|
105
|
+
]);
|
|
106
|
+
}
|
|
107
|
+
for (const field of fields) {
|
|
108
|
+
const childValueLoc = descend(path, field.field);
|
|
109
|
+
issues = issues.concat(await validateProfileElement(ctx, profile, childElementLoc, root, childValueLoc, field.type));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const additionalFields = new Set(Object.keys(value)).difference(foundFields);
|
|
113
|
+
if (additionalFields.size > 0) {
|
|
114
|
+
issues = issues.concat([
|
|
115
|
+
issueError("structure", `Additional fields found at path '${toJSONPointer(path)}': '${Array.from(additionalFields).join(", ")}'`, [toJSONPointer(path)]),
|
|
116
|
+
]);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else if (type === "code") {
|
|
120
|
+
issues = issues.concat(await validatePrimitive(ctx, element, root, path, type));
|
|
121
|
+
}
|
|
122
|
+
return issues;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Because profile is merely a constraint on the base we only need to validate select pieces.
|
|
126
|
+
*
|
|
127
|
+
* [ALLOWED]:
|
|
128
|
+
* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
129
|
+
* Restricting the cardinality of the element; e.g. the base might allow 0..*, and a particular application might support 1..2
|
|
130
|
+
* Ruling out use of an element by setting its maximum cardinality to 0
|
|
131
|
+
* Restricting the contents of an element to a single fixed value
|
|
132
|
+
* Making additional constraints on the content of nested elements within the resource (expressed as FHIRPath statements)
|
|
133
|
+
* Restricting the types for an element that allows multiple types
|
|
134
|
+
* Requiring a typed element or the target of a resource reference to conform to another structure profile (declared in the same profile, or elsewhere)
|
|
135
|
+
* Specifying a binding to a different terminology value set (see below)
|
|
136
|
+
* 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
|
|
137
|
+
* 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
|
|
138
|
+
* Declaring that one or more elements in the structure must be 'supported' (see below)
|
|
139
|
+
* 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
|
|
140
|
+
* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
141
|
+
*
|
|
142
|
+
* [DISSALLOWED]:
|
|
143
|
+
* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
144
|
+
* Profiles cannot break the rules established in the base specification (e.g. cardinality as described above)
|
|
145
|
+
* Profiles cannot specify default values or meanings for elements defined in the base specification (note that datatypes and resources do not
|
|
146
|
+
* define default values at all, but default values may be defined for logical models
|
|
147
|
+
* Profiles cannot change the name of elements defined in the base specification, or add new elements
|
|
148
|
+
* It must be safe to process a resource without knowing the profile
|
|
149
|
+
* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
150
|
+
* @param ctx Validation CTX
|
|
151
|
+
* @param profile Profile SD
|
|
152
|
+
* @param elementLoc Current ElementDefinition validating
|
|
153
|
+
* @param root Root value to be validated
|
|
154
|
+
* @param path Path inside of value to validate
|
|
155
|
+
* @param type
|
|
156
|
+
* @returns
|
|
157
|
+
*/
|
|
158
|
+
export async function validateProfileElement(ctx, profile, elementLoc, root, path, type) {
|
|
159
|
+
const value = get(path, root);
|
|
160
|
+
const element = get(elementLoc, profile);
|
|
161
|
+
if (!element) {
|
|
162
|
+
throw new OperationError(outcomeFatal("not-found", `Unable to resolve element at location '${toJSONPointer(elementLoc)}'`, [toJSONPointer(path)]));
|
|
163
|
+
}
|
|
164
|
+
// [Slicing Validation]
|
|
165
|
+
let issues = [];
|
|
166
|
+
// [Cardinality validation]
|
|
167
|
+
issues = issues.concat(validateCardinality(element, root, path));
|
|
168
|
+
switch (true) {
|
|
169
|
+
case Array.isArray(value): {
|
|
170
|
+
issues = issues.concat((await Promise.all(value.map((_v, index) => validateSingularProfileElement(ctx, profile, elementLoc, root, descend(path, index), type)))).flat());
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
default: {
|
|
174
|
+
issues = issues.concat(await validateSingularProfileElement(ctx, profile, elementLoc, root, path, type));
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return issues;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=element.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element.js","sourceRoot":"","sources":["../../src/profile/element.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Loc } from "@haste-health/fhir-pointer";
|
|
2
|
+
import { OperationOutcomeIssue, canonical } from "@haste-health/fhir-types/r4/types";
|
|
3
|
+
import { AllResourceTypes, FHIR_VERSION, Resource } from "@haste-health/fhir-types/versions";
|
|
4
|
+
import { ValidationCTX } from "../types.js";
|
|
5
|
+
export declare function validateProfile(ctx: ValidationCTX, profile: Resource<FHIR_VERSION, "StructureDefinition">, root: object, path_?: Loc<any, any, any>): Promise<OperationOutcomeIssue[]>;
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param ctx_ Validation CTX
|
|
9
|
+
* @param profileURL Profile canonical to validate
|
|
10
|
+
* @param value the value to check
|
|
11
|
+
* @param path The current path of the value.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateProfileCanonical(ctx: ValidationCTX, profileURL: canonical, root: object, path_?: Loc<any, any, any>): Promise<OperationOutcomeIssue[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Validates a resources profiles found on meta.profile.
|
|
16
|
+
* @param ctx Validation Context
|
|
17
|
+
* @param resource The resource with profiles to validate
|
|
18
|
+
* @returns Any issues found during profile validation.
|
|
19
|
+
*/
|
|
20
|
+
export default function validateResourceProfiles(ctx: ValidationCTX, resource: Resource<FHIR_VERSION, AllResourceTypes>, path_?: Loc<any, any, any>): Promise<OperationOutcomeIssue[]>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { descend, pointer, toJSONPointer, } from "@haste-health/fhir-pointer";
|
|
3
|
+
import { OperationError, outcomeFatal } from "@haste-health/operation-outcomes";
|
|
4
|
+
import { validateProfileElement } from "./element.js";
|
|
5
|
+
export async function validateProfile(ctx, profile, root, path_) {
|
|
6
|
+
const path = path_ ??
|
|
7
|
+
pointer(ctx.fhirVersion, profile?.type, "id");
|
|
8
|
+
if (profile.derivation !== "constraint") {
|
|
9
|
+
throw new OperationError(outcomeFatal("invalid", `Profile must be a constraint profile, got ${profile.derivation}`, [toJSONPointer(path)]));
|
|
10
|
+
}
|
|
11
|
+
const startingLoc = descend(descend(descend(pointer(ctx.fhirVersion, "StructureDefinition", profile.id), "snapshot"), "element"), 0);
|
|
12
|
+
return validateProfileElement(ctx, profile, startingLoc, root, path, profile.type);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @param ctx_ Validation CTX
|
|
17
|
+
* @param profileURL Profile canonical to validate
|
|
18
|
+
* @param value the value to check
|
|
19
|
+
* @param path The current path of the value.
|
|
20
|
+
*/
|
|
21
|
+
export async function validateProfileCanonical(ctx, profileURL, root, path_) {
|
|
22
|
+
const profile = await ctx.resolveCanonical(ctx.fhirVersion, "StructureDefinition", profileURL);
|
|
23
|
+
const path = path_ ??
|
|
24
|
+
pointer(ctx.fhirVersion, profile?.type, "id");
|
|
25
|
+
// If we can't resolve profile just ignore for now.
|
|
26
|
+
if (!profile) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
const issues = await validateProfile(ctx, profile, root, path);
|
|
30
|
+
return issues;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validates a resources profiles found on meta.profile.
|
|
34
|
+
* @param ctx Validation Context
|
|
35
|
+
* @param resource The resource with profiles to validate
|
|
36
|
+
* @returns Any issues found during profile validation.
|
|
37
|
+
*/
|
|
38
|
+
export default async function validateResourceProfiles(ctx, resource, path_) {
|
|
39
|
+
const profiles = resource.meta?.profile ?? [];
|
|
40
|
+
const path = path_ ??
|
|
41
|
+
pointer(ctx.fhirVersion, resource.resourceType, resource.id ?? "new");
|
|
42
|
+
const issues = (await Promise.all(profiles.map((profile) => validateProfileCanonical(ctx, profile, resource, path)))).flat();
|
|
43
|
+
return issues;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/profile/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAEL,OAAO,EACP,OAAO,EACP,aAAa,GACd,MAAM,4BAA4B,CAAC;AAYpC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAGhF,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAkB,EAClB,OAAsD,EACtD,IAAY,EACZ,KAA0B;IAE1B,MAAM,IAAI,GACR,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,IAAoB,EAAE,IAAU,CAAC,CAAC;IAEtE,IAAI,OAAO,CAAC,UAAU,KAAK,YAAY,EAAE,CAAC;QACxC,MAAM,IAAI,cAAc,CACtB,YAAY,CACV,SAAS,EACT,6CAA6C,OAAO,CAAC,UAAU,EAAE,EACjE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CACtB,CACF,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CACzB,OAAO,CACL,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,qBAAqB,EAAE,OAAO,CAAC,EAAQ,CAAC,EACjE,UAAU,CACX,EACD,SAAS,CACV,EACD,CAAC,CACF,CAAC;IAEF,OAAO,sBAAsB,CAC3B,GAAG,EACH,OAAO,EACP,WAAoC,EACpC,IAAI,EACJ,IAAI,EACJ,OAAO,CAAC,IAAI,CACb,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,GAAkB,EAClB,UAAqB,EACrB,IAAY,EACZ,KAA0B;IAE1B,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,gBAAgB,CACxC,GAAG,CAAC,WAAW,EACf,qBAAqB,EACrB,UAAU,CACX,CAAC;IAEF,MAAM,IAAI,GACR,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,IAAoB,EAAE,IAAU,CAAC,CAAC;IAEtE,mDAAmD;IACnD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAE/D,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,wBAAwB,CACpD,GAAkB,EAClB,QAAkD,EAClD,KAA0B;IAE1B,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC;IAC9C,MAAM,IAAI,GACR,KAAK;QACL,OAAO,CACL,GAAG,CAAC,WAAW,EACf,QAAQ,CAAC,YAAY,EACrB,QAAQ,CAAC,EAAE,IAAK,KAAY,CAC7B,CAAC;IAEJ,MAAM,MAAM,GAAG,CACb,MAAM,OAAO,CAAC,GAAG,CACf,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CACvB,wBAAwB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,CACvD,CACF,CACF,CAAC,IAAI,EAAE,CAAC;IAET,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Loc } from "@haste-health/fhir-pointer";
|
|
2
|
+
import { ElementDefinition, OperationOutcome } 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
|
+
type SlicingDescriptor = {
|
|
6
|
+
discriminator: number;
|
|
7
|
+
slices: number[];
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Filter elements for discriminator slice + slicing elements.
|
|
11
|
+
* @param elements
|
|
12
|
+
*/
|
|
13
|
+
export declare function getSliceIndices(profile: Resource<FHIR_VERSION, "StructureDefinition">, elementLoc: ElementLoc): SlicingDescriptor[];
|
|
14
|
+
export declare function validateSlice(elements: ElementDefinition[], sliceIndex: number, root: object, sliceValueLocs: Loc<any, any, any>[]): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the location for the value to be sliced. Note this could be an array or a singular value (in the case of slicing by type).
|
|
17
|
+
* @param discriminatorElement The element definition that is the discriminator. This defines what method is used for slicing.
|
|
18
|
+
* @param root The value of the root object
|
|
19
|
+
* @param loc Location in the root object of the slice.
|
|
20
|
+
* @returns Location of the value to be sliced against the root.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getSliceLocs(discriminatorElement: ElementDefinition, root: object, loc: Loc<any, any, any>): Loc<any, any, any>[];
|
|
23
|
+
export declare function validateSliceDescriptor(ctx: ValidationCTX, profile: Resource<FHIR_VERSION, "StructureDefinition">, sliceDescriptor: SlicingDescriptor, root: object, loc: Loc<any, any, any>): Promise<OperationOutcome["issue"]>;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { eleIndexToChildIndices } from "@haste-health/codegen/traversal/structure-definition";
|
|
3
|
+
import { descend, get, pathMeta, pointer, toFHIRPath, toJSONPointer, } from "@haste-health/fhir-pointer";
|
|
4
|
+
import { R4 } from "@haste-health/fhir-types/versions";
|
|
5
|
+
import * as fp from "@haste-health/fhirpath";
|
|
6
|
+
import { metaValue } from "@haste-health/meta-value/v2";
|
|
7
|
+
import { OperationError, issueError, outcomeError, } from "@haste-health/operation-outcomes";
|
|
8
|
+
import { conformsToValue } from "../../elements/validators/fixedValue.js";
|
|
9
|
+
import { conformsToPattern } from "../../elements/validators/pattern.js";
|
|
10
|
+
import { ascendElementLoc, fieldName, isTypeChoice } from "../../utilities.js";
|
|
11
|
+
import { validateSingularProfileElement } from "../element.js";
|
|
12
|
+
import { convertPathToElementPointer, joinPaths, removeTypeOnPath, } from "../utilities.js";
|
|
13
|
+
function isSliced(element) {
|
|
14
|
+
return element.slicing !== undefined;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Filter elements for discriminator slice + slicing elements.
|
|
18
|
+
* @param elements
|
|
19
|
+
*/
|
|
20
|
+
export function getSliceIndices(profile, elementLoc) {
|
|
21
|
+
const { parent: elementsLoc, field: index } = ascendElementLoc(elementLoc);
|
|
22
|
+
const elements = get(elementsLoc, profile);
|
|
23
|
+
const children = eleIndexToChildIndices(elements, index);
|
|
24
|
+
const slices = [];
|
|
25
|
+
let i = 0;
|
|
26
|
+
while (i < children.length) {
|
|
27
|
+
const childIndex = children[i++];
|
|
28
|
+
if (isSliced(elements[childIndex])) {
|
|
29
|
+
const discriminatorIndex = childIndex;
|
|
30
|
+
const sliceIndexes = [];
|
|
31
|
+
while (i < children.length && elements[children[i]].sliceName) {
|
|
32
|
+
sliceIndexes.push(children[i]);
|
|
33
|
+
i++;
|
|
34
|
+
}
|
|
35
|
+
slices.push({
|
|
36
|
+
discriminator: discriminatorIndex,
|
|
37
|
+
slices: sliceIndexes,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return slices;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Returns the elementDefinition associated with the given discriminator. This is used to extract the value the slice is expecting.
|
|
45
|
+
* @param discriminator The discriminator to use to distinguish slices.
|
|
46
|
+
* @param elements The elements to search for the slice value.
|
|
47
|
+
* @param currentIndex The current index to search for the slice value.
|
|
48
|
+
* @returns The index of elementdefinition to use to slice the value for the discriminator.
|
|
49
|
+
*/
|
|
50
|
+
async function findElementDefinitionForSliceDiscriminator(ctx, searchingForElementPath, elements, currentIndex, parentCurrentElementPath = undefined) {
|
|
51
|
+
const element = elements[currentIndex];
|
|
52
|
+
const currentElementPath = parentCurrentElementPath
|
|
53
|
+
? joinPaths(parentCurrentElementPath, removeTypeOnPath(element.path))
|
|
54
|
+
: removeTypeOnPath(element.path);
|
|
55
|
+
if (searchingForElementPath === currentElementPath) {
|
|
56
|
+
return element;
|
|
57
|
+
}
|
|
58
|
+
// No need for further processing if the discriminator path is not a prefix of the current element path.
|
|
59
|
+
if (searchingForElementPath.startsWith(currentElementPath)) {
|
|
60
|
+
const profiles = element.type
|
|
61
|
+
?.map((t) => t.profile)
|
|
62
|
+
.flat()
|
|
63
|
+
.filter((t) => t !== undefined);
|
|
64
|
+
if (profiles) {
|
|
65
|
+
for (const profile of profiles) {
|
|
66
|
+
const profileSD = await ctx.resolveCanonical(ctx.fhirVersion, "StructureDefinition", profile);
|
|
67
|
+
if (!profileSD) {
|
|
68
|
+
throw new OperationError(outcomeError("not-found", `Could not resolve profile '${profile}'`));
|
|
69
|
+
}
|
|
70
|
+
const elementInProfile = await findElementDefinitionForSliceDiscriminator(ctx, searchingForElementPath, profileSD.snapshot?.element ?? [], 0,
|
|
71
|
+
// Use current element path as parent path.
|
|
72
|
+
currentElementPath);
|
|
73
|
+
if (elementInProfile !== undefined)
|
|
74
|
+
return elementInProfile;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const childIndexes = eleIndexToChildIndices(elements, currentIndex);
|
|
78
|
+
for (const childIndex of childIndexes) {
|
|
79
|
+
const elementDefinitionForSliceDiscriminator = await findElementDefinitionForSliceDiscriminator(ctx, searchingForElementPath, elements, childIndex, parentCurrentElementPath);
|
|
80
|
+
if (elementDefinitionForSliceDiscriminator !== undefined) {
|
|
81
|
+
return elementDefinitionForSliceDiscriminator;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
async function isConformantToSlicesDiscriminator(discriminator, sliceValueElementDefinition, root, locs) {
|
|
88
|
+
switch (discriminator.type) {
|
|
89
|
+
case "value": {
|
|
90
|
+
const expectedValue = (await fp.evaluate("$this.fixed", sliceValueElementDefinition, {
|
|
91
|
+
type: "ElementDefinition",
|
|
92
|
+
}))[0];
|
|
93
|
+
const conformantLocs = [];
|
|
94
|
+
for (const loc of locs) {
|
|
95
|
+
const value = get(loc, root);
|
|
96
|
+
const evaluation = await fp.evaluate(discriminator.path, value);
|
|
97
|
+
if (evaluation.find((v) => conformsToValue(expectedValue, v)) !==
|
|
98
|
+
undefined) {
|
|
99
|
+
conformantLocs.push(loc);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return conformantLocs;
|
|
103
|
+
}
|
|
104
|
+
case "exists":
|
|
105
|
+
case "pattern": {
|
|
106
|
+
const pattern = (await fp.evaluate("$this.pattern", metaValue({ type: "ElementDefinition", fhirVersion: R4 }, sliceValueElementDefinition)))[0];
|
|
107
|
+
if (!pattern) {
|
|
108
|
+
throw new OperationError(outcomeError("not-found", "Could not find a pattern for slice."));
|
|
109
|
+
}
|
|
110
|
+
const conformantLocs = [];
|
|
111
|
+
for (const loc of locs) {
|
|
112
|
+
const value = get(loc, root);
|
|
113
|
+
const evaluation = await fp.evaluate(discriminator.path, value);
|
|
114
|
+
if (evaluation.find((v) => conformsToPattern(pattern, v))) {
|
|
115
|
+
conformantLocs.push(loc);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return conformantLocs;
|
|
119
|
+
}
|
|
120
|
+
case "type": {
|
|
121
|
+
const expectedTypes = sliceValueElementDefinition.type?.map((t) => t.code) ?? [];
|
|
122
|
+
const conformantLocs = [];
|
|
123
|
+
for (const loc of locs) {
|
|
124
|
+
const meta = pathMeta(loc);
|
|
125
|
+
const value = await fp.evaluateWithMeta(toFHIRPath(loc), root, {
|
|
126
|
+
fhirVersion: meta?.version,
|
|
127
|
+
type: meta?.type,
|
|
128
|
+
});
|
|
129
|
+
// Map over to use the metavaluesingular.
|
|
130
|
+
const evaluation = (await Promise.all(value.map((v) => fp.evaluateWithMeta(discriminator.path, v)))).flat();
|
|
131
|
+
const type = evaluation?.[0]?.meta()?.type;
|
|
132
|
+
if (type && expectedTypes.includes(type)) {
|
|
133
|
+
conformantLocs.push(loc);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return conformantLocs;
|
|
137
|
+
}
|
|
138
|
+
case "profile": {
|
|
139
|
+
throw new Error("Not supported");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
throw new Error("invalid");
|
|
143
|
+
}
|
|
144
|
+
export async function validateSlice(elements, sliceIndex, root, sliceValueLocs) {
|
|
145
|
+
for (const sliceValueLoc of sliceValueLocs) {
|
|
146
|
+
const sliceElement = elements[sliceIndex];
|
|
147
|
+
const patternCheck = await fp.evaluate("$this.pattern", sliceElement);
|
|
148
|
+
const sliceValue = get(sliceValueLoc, root);
|
|
149
|
+
const fixedValueCheck = await fp.evaluate("$this.fixed", sliceElement);
|
|
150
|
+
if (patternCheck && !conformsToPattern(patternCheck[0], sliceValue)) {
|
|
151
|
+
throw new OperationError(outcomeError("exception", "pattern mismatch"));
|
|
152
|
+
}
|
|
153
|
+
if (fixedValueCheck) {
|
|
154
|
+
if (JSON.stringify(fixedValueCheck[0]) !== JSON.stringify(sliceValue)) {
|
|
155
|
+
throw new OperationError(outcomeError("exception", "fixed value mismatch"));
|
|
156
|
+
}
|
|
157
|
+
const childrenIndices = eleIndexToChildIndices(elements, sliceIndex);
|
|
158
|
+
for (const child of childrenIndices) {
|
|
159
|
+
const field = fieldName(elements[child]);
|
|
160
|
+
const fieldLoc = descend(sliceValueLoc, field);
|
|
161
|
+
validateSlice(elements, child, root, [fieldLoc]);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
async function splitSlicing(ctx, elements, sliceDescriptor, root, locsToCheck) {
|
|
167
|
+
const sliceSplit = sliceDescriptor.slices.reduce((acc, sliceIndex) => {
|
|
168
|
+
acc[sliceIndex] = [];
|
|
169
|
+
return acc;
|
|
170
|
+
}, {});
|
|
171
|
+
// [Serialized as a group] The entries must be adjacent for a given slice.
|
|
172
|
+
const discriminatorElement = elements[sliceDescriptor.discriminator];
|
|
173
|
+
const discriminators = discriminatorElement.slicing?.discriminator ?? [];
|
|
174
|
+
const discriminatorElementPaths = discriminators.map((d) => convertPathToElementPointer(discriminatorElement, d));
|
|
175
|
+
for (const sliceIndex of sliceDescriptor.slices) {
|
|
176
|
+
let sliceValueLocs = locsToCheck;
|
|
177
|
+
for (let d = 0; d < discriminators.length; d++) {
|
|
178
|
+
const discriminator = discriminators[d];
|
|
179
|
+
const sliceDiscriminatorElementValue = await findElementDefinitionForSliceDiscriminator(ctx, discriminatorElementPaths[d], elements, sliceIndex);
|
|
180
|
+
if (!sliceDiscriminatorElementValue) {
|
|
181
|
+
throw new OperationError(outcomeError("invalid", `Could not find element definition to use for slice discriminator '${discriminatorElementPaths[d]}'.`));
|
|
182
|
+
}
|
|
183
|
+
sliceValueLocs = await isConformantToSlicesDiscriminator(discriminator, sliceDiscriminatorElementValue, root, sliceValueLocs);
|
|
184
|
+
}
|
|
185
|
+
locsToCheck = locsToCheck.filter((l) => !sliceValueLocs.includes(l));
|
|
186
|
+
sliceSplit[sliceIndex] = sliceValueLocs;
|
|
187
|
+
}
|
|
188
|
+
return sliceSplit;
|
|
189
|
+
}
|
|
190
|
+
function validateSliceCardinality(parentLoc, sliceElement, paths) {
|
|
191
|
+
const issues = [];
|
|
192
|
+
if (paths.length < (sliceElement.min ?? 0)) {
|
|
193
|
+
issues.push(issueError("structure", `Slice '${sliceElement.sliceName}' does not have the minimum number of values.`, [toJSONPointer(parentLoc)]));
|
|
194
|
+
}
|
|
195
|
+
if (!isNaN(parseInt(sliceElement.max ?? "1"))) {
|
|
196
|
+
const max = parseInt(sliceElement.max ?? "1");
|
|
197
|
+
if (paths.length > max) {
|
|
198
|
+
issues.push(issueError("structure", `Slice '${sliceElement.sliceName}' has more than the maximum number of values.`, [toJSONPointer(parentLoc)]));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return issues;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Returns the location for the value to be sliced. Note this could be an array or a singular value (in the case of slicing by type).
|
|
205
|
+
* @param discriminatorElement The element definition that is the discriminator. This defines what method is used for slicing.
|
|
206
|
+
* @param root The value of the root object
|
|
207
|
+
* @param loc Location in the root object of the slice.
|
|
208
|
+
* @returns Location of the value to be sliced against the root.
|
|
209
|
+
*/
|
|
210
|
+
export function getSliceLocs(discriminatorElement, root, loc) {
|
|
211
|
+
if (isTypeChoice(discriminatorElement)) {
|
|
212
|
+
return (discriminatorElement.type?.map((t) => descend(loc, fieldName(discriminatorElement, t.code))) ?? []);
|
|
213
|
+
}
|
|
214
|
+
const valueLoc = descend(loc, fieldName(discriminatorElement));
|
|
215
|
+
const value = get(valueLoc, root);
|
|
216
|
+
if (Array.isArray(value)) {
|
|
217
|
+
return value.map((_v, i) => descend(valueLoc, i));
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
return [valueLoc];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
export async function validateSliceDescriptor(ctx, profile, sliceDescriptor, root, loc) {
|
|
224
|
+
const snapshot = profile.snapshot?.element ?? [];
|
|
225
|
+
const discriminatorElement = snapshot[sliceDescriptor.discriminator];
|
|
226
|
+
const sliceValueLocs = getSliceLocs(discriminatorElement, root, loc);
|
|
227
|
+
const slices = await splitSlicing(ctx, snapshot, sliceDescriptor, root, sliceValueLocs);
|
|
228
|
+
let issues = [];
|
|
229
|
+
const snapshotLoc = descend(descend(pointer(ctx.fhirVersion, "StructureDefinition", profile.id), "snapshot"), "element");
|
|
230
|
+
for (const slice of sliceDescriptor.slices) {
|
|
231
|
+
const sliceLoc = descend(snapshotLoc, slice);
|
|
232
|
+
const sliceElement = get(sliceLoc, profile);
|
|
233
|
+
if (!sliceElement) {
|
|
234
|
+
throw new OperationError(outcomeError("not-found", `Slice element not found at '${sliceLoc}'`));
|
|
235
|
+
}
|
|
236
|
+
const type = sliceElement.type ?? [];
|
|
237
|
+
issues = issues.concat(validateSliceCardinality(loc, sliceElement, slices[slice]));
|
|
238
|
+
if (type.length > 1) {
|
|
239
|
+
throw new OperationError(outcomeError("not-supported", "typechoices not supported for slicing."));
|
|
240
|
+
}
|
|
241
|
+
for (const path of slices[slice]) {
|
|
242
|
+
issues = issues.concat(await validateSingularProfileElement(ctx, profile, sliceLoc, root, path, type[0].code));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return issues;
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/profile/slicing/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ElementDefinition,
|
|
3
|
+
OperationOutcome,
|
|
4
|
+
OperationOutcomeIssue,
|
|
5
|
+
} from "@oxidized-health/fhir-types/r4/types";
|
|
6
|
+
import { Loc } from "@oxidized-health/fhir-pointer";
|
|
7
|
+
import { FHIR_VERSION, Resource } from "@oxidized-health/fhir-types/versions";
|
|
8
|
+
import { ValidationCTX } from "../types.js";
|
|
9
|
+
type SlicingDescriptor = {
|
|
10
|
+
discriminator: number;
|
|
11
|
+
slices: number[];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Filter elements for discriminator slice + slicing elements.
|
|
15
|
+
* @param elements
|
|
16
|
+
*/
|
|
17
|
+
export declare function getSliceIndices(
|
|
18
|
+
elements: ElementDefinition[],
|
|
19
|
+
index: number
|
|
20
|
+
): SlicingDescriptor[];
|
|
21
|
+
export declare function validateSlice(
|
|
22
|
+
elements: ElementDefinition[],
|
|
23
|
+
sliceIndex: number,
|
|
24
|
+
root: object,
|
|
25
|
+
sliceValueLocs: Loc<any, any, any>[]
|
|
26
|
+
): Promise<void>;
|
|
27
|
+
export declare function splitSlicing(
|
|
28
|
+
elements: ElementDefinition[],
|
|
29
|
+
sliceDescriptor: SlicingDescriptor,
|
|
30
|
+
root: object,
|
|
31
|
+
loc: Loc<any, any, any>
|
|
32
|
+
): Promise<Record<number, Loc<any, any, any>[]>>;
|
|
33
|
+
export declare function validateSliceDescriptor(
|
|
34
|
+
ctx: ValidationCTX,
|
|
35
|
+
profile: Resource<FHIR_VERSION, "StructureDefinition">,
|
|
36
|
+
sliceDescriptor: SlicingDescriptor,
|
|
37
|
+
root: object,
|
|
38
|
+
loc: Loc<any, any, any>
|
|
39
|
+
): Promise<OperationOutcome["issue"]>;
|
|
40
|
+
export default function validateAllSlicesAtLocation(
|
|
41
|
+
ctx: ValidationCTX,
|
|
42
|
+
profile: Resource<FHIR_VERSION, "StructureDefinition">,
|
|
43
|
+
elementIndex: number,
|
|
44
|
+
root: object,
|
|
45
|
+
loc: Loc<any, any, any>
|
|
46
|
+
): Promise<OperationOutcomeIssue[]>;
|
|
47
|
+
export {};
|