diff --git a/src/helpers/ConstrainHelpers.ts b/src/helpers/ConstrainHelpers.ts index 7aa53e49db..843dc8ede5 100644 --- a/src/helpers/ConstrainHelpers.ts +++ b/src/helpers/ConstrainHelpers.ts @@ -2,8 +2,10 @@ import { ConstrainedAnyModel, ConstrainedBooleanModel, ConstrainedFloatModel, Co import { AnyModel, BooleanModel, FloatModel, IntegerModel, ObjectModel, ReferenceModel, StringModel, TupleModel, ArrayModel, UnionModel, EnumModel, DictionaryModel, MetaModel, ObjectPropertyModel } from '../models/MetaModel'; import { getTypeFromMapping, TypeMapping } from './TypeHelpers'; -export type ConstrainContext = { - propertyKey?: string, +export type ConstrainContext< + Options, + M extends MetaModel> = { + partOfProperty?: ConstrainedObjectPropertyModel, metaModel: M, constrainedName: string, options: Options @@ -50,12 +52,12 @@ function constrainReferenceModel(typeMapping: TypeMapping, con const constrainedModel = new ConstrainedReferenceModel(context.constrainedName, context.metaModel.originalInput, '', placeHolderConstrainedObject); alreadySeenModels.set(context.metaModel, constrainedModel); - const constrainedRefModel = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: context.metaModel.ref, propertyKey: undefined}, alreadySeenModels); + const constrainedRefModel = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: context.metaModel.ref, partOfProperty: undefined}, alreadySeenModels); constrainedModel.ref = constrainedRefModel; constrainedModel.type = getTypeFromMapping(typeMapping, { constrainedModel, options: context.options, - propertyKey: context.propertyKey + partOfProperty: context.partOfProperty }); return constrainedModel; } @@ -64,7 +66,7 @@ function constrainAnyModel(typeMapping: TypeMapping, context: constrainedModel.type = getTypeFromMapping(typeMapping, { constrainedModel, options: context.options, - propertyKey: context.propertyKey + partOfProperty: context.partOfProperty }); return constrainedModel; } @@ -73,7 +75,7 @@ function constrainFloatModel(typeMapping: TypeMapping, context constrainedModel.type = getTypeFromMapping(typeMapping, { constrainedModel, options: context.options, - propertyKey: context.propertyKey + partOfProperty: context.partOfProperty }); return constrainedModel; } @@ -82,7 +84,7 @@ function constrainIntegerModel(typeMapping: TypeMapping, conte constrainedModel.type = getTypeFromMapping(typeMapping, { constrainedModel, options: context.options, - propertyKey: context.propertyKey + partOfProperty: context.partOfProperty }); return constrainedModel; } @@ -91,7 +93,7 @@ function constrainStringModel(typeMapping: TypeMapping, contex constrainedModel.type = getTypeFromMapping(typeMapping, { constrainedModel, options: context.options, - propertyKey: context.propertyKey + partOfProperty: context.partOfProperty }); return constrainedModel; } @@ -100,7 +102,7 @@ function constrainBooleanModel(typeMapping: TypeMapping, conte constrainedModel.type = getTypeFromMapping(typeMapping, { constrainedModel, options: context.options, - propertyKey: context.propertyKey + partOfProperty: context.partOfProperty }); return constrainedModel; } @@ -109,26 +111,26 @@ function constrainTupleModel(typeMapping: TypeMapping, constra alreadySeenModels.set(context.metaModel, constrainedModel); const constrainedTupleModels = context.metaModel.tuple.map((tupleValue) => { - const tupleType = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: tupleValue.value, propertyKey: undefined}, alreadySeenModels); + const tupleType = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: tupleValue.value, partOfProperty: undefined}, alreadySeenModels); return new ConstrainedTupleValueModel(tupleValue.index, tupleType); }); constrainedModel.tuple = constrainedTupleModels; constrainedModel.type = getTypeFromMapping(typeMapping, { constrainedModel, options: context.options, - propertyKey: context.propertyKey + partOfProperty: context.partOfProperty }); return constrainedModel; } function constrainArrayModel(typeMapping: TypeMapping, constrainRules: Constraints, context: ConstrainContext, alreadySeenModels: Map): ConstrainedArrayModel { const constrainedModel = new ConstrainedArrayModel(context.constrainedName, context.metaModel.originalInput, '', placeHolderConstrainedObject); alreadySeenModels.set(context.metaModel, constrainedModel); - const constrainedValueModel = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: context.metaModel.valueModel, propertyKey: undefined}, alreadySeenModels); + const constrainedValueModel = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: context.metaModel.valueModel, partOfProperty: undefined}, alreadySeenModels); constrainedModel.valueModel = constrainedValueModel; constrainedModel.type = getTypeFromMapping(typeMapping, { constrainedModel, options: context.options, - propertyKey: context.propertyKey + partOfProperty: context.partOfProperty }); return constrainedModel; } @@ -137,13 +139,13 @@ function constrainUnionModel(typeMapping: TypeMapping, constra alreadySeenModels.set(context.metaModel, constrainedModel); const constrainedUnionModels = context.metaModel.union.map((unionValue) => { - return constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: unionValue, propertyKey: undefined}, alreadySeenModels); + return constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: unionValue, partOfProperty: undefined}, alreadySeenModels); }); constrainedModel.union = constrainedUnionModels; constrainedModel.type = getTypeFromMapping(typeMapping, { constrainedModel, options: context.options, - propertyKey: context.propertyKey + partOfProperty: context.partOfProperty }); return constrainedModel; } @@ -151,14 +153,14 @@ function constrainDictionaryModel(typeMapping: TypeMapping, co const constrainedModel = new ConstrainedDictionaryModel(context.constrainedName, context.metaModel.originalInput, '', placeHolderConstrainedObject, placeHolderConstrainedObject, context.metaModel.serializationType); alreadySeenModels.set(context.metaModel, constrainedModel); - const keyModel = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: context.metaModel.key, propertyKey: undefined}, alreadySeenModels); + const keyModel = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: context.metaModel.key, partOfProperty: undefined}, alreadySeenModels); constrainedModel.key = keyModel; - const valueModel = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: context.metaModel.value, propertyKey: undefined}, alreadySeenModels); + const valueModel = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: context.metaModel.value, partOfProperty: undefined}, alreadySeenModels); constrainedModel.value = valueModel; constrainedModel.type = getTypeFromMapping(typeMapping, { constrainedModel, options: context.options, - propertyKey: context.propertyKey + partOfProperty: context.partOfProperty }); return constrainedModel; } @@ -171,14 +173,14 @@ function constrainObjectModel(typeMapping: TypeMapping, constr const constrainedPropertyModel = new ConstrainedObjectPropertyModel('', propertyMetaModel.propertyName, propertyMetaModel.required, constrainedModel); const constrainedPropertyName = constrainRules.propertyKey({objectPropertyModel: propertyMetaModel, constrainedObjectPropertyModel: constrainedPropertyModel, constrainedObjectModel: constrainedModel, objectModel: context.metaModel}); constrainedPropertyModel.propertyName = constrainedPropertyName; - const constrainedProperty = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: propertyMetaModel.property, propertyKey: constrainedPropertyName}, alreadySeenModels); + const constrainedProperty = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: propertyMetaModel.property, partOfProperty: constrainedPropertyModel}, alreadySeenModels); constrainedPropertyModel.property = constrainedProperty; constrainedModel.properties[String(constrainedPropertyName)] = constrainedPropertyModel; } constrainedModel.type = getTypeFromMapping(typeMapping, { constrainedModel, options: context.options, - propertyKey: context.propertyKey + partOfProperty: context.partOfProperty }); return constrainedModel; } @@ -193,7 +195,7 @@ function ConstrainEnumModel(typeMapping: TypeMapping, constrai const constrainedEnumValueModel = new ConstrainedEnumValueModel(constrainedEnumKey, constrainedEnumValue); constrainedModel.values.push(constrainedEnumValueModel); } - constrainedModel.type = getTypeFromMapping(typeMapping, {constrainedModel, options: context.options, propertyKey: context.propertyKey}); + constrainedModel.type = getTypeFromMapping(typeMapping, {constrainedModel, options: context.options, partOfProperty: context.partOfProperty}); return constrainedModel; } diff --git a/src/helpers/TypeHelpers.ts b/src/helpers/TypeHelpers.ts index ffbfd00519..c13e5969ca 100644 --- a/src/helpers/TypeHelpers.ts +++ b/src/helpers/TypeHelpers.ts @@ -1,7 +1,7 @@ -import { ConstrainedAnyModel, ConstrainedBooleanModel, ConstrainedFloatModel, ConstrainedIntegerModel, ConstrainedMetaModel, ConstrainedObjectModel, ConstrainedReferenceModel, ConstrainedStringModel, ConstrainedTupleModel, ConstrainedArrayModel, ConstrainedUnionModel, ConstrainedEnumModel, ConstrainedDictionaryModel } from '../models/ConstrainedMetaModel'; +import { ConstrainedAnyModel, ConstrainedBooleanModel, ConstrainedFloatModel, ConstrainedIntegerModel, ConstrainedMetaModel, ConstrainedObjectModel, ConstrainedReferenceModel, ConstrainedStringModel, ConstrainedTupleModel, ConstrainedArrayModel, ConstrainedUnionModel, ConstrainedEnumModel, ConstrainedDictionaryModel, ConstrainedObjectPropertyModel } from '../models/ConstrainedMetaModel'; export type TypeContext = { - propertyKey?: string, + partOfProperty?: ConstrainedObjectPropertyModel, options: Options, constrainedModel: T, } diff --git a/test/helpers/ConstrainHelpers.spec.ts b/test/helpers/ConstrainHelpers.spec.ts index 639cb62583..d76de98062 100644 --- a/test/helpers/ConstrainHelpers.spec.ts +++ b/test/helpers/ConstrainHelpers.spec.ts @@ -26,6 +26,18 @@ describe('ConstrainHelpers', () => { expect(mockedTypeMapping.String).toHaveBeenCalledTimes(1); }); + test('should have access to partOfProperty', () => { + const testProperty = new StringModel('', undefined); + const metaModel = new ObjectModel('test', undefined, { + testProperty: new ObjectPropertyModel('testProperty', false, testProperty) + }); + constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(mockedTypeMapping.String).toBeCalledWith(expect.objectContaining({partOfProperty: expect.objectContaining({})})); + }); test('should handle recursive models', () => { const model = new ObjectModel('testObj', undefined, {}); const objectPropertyModel = new ObjectPropertyModel('recursiveProp', false, model); diff --git a/test/helpers/TypeHelpers.spec.ts b/test/helpers/TypeHelpers.spec.ts index d510494345..b5058b49c5 100644 --- a/test/helpers/TypeHelpers.spec.ts +++ b/test/helpers/TypeHelpers.spec.ts @@ -1,5 +1,5 @@ import { getTypeFromMapping, TypeMapping } from '../../src/helpers'; -import { CommonModel, ConstrainedAnyModel, ConstrainedArrayModel, ConstrainedBooleanModel, ConstrainedDictionaryModel, ConstrainedEnumModel, ConstrainedFloatModel, ConstrainedIntegerModel, ConstrainedMetaModel, ConstrainedObjectModel, ConstrainedReferenceModel, ConstrainedStringModel, ConstrainedTupleModel, ConstrainedUnionModel } from '../../src/models'; +import { CommonModel, ConstrainedAnyModel, ConstrainedArrayModel, ConstrainedBooleanModel, ConstrainedDictionaryModel, ConstrainedEnumModel, ConstrainedFloatModel, ConstrainedIntegerModel, ConstrainedMetaModel, ConstrainedObjectModel, ConstrainedObjectPropertyModel, ConstrainedReferenceModel, ConstrainedStringModel, ConstrainedTupleModel, ConstrainedUnionModel } from '../../src/models'; describe('TypeHelpers', () => { describe('getTypeFromMapping', () => { @@ -24,12 +24,12 @@ describe('TypeHelpers', () => { } test('should return undefined with generic constrained model', () => { const constrainedModel = new CustomConstrainedMetaModel('', undefined, ''); - const t = () => { getTypeFromMapping(typeMapping, {constrainedModel, options: {}}); }; expect(t).toThrow('Could not find type for model'); }); + const modelsToCheck = [ new ConstrainedObjectModel('', undefined, '', {}), new ConstrainedReferenceModel('', undefined, '', new CustomConstrainedMetaModel('', undefined, '')),