componentsjs 4.5.0 → 5.0.0-beta.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/CHANGELOG.md +261 -0
- package/README.md +16 -0
- package/components/context.jsonld +87 -2
- package/lib/ComponentsManager.js +3 -5
- package/lib/construction/ConfigConstructor.js +7 -14
- package/lib/construction/argument/ArgumentConstructorHandlerHash.js +3 -2
- package/lib/construction/strategy/ConstructionStrategyCommonJsString.js +3 -0
- package/lib/construction/strategy/IConstructionStrategy.d.ts +2 -2
- package/lib/loading/ComponentRegistry.js +1 -1
- package/lib/loading/ComponentRegistryFinalizer.js +25 -4
- package/lib/preprocess/ConfigPreprocessorComponent.d.ts +3 -1
- package/lib/preprocess/ConfigPreprocessorComponent.js +34 -12
- package/lib/preprocess/ConfigPreprocessorComponentMapped.d.ts +4 -3
- package/lib/preprocess/ConfigPreprocessorComponentMapped.js +17 -18
- package/lib/preprocess/GenericsContext.d.ts +74 -0
- package/lib/preprocess/GenericsContext.js +326 -0
- package/lib/preprocess/ParameterHandler.d.ts +6 -2
- package/lib/preprocess/ParameterHandler.js +23 -21
- package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerCollectEntries.d.ts +3 -2
- package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerCollectEntries.js +24 -10
- package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerElements.d.ts +2 -1
- package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerElements.js +8 -5
- package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerFields.d.ts +2 -1
- package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerFields.js +16 -9
- package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerKeyValue.d.ts +4 -3
- package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerKeyValue.js +12 -12
- package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerList.d.ts +2 -1
- package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerList.js +9 -22
- package/lib/preprocess/constructorargumentsmapping/IConstructorArgumentsElementMappingHandler.d.ts +5 -2
- package/lib/preprocess/constructorargumentsmapping/IConstructorArgumentsMapper.d.ts +5 -2
- package/lib/preprocess/parameterproperty/IParameterPropertyHandler.d.ts +5 -2
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerDefault.d.ts +6 -3
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerDefault.js +20 -3
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerDefaultScoped.d.ts +2 -2
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerDefaultScoped.js +16 -5
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerFixed.d.ts +5 -3
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerFixed.js +25 -2
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerLazy.d.ts +2 -2
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerLazy.js +10 -3
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerRange.d.ts +38 -4
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerRange.js +412 -31
- package/lib/rdf/RdfParser.d.ts +1 -1
- package/lib/rdf/RdfParser.js +16 -4
- package/lib/rdf/RdfStreamIncluder.js +1 -1
- package/lib/util/ErrorResourcesContext.d.ts +11 -14
- package/lib/util/ErrorResourcesContext.js +44 -22
- package/package.json +2 -2
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerRequired.d.ts +0 -11
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerRequired.js +0 -23
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerUnique.d.ts +0 -12
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerUnique.js +0 -34
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { RdfObjectLoader, Resource } from 'rdf-object';
|
|
2
|
+
import type { IErrorContext } from '../../util/ErrorResourcesContext';
|
|
3
|
+
import { GenericsContext } from '../GenericsContext';
|
|
2
4
|
import type { IParameterPropertyHandler } from './IParameterPropertyHandler';
|
|
3
5
|
/**
|
|
4
6
|
* If a param range is defined, apply the type and validate the range.
|
|
@@ -6,8 +8,8 @@ import type { IParameterPropertyHandler } from './IParameterPropertyHandler';
|
|
|
6
8
|
export declare class ParameterPropertyHandlerRange implements IParameterPropertyHandler {
|
|
7
9
|
private readonly objectLoader;
|
|
8
10
|
constructor(objectLoader: RdfObjectLoader);
|
|
9
|
-
canHandle(value: Resource
|
|
10
|
-
handle(value: Resource
|
|
11
|
+
canHandle(value: Resource | undefined, configRoot: Resource, parameter: Resource): boolean;
|
|
12
|
+
handle(value: Resource | undefined, configRoot: Resource, parameter: Resource, configElement: Resource, genericsContext: GenericsContext): Resource | undefined;
|
|
11
13
|
/**
|
|
12
14
|
* Apply the given datatype to the given literal.
|
|
13
15
|
* Checks if the datatype is correct and casts to the correct js type.
|
|
@@ -15,7 +17,39 @@ export declare class ParameterPropertyHandlerRange implements IParameterProperty
|
|
|
15
17
|
* Will be ignored if the value is not a literal or the type is not recognized.
|
|
16
18
|
* @param value The value.
|
|
17
19
|
* @param param The parameter.
|
|
20
|
+
* @param genericsContext Context for generic types.
|
|
18
21
|
*/
|
|
19
|
-
captureType(value: Resource, param: Resource): Resource;
|
|
20
|
-
|
|
22
|
+
captureType(value: Resource | undefined, param: Resource, genericsContext: GenericsContext): Resource | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Check if the given value is of the given type.
|
|
25
|
+
*
|
|
26
|
+
* For valid literals, the `valueRaw` field will be set.
|
|
27
|
+
*
|
|
28
|
+
* @param value The value.
|
|
29
|
+
* @param type The parameter's range.
|
|
30
|
+
* @param genericsContext Context for generic types.
|
|
31
|
+
* @param errorContext The context for error reporting.
|
|
32
|
+
* @return IParamValueConflict A conflict value if there was an error, or undefined if there was no error
|
|
33
|
+
*/
|
|
34
|
+
hasValueType(value: Resource | undefined, type: Resource | undefined, errorContext: IErrorContext, genericsContext: GenericsContext): IParamValueConflict | undefined;
|
|
35
|
+
static throwIncorrectTypeError(value: Resource | undefined, parameter: Resource, genericsContext: GenericsContext, conflict: IParamValueConflict): never;
|
|
36
|
+
/**
|
|
37
|
+
* Check if the given value is of the given type.
|
|
38
|
+
* @param value A value.
|
|
39
|
+
* @param type A type.
|
|
40
|
+
* @param genericsContext The current generics context.
|
|
41
|
+
* @param genericTypeInstancesComponentScope
|
|
42
|
+
* @param genericTypeInstances
|
|
43
|
+
* @param errorContext
|
|
44
|
+
*/
|
|
45
|
+
hasType(value: Resource, type: Resource, genericsContext: GenericsContext, genericTypeInstancesComponentScope: Resource | undefined, genericTypeInstances: Resource[], errorContext: IErrorContext): IParamValueConflict | undefined;
|
|
46
|
+
static rangeToDisplayString(paramRange: Resource | undefined, genericsContext: GenericsContext): string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Represents a conflict between a value and a type.
|
|
50
|
+
*/
|
|
51
|
+
export interface IParamValueConflict {
|
|
52
|
+
description: string;
|
|
53
|
+
context: IErrorContext;
|
|
54
|
+
causes?: IParamValueConflict[];
|
|
21
55
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ParameterPropertyHandlerRange = void 0;
|
|
4
4
|
const Iris_1 = require("../../rdf/Iris");
|
|
5
5
|
const ErrorResourcesContext_1 = require("../../util/ErrorResourcesContext");
|
|
6
|
+
const GenericsContext_1 = require("../GenericsContext");
|
|
6
7
|
/**
|
|
7
8
|
* If a param range is defined, apply the type and validate the range.
|
|
8
9
|
*/
|
|
@@ -10,13 +11,11 @@ class ParameterPropertyHandlerRange {
|
|
|
10
11
|
constructor(objectLoader) {
|
|
11
12
|
this.objectLoader = objectLoader;
|
|
12
13
|
}
|
|
13
|
-
canHandle(value, configRoot, parameter
|
|
14
|
+
canHandle(value, configRoot, parameter) {
|
|
14
15
|
return Boolean(parameter.property.range);
|
|
15
16
|
}
|
|
16
|
-
handle(value, configRoot, parameter, configElement) {
|
|
17
|
-
|
|
18
|
-
this.captureType(subValue, parameter);
|
|
19
|
-
}
|
|
17
|
+
handle(value, configRoot, parameter, configElement, genericsContext) {
|
|
18
|
+
this.captureType(value, parameter, genericsContext);
|
|
20
19
|
return value;
|
|
21
20
|
}
|
|
22
21
|
/**
|
|
@@ -26,11 +25,48 @@ class ParameterPropertyHandlerRange {
|
|
|
26
25
|
* Will be ignored if the value is not a literal or the type is not recognized.
|
|
27
26
|
* @param value The value.
|
|
28
27
|
* @param param The parameter.
|
|
28
|
+
* @param genericsContext Context for generic types.
|
|
29
29
|
*/
|
|
30
|
-
captureType(value, param) {
|
|
31
|
-
|
|
30
|
+
captureType(value, param, genericsContext) {
|
|
31
|
+
const errorContext = { param };
|
|
32
|
+
const conflict = this.hasValueType(value, param.property.range, errorContext, genericsContext);
|
|
33
|
+
if (!conflict) {
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
ParameterPropertyHandlerRange.throwIncorrectTypeError(value, param, genericsContext, conflict);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Check if the given value is of the given type.
|
|
40
|
+
*
|
|
41
|
+
* For valid literals, the `valueRaw` field will be set.
|
|
42
|
+
*
|
|
43
|
+
* @param value The value.
|
|
44
|
+
* @param type The parameter's range.
|
|
45
|
+
* @param genericsContext Context for generic types.
|
|
46
|
+
* @param errorContext The context for error reporting.
|
|
47
|
+
* @return IParamValueConflict A conflict value if there was an error, or undefined if there was no error
|
|
48
|
+
*/
|
|
49
|
+
hasValueType(value, type, errorContext, genericsContext) {
|
|
50
|
+
errorContext = Object.assign(Object.assign({}, errorContext), { value, type });
|
|
51
|
+
if (!type) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (type.isA('ParameterRangeWildcard')) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (!value && type.isA('ParameterRangeUndefined')) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
// Always match variable values
|
|
61
|
+
if (value && value.isA('Variable')) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// Handle literal values
|
|
65
|
+
if (value && value.type === 'Literal') {
|
|
32
66
|
let parsed;
|
|
33
|
-
switch (
|
|
67
|
+
switch (type.value) {
|
|
68
|
+
case Iris_1.IRIS_XSD.string:
|
|
69
|
+
return;
|
|
34
70
|
case Iris_1.IRIS_XSD.boolean:
|
|
35
71
|
if (value.value === 'true') {
|
|
36
72
|
value.term.valueRaw = true;
|
|
@@ -39,9 +75,12 @@ class ParameterPropertyHandlerRange {
|
|
|
39
75
|
value.term.valueRaw = false;
|
|
40
76
|
}
|
|
41
77
|
else {
|
|
42
|
-
|
|
78
|
+
return {
|
|
79
|
+
description: 'value must either be "true" or "false"',
|
|
80
|
+
context: errorContext,
|
|
81
|
+
};
|
|
43
82
|
}
|
|
44
|
-
|
|
83
|
+
return;
|
|
45
84
|
case Iris_1.IRIS_XSD.integer:
|
|
46
85
|
case Iris_1.IRIS_XSD.number:
|
|
47
86
|
case Iris_1.IRIS_XSD.int:
|
|
@@ -49,44 +88,386 @@ class ParameterPropertyHandlerRange {
|
|
|
49
88
|
case Iris_1.IRIS_XSD.long:
|
|
50
89
|
parsed = Number.parseInt(value.value, 10);
|
|
51
90
|
if (Number.isNaN(parsed)) {
|
|
52
|
-
|
|
91
|
+
return {
|
|
92
|
+
description: `value is not a number`,
|
|
93
|
+
context: errorContext,
|
|
94
|
+
};
|
|
53
95
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
96
|
+
// ParseInt also parses floats to ints!
|
|
97
|
+
if (String(parsed) !== value.value) {
|
|
98
|
+
return {
|
|
99
|
+
description: `value can not be a float`,
|
|
100
|
+
context: errorContext,
|
|
101
|
+
};
|
|
60
102
|
}
|
|
61
|
-
|
|
103
|
+
value.term.valueRaw = parsed;
|
|
104
|
+
return;
|
|
62
105
|
case Iris_1.IRIS_XSD.float:
|
|
63
106
|
case Iris_1.IRIS_XSD.decimal:
|
|
64
107
|
case Iris_1.IRIS_XSD.double:
|
|
65
108
|
parsed = Number.parseFloat(value.value);
|
|
66
109
|
if (Number.isNaN(parsed)) {
|
|
67
|
-
|
|
110
|
+
return {
|
|
111
|
+
description: `value is not a number`,
|
|
112
|
+
context: errorContext,
|
|
113
|
+
};
|
|
68
114
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
break;
|
|
115
|
+
value.term.valueRaw = parsed;
|
|
116
|
+
return;
|
|
73
117
|
case Iris_1.IRIS_RDF.JSON:
|
|
74
118
|
try {
|
|
75
119
|
parsed = JSON.parse(value.value);
|
|
76
120
|
value.term.valueRaw = parsed;
|
|
77
121
|
}
|
|
78
|
-
catch (
|
|
79
|
-
|
|
122
|
+
catch (error) {
|
|
123
|
+
return {
|
|
124
|
+
description: `JSON parse exception: ${error.message}`,
|
|
125
|
+
context: errorContext,
|
|
126
|
+
};
|
|
80
127
|
}
|
|
81
|
-
|
|
128
|
+
return;
|
|
82
129
|
}
|
|
83
130
|
}
|
|
84
|
-
|
|
131
|
+
// Allow IRIs to be casted to strings
|
|
132
|
+
if (value && type.value === Iris_1.IRIS_XSD.string && value.type === 'NamedNode') {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
// Try to match the value with the parameter's range (which will always be defined at this stage)
|
|
136
|
+
// Check if the value has a super-type that equals the parameter's range
|
|
137
|
+
let hasTypeConflict;
|
|
138
|
+
if (value) {
|
|
139
|
+
const hasTypeConflictInner = this.hasType(value, type, genericsContext, value.property.genericTypeInstancesComponentScope, value.properties.genericTypeInstances, errorContext);
|
|
140
|
+
if (!hasTypeConflictInner) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
hasTypeConflict = hasTypeConflictInner;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
hasTypeConflict = undefined;
|
|
147
|
+
}
|
|
148
|
+
// Check if the param type is an array
|
|
149
|
+
if (value && type.isA('ParameterRangeArray')) {
|
|
150
|
+
if (!value.list) {
|
|
151
|
+
return {
|
|
152
|
+
description: `value is not an RDF list`,
|
|
153
|
+
context: errorContext,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
const subConflicts = value.list.map(listElement => this
|
|
157
|
+
.hasValueType(listElement, type.property.parameterRangeValue, errorContext, genericsContext))
|
|
158
|
+
.filter(subConflict => subConflict !== undefined);
|
|
159
|
+
return subConflicts.length === 0 ?
|
|
160
|
+
undefined :
|
|
161
|
+
{
|
|
162
|
+
description: `one or more array values are invalid`,
|
|
163
|
+
context: errorContext,
|
|
164
|
+
causes: subConflicts,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// Check if the param type is a composed type
|
|
168
|
+
if (type.isA('ParameterRangeUnion')) {
|
|
169
|
+
const subConflicts = [];
|
|
170
|
+
for (const parameterRangeElement of type.properties.parameterRangeElements) {
|
|
171
|
+
const subConflict = this.hasValueType(value, parameterRangeElement, errorContext, genericsContext);
|
|
172
|
+
if (!subConflict) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
subConflicts.push(subConflict);
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
description: `no union values are valid`,
|
|
179
|
+
context: errorContext,
|
|
180
|
+
causes: subConflicts,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
if (type.isA('ParameterRangeIntersection')) {
|
|
184
|
+
const subConflicts = type.properties.parameterRangeElements
|
|
185
|
+
.map(child => this.hasValueType(value, child, errorContext, genericsContext));
|
|
186
|
+
if (subConflicts.every(subConflict => subConflict === undefined)) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
description: `not all intersection values are valid`,
|
|
191
|
+
context: errorContext,
|
|
192
|
+
causes: subConflicts.filter(subConflict => subConflict !== undefined),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
if (type.isA('ParameterRangeTuple')) {
|
|
196
|
+
if (!value) {
|
|
197
|
+
return {
|
|
198
|
+
description: `undefined value is not an RDF list`,
|
|
199
|
+
context: errorContext,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
if (!value.list) {
|
|
203
|
+
return {
|
|
204
|
+
description: `value is not an RDF list`,
|
|
205
|
+
context: errorContext,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
// Iterate over list elements and try to match with tuple types
|
|
209
|
+
const listElements = value.list;
|
|
210
|
+
const tupleTypes = type.properties.parameterRangeElements;
|
|
211
|
+
let listIndex = 0;
|
|
212
|
+
let tupleIndex = 0;
|
|
213
|
+
while (listIndex < listElements.length && tupleIndex < tupleTypes.length) {
|
|
214
|
+
if (tupleTypes[tupleIndex].isA('ParameterRangeRest')) {
|
|
215
|
+
// Rest types can match multiple list elements, so only increment index if no match is found.
|
|
216
|
+
const subConflict = this.hasValueType(listElements[listIndex], tupleTypes[tupleIndex].property.parameterRangeValue, errorContext, genericsContext);
|
|
217
|
+
if (subConflict) {
|
|
218
|
+
tupleIndex++;
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
listIndex++;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
const subConflict = this.hasValueType(listElements[listIndex], tupleTypes[tupleIndex], errorContext, genericsContext);
|
|
226
|
+
if (subConflict) {
|
|
227
|
+
return {
|
|
228
|
+
description: `tuple element is invalid`,
|
|
229
|
+
context: errorContext,
|
|
230
|
+
causes: [subConflict],
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
tupleIndex++;
|
|
234
|
+
listIndex++;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (!(listIndex === listElements.length &&
|
|
238
|
+
(tupleIndex === tupleTypes.length ||
|
|
239
|
+
(tupleIndex === tupleTypes.length - 1 && tupleTypes[tupleIndex].isA('ParameterRangeRest'))))) {
|
|
240
|
+
return {
|
|
241
|
+
description: `tuple does not contain the expected number of elements`,
|
|
242
|
+
context: errorContext,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (type.isA('ParameterRangeLiteral')) {
|
|
248
|
+
if (value && value.term.equals(type.property.parameterRangeValue.term)) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
description: `literal value is unequal`,
|
|
253
|
+
context: errorContext,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
// Check if the range refers to `keyof ...`
|
|
257
|
+
if (type.isA('ParameterRangeKeyof')) {
|
|
258
|
+
const component = type.property.parameterRangeValue;
|
|
259
|
+
// Simulate a union of the member keys as literal parameter ranges
|
|
260
|
+
const simulatedUnionRange = this.objectLoader.createCompactedResource({
|
|
261
|
+
'@type': 'ParameterRangeUnion',
|
|
262
|
+
parameterRangeElements: component.properties.memberKeys.map(memberKey => ({
|
|
263
|
+
'@type': 'ParameterRangeLiteral',
|
|
264
|
+
parameterRangeValue: memberKey,
|
|
265
|
+
})),
|
|
266
|
+
});
|
|
267
|
+
const subConflict = this.hasValueType(value, simulatedUnionRange, errorContext, genericsContext);
|
|
268
|
+
if (!subConflict) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
return {
|
|
272
|
+
description: `keyof value is invalid`,
|
|
273
|
+
context: errorContext,
|
|
274
|
+
causes: [subConflict],
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
// Check if the range refers to a generic type
|
|
278
|
+
if (type.isA('ParameterRangeGenericTypeReference')) {
|
|
279
|
+
return genericsContext.bindGenericTypeToValue(type.property.parameterRangeGenericType.value, value, (subValue, subType) => this.hasValueType(subValue, subType, errorContext, genericsContext), (subType, superType) => this.hasType(subType, superType, genericsContext, undefined, [], errorContext));
|
|
280
|
+
}
|
|
281
|
+
// Check if the range refers to a component with a generic type
|
|
282
|
+
if (type.isA('ParameterRangeGenericComponent')) {
|
|
283
|
+
if (value) {
|
|
284
|
+
if (!value.property.genericTypeInstances) {
|
|
285
|
+
// For the defined generic type instances, apply them into the instance so they can be checked later during a
|
|
286
|
+
// call to GenericsContext#bindComponentGenericTypes.
|
|
287
|
+
value.property.genericTypeInstancesComponentScope = type.property.component;
|
|
288
|
+
value.properties.genericTypeInstances = type.properties.genericTypeInstances
|
|
289
|
+
.map(genericTypeInstance => {
|
|
290
|
+
// If we have a generic param type reference, instantiate them based on the current generics context
|
|
291
|
+
if (genericTypeInstance.isA('ParameterRangeGenericTypeReference')) {
|
|
292
|
+
if (!genericTypeInstance.property.parameterRangeGenericType) {
|
|
293
|
+
throw new ErrorResourcesContext_1.ErrorResourcesContext(`Invalid generic type instance in a ParameterRangeGenericComponent was detected: missing parameterRangeGenericType property.`, Object.assign(Object.assign({}, errorContext), { genericTypeInstance }));
|
|
294
|
+
}
|
|
295
|
+
return this.objectLoader.createCompactedResource({
|
|
296
|
+
'@type': 'ParameterRangeGenericTypeReference',
|
|
297
|
+
parameterRangeGenericType: genericTypeInstance.property.parameterRangeGenericType.value,
|
|
298
|
+
parameterRangeGenericBindings: genericsContext
|
|
299
|
+
.bindings[genericTypeInstance.property.parameterRangeGenericType.value],
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
// For all other param types, return the as-is
|
|
303
|
+
return genericTypeInstance;
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
// TODO: Once we support manual generics setting, we'll need to check here if we can merge with it.
|
|
308
|
+
// (sometimes, it can also be identical)
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
const subConflict = this.hasValueType(value, type.property.component, errorContext, genericsContext);
|
|
312
|
+
if (!subConflict) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
description: `generic component is invalid`,
|
|
317
|
+
context: errorContext,
|
|
318
|
+
causes: [subConflict],
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
// Check if this param defines a field with sub-params
|
|
322
|
+
if (type.isA('ParameterRangeCollectEntries')) {
|
|
323
|
+
// TODO: Add support for type-checking nested fields with collectEntries
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
return hasTypeConflict || { description: 'unknown parameter type', context: errorContext };
|
|
327
|
+
}
|
|
328
|
+
static throwIncorrectTypeError(value, parameter, genericsContext, conflict) {
|
|
329
|
+
const withTypes = value && value.properties.types.length > 0 ? ` with types "${value.properties.types.map(resource => resource.value)}"` : '';
|
|
330
|
+
// eslint-disable-next-line @typescript-eslint/no-extra-parens
|
|
331
|
+
const valueString = value ? (value.list ? `[${value.list.map(subValue => subValue.value).join(', ')}]` : value.value) : 'undefined';
|
|
332
|
+
throw new ErrorResourcesContext_1.ErrorResourcesContext(`The value "${valueString}"${withTypes} for parameter "${parameter.value}" is not of required range type "${ParameterPropertyHandlerRange.rangeToDisplayString(parameter.property.range, genericsContext)}"`, Object.assign(Object.assign({ cause: conflict, value: value || 'undefined' }, Object.keys(genericsContext.bindings).length > 0 ?
|
|
333
|
+
{ generics: `[\n ${Object.entries(genericsContext.bindings)
|
|
334
|
+
.map(([id, subValue]) => `<${id}> => ${ParameterPropertyHandlerRange.rangeToDisplayString(subValue, genericsContext)}`)
|
|
335
|
+
.join(',\n ')}\n]` } :
|
|
336
|
+
{}), { parameter }));
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Check if the given value is of the given type.
|
|
340
|
+
* @param value A value.
|
|
341
|
+
* @param type A type.
|
|
342
|
+
* @param genericsContext The current generics context.
|
|
343
|
+
* @param genericTypeInstancesComponentScope
|
|
344
|
+
* @param genericTypeInstances
|
|
345
|
+
* @param errorContext
|
|
346
|
+
*/
|
|
347
|
+
hasType(value, type, genericsContext, genericTypeInstancesComponentScope, genericTypeInstances, errorContext) {
|
|
348
|
+
var _a;
|
|
349
|
+
// Immediately return if the terms are equal
|
|
350
|
+
if (value.term.equals(type.term)) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
// Otherwise, iterate over the value's super types are recursively call this method again.
|
|
354
|
+
const subConflictTypes = [];
|
|
355
|
+
for (const valueSuperType of [...value.properties.extends, ...value.properties.type]) {
|
|
356
|
+
// Special case: if the super component is wrapped in a generic component instantiation, unwrap it.
|
|
357
|
+
if (((_a = valueSuperType.property.type) === null || _a === void 0 ? void 0 : _a.value) === this.objectLoader.contextResolved
|
|
358
|
+
.expandTerm('oo:GenericComponentExtension')) {
|
|
359
|
+
// First recursively continue calling hasType for the unwrapped component
|
|
360
|
+
const hasTypeConflict = this.hasType(valueSuperType.property.component, type, genericsContext, genericTypeInstancesComponentScope, genericTypeInstances, errorContext);
|
|
361
|
+
if (!hasTypeConflict) {
|
|
362
|
+
// If hasType has passed, validate the generic instantiations
|
|
363
|
+
// AND (possibly) the parameter's generic type instances against the component's generic params.
|
|
364
|
+
const superComponent = valueSuperType.property.component;
|
|
365
|
+
const genericsContextInner = new GenericsContext_1.GenericsContext(this.objectLoader, superComponent.properties.genericTypeParameters);
|
|
366
|
+
const typeTypeValidator = (subType, superType) => this
|
|
367
|
+
.hasType(subType, superType, genericsContextInner, undefined, [], errorContext);
|
|
368
|
+
// Try to bind the generic instances from the wrapped generic component instantiation
|
|
369
|
+
const subConflictWrapped = genericsContextInner.bindComponentGenericTypes(superComponent, valueSuperType.properties.genericTypeInstances
|
|
370
|
+
.map(instance => this.objectLoader.createCompactedResource({
|
|
371
|
+
parameterRangeGenericBindings: instance,
|
|
372
|
+
})), { value }, typeTypeValidator);
|
|
373
|
+
if (subConflictWrapped) {
|
|
374
|
+
return {
|
|
375
|
+
description: `invalid wrapped bindings for generic type instances for generic component extension of "${superComponent.value}"`,
|
|
376
|
+
context: { value, type },
|
|
377
|
+
causes: [subConflictWrapped],
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
// If the given generic type component scope applies to this component,
|
|
381
|
+
// Try to bind the generic instances from the parameter type-checking.
|
|
382
|
+
if (genericTypeInstancesComponentScope && genericTypeInstancesComponentScope.value === superComponent.value) {
|
|
383
|
+
const subConflictParam = genericsContextInner.bindComponentGenericTypes(superComponent, genericTypeInstances, { value }, typeTypeValidator);
|
|
384
|
+
if (subConflictParam) {
|
|
385
|
+
return {
|
|
386
|
+
description: `invalid parameter bindings for generic type instances for generic component extension of "${superComponent.value}"`,
|
|
387
|
+
context: { value, type },
|
|
388
|
+
causes: [subConflictParam],
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
// Extract the bound generic instances from the inner context into the actual context.
|
|
392
|
+
// This is needed for cases where param generics are bound via a wrapped generic component instantiation.
|
|
393
|
+
for (const [i, genericTypeInstance] of genericTypeInstances.entries()) {
|
|
394
|
+
const innerGenericType = genericTypeInstancesComponentScope.properties.genericTypeParameters[i].value;
|
|
395
|
+
if (genericTypeInstance.isA('ParameterRangeGenericTypeReference')) {
|
|
396
|
+
// If the generic type instance refers to another generic,
|
|
397
|
+
// bind it to the corresponding value of the inner context
|
|
398
|
+
const outerGenericType = genericTypeInstance.property.parameterRangeGenericType.value;
|
|
399
|
+
genericsContext.bindings[outerGenericType] = genericsContextInner.bindings[innerGenericType];
|
|
400
|
+
}
|
|
401
|
+
else if (!genericsContextInner.mergeRanges(genericsContextInner.bindings[innerGenericType], genericTypeInstance, typeTypeValidator)) {
|
|
402
|
+
// If the generic type instance is just a type, check it against the value in the inner context.
|
|
403
|
+
// If it does not match, return an error.
|
|
404
|
+
return {
|
|
405
|
+
description: `invalid binding for generic type <${innerGenericType}> in generic component extension of "${superComponent.value}": existing range "${ParameterPropertyHandlerRange.rangeToDisplayString(genericsContextInner.bindings[innerGenericType], genericsContextInner)}" can not be bound to range "${ParameterPropertyHandlerRange.rangeToDisplayString(genericTypeInstance, genericsContextInner)}"`,
|
|
406
|
+
context: { value, type },
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
description: `value is not a subtype of the referenced component in the generic component extension of "${valueSuperType.property.component.value}"`,
|
|
415
|
+
context: { value, type },
|
|
416
|
+
causes: [hasTypeConflict],
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
// The default case just checks the super type recursively.
|
|
420
|
+
const subConflictType = this.hasType(valueSuperType, type, genericsContext, genericTypeInstancesComponentScope, genericTypeInstances, errorContext);
|
|
421
|
+
if (!subConflictType) {
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
subConflictTypes.push(subConflictType);
|
|
425
|
+
}
|
|
426
|
+
return Object.assign({ description: `value is not a subtype of "${type.value}"`, context: { value, type } }, subConflictTypes.length > 0 ? { causes: subConflictTypes } : {});
|
|
85
427
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
428
|
+
static rangeToDisplayString(paramRange, genericsContext) {
|
|
429
|
+
if (!paramRange || paramRange.isA('ParameterRangeWildcard')) {
|
|
430
|
+
return `any`;
|
|
431
|
+
}
|
|
432
|
+
if (paramRange.isA('ParameterRangeUndefined')) {
|
|
433
|
+
return `undefined`;
|
|
434
|
+
}
|
|
435
|
+
if (paramRange.isA('ParameterRangeArray')) {
|
|
436
|
+
return `${ParameterPropertyHandlerRange.rangeToDisplayString(paramRange.property.parameterRangeValue, genericsContext)}[]`;
|
|
437
|
+
}
|
|
438
|
+
if (paramRange.isA('ParameterRangeRest')) {
|
|
439
|
+
return `...${ParameterPropertyHandlerRange.rangeToDisplayString(paramRange.property.parameterRangeValue, genericsContext)}`;
|
|
440
|
+
}
|
|
441
|
+
if (paramRange.isA('ParameterRangeKeyof')) {
|
|
442
|
+
return `keyof ${ParameterPropertyHandlerRange.rangeToDisplayString(paramRange.property.parameterRangeValue, genericsContext)}`;
|
|
443
|
+
}
|
|
444
|
+
if (paramRange.isA('ParameterRangeUnion')) {
|
|
445
|
+
return paramRange.properties.parameterRangeElements
|
|
446
|
+
.map(child => ParameterPropertyHandlerRange.rangeToDisplayString(child, genericsContext))
|
|
447
|
+
.join(' | ');
|
|
448
|
+
}
|
|
449
|
+
if (paramRange.isA('ParameterRangeIntersection')) {
|
|
450
|
+
return paramRange.properties.parameterRangeElements
|
|
451
|
+
.map(child => ParameterPropertyHandlerRange.rangeToDisplayString(child, genericsContext))
|
|
452
|
+
.join(' & ');
|
|
453
|
+
}
|
|
454
|
+
if (paramRange.isA('ParameterRangeTuple')) {
|
|
455
|
+
return `[${paramRange.properties.parameterRangeElements
|
|
456
|
+
.map(child => ParameterPropertyHandlerRange.rangeToDisplayString(child, genericsContext))
|
|
457
|
+
.join(', ')}]`;
|
|
458
|
+
}
|
|
459
|
+
if (paramRange.isA('ParameterRangeLiteral')) {
|
|
460
|
+
return paramRange.property.parameterRangeValue.value;
|
|
461
|
+
}
|
|
462
|
+
if (paramRange.isA('ParameterRangeGenericTypeReference')) {
|
|
463
|
+
const valid = paramRange.property.parameterRangeGenericType.value in genericsContext.genericTypeIds;
|
|
464
|
+
return `${valid ? 'GENERIC: ' : 'UNKNOWN GENERIC: '}${paramRange.property.parameterRangeGenericType.value}`;
|
|
465
|
+
}
|
|
466
|
+
if (paramRange.isA('ParameterRangeGenericComponent')) {
|
|
467
|
+
return `(${ParameterPropertyHandlerRange.rangeToDisplayString(paramRange.property.component, genericsContext)})<${paramRange.properties.genericTypeInstances
|
|
468
|
+
.map(genericTypeInstance => ParameterPropertyHandlerRange.rangeToDisplayString(genericTypeInstance, genericsContext)).join(', ')}>`;
|
|
469
|
+
}
|
|
470
|
+
return paramRange.value;
|
|
90
471
|
}
|
|
91
472
|
}
|
|
92
473
|
exports.ParameterPropertyHandlerRange = ParameterPropertyHandlerRange;
|
package/lib/rdf/RdfParser.d.ts
CHANGED
package/lib/rdf/RdfParser.js
CHANGED
|
@@ -20,10 +20,22 @@ class RdfParser {
|
|
|
20
20
|
// Parsing libraries don't work as expected if path contains backslashes
|
|
21
21
|
options.path = options.path.replace(/\\+/gu, '/');
|
|
22
22
|
if (!options.baseIRI) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
// Try converting path to URL using defined import paths
|
|
24
|
+
if (options.importPaths) {
|
|
25
|
+
for (const [url, file] of Object.entries(options.importPaths)) {
|
|
26
|
+
if (options.path.startsWith(file)) {
|
|
27
|
+
options.baseIRI = `${url}${options.path.slice(file.length)}`;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Fallback to a baseIRI using the file scheme
|
|
33
|
+
if (!options.baseIRI) {
|
|
34
|
+
options.baseIRI = options.path;
|
|
35
|
+
// Windows paths always contain a ':'
|
|
36
|
+
if (!options.baseIRI.includes(':') || /^[A-Za-z]:[/\\][^/]/u.test(options.baseIRI)) {
|
|
37
|
+
options.baseIRI = `file://${options.baseIRI}`;
|
|
38
|
+
}
|
|
27
39
|
}
|
|
28
40
|
}
|
|
29
41
|
// Set JSON-LD parser options
|
|
@@ -51,7 +51,7 @@ class RdfStreamIncluder extends stream_1.Transform {
|
|
|
51
51
|
// Recursively call the parser
|
|
52
52
|
RdfParser_1.RdfParser.fetchFileOrUrl(relativeFilePath)
|
|
53
53
|
.then((rawStream) => {
|
|
54
|
-
const data = new RdfParser_1.RdfParser().parse(rawStream, Object.assign(Object.assign({}, this.parserOptions), { path: relativeFilePath, importedFromPath: this.parserOptions.path }));
|
|
54
|
+
const data = new RdfParser_1.RdfParser().parse(rawStream, Object.assign(Object.assign({}, this.parserOptions), { baseIRI: undefined, path: relativeFilePath, importedFromPath: this.parserOptions.path }));
|
|
55
55
|
data
|
|
56
56
|
.on('data', (subData) => this.push(subData))
|
|
57
57
|
.on('error', (error) => this.emit('error', error))
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Resource } from 'rdf-object';
|
|
2
|
+
import type { IParamValueConflict } from '../preprocess/parameterproperty/ParameterPropertyHandlerRange';
|
|
2
3
|
/**
|
|
3
4
|
* An error that can include a context containing resources for display.
|
|
4
5
|
*/
|
|
5
6
|
export declare class ErrorResourcesContext extends Error {
|
|
6
|
-
readonly context:
|
|
7
|
-
constructor(message: string, context:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*
|
|
16
|
-
* @param resource A resource.
|
|
17
|
-
*/
|
|
18
|
-
static resourceToString(resource: Resource): string;
|
|
7
|
+
readonly context: IErrorContext;
|
|
8
|
+
constructor(message: string, context: IErrorContext);
|
|
9
|
+
exportContext(): any;
|
|
10
|
+
static contextToJson(context: IErrorContext): any;
|
|
11
|
+
static resourceToJson(resource: Resource | undefined): any;
|
|
12
|
+
static conflictToJson(conflict: IParamValueConflict): any;
|
|
13
|
+
}
|
|
14
|
+
export interface IErrorContext {
|
|
15
|
+
[key: string]: Resource | Resource[] | string | undefined | IErrorContext | IParamValueConflict;
|
|
19
16
|
}
|