diff --git a/README.md b/README.md index adc467e..94eecd1 100644 --- a/README.md +++ b/README.md @@ -349,7 +349,7 @@ const Greetings = Model('Greetings', { properties: { name: TextProperty(), greeting: TextProperty(), - displayName: DenormalizedProperty("TextProperty", (modelData: TypedJsonObj) => { + displayName: DenormalizedProperty("TextProperty", (modelData: Greeting) => { return `${modelData.greeting} ${modelData.name}` }), } diff --git a/package.json b/package.json index 38055ce..0ff2e63 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "functional-models", - "version": "2.1.6", + "version": "2.1.8", "description": "A library for creating JavaScript function based models.", "main": "index.js", "types": "index.d.ts", diff --git a/src/interfaces.ts b/src/interfaces.ts index 3b757d1..2f54543 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -338,7 +338,7 @@ type OptionalModelOptions< type CalculateDenormalization< T extends FunctionalValue, TModel extends FunctionalModel, -> = (modelData: TypedJsonObj) => MaybePromise +> = (modelData: TModel, modelInstance: ModelInstance) => MaybePromise export { MaybeFunction, diff --git a/src/properties.ts b/src/properties.ts index 4985d2d..82f5580 100644 --- a/src/properties.ts +++ b/src/properties.ts @@ -455,10 +455,10 @@ const AdvancedModelReferenceProperty = < /** * A property for denormalizing values. - * @param propertyType - * @param calculate - * @param config - * @param additionalMetadata + * @param propertyType - A property type. + * @param calculate - A function for calculating the denormalized value. + * @param config - A Config + * @param additionalMetadata _ Any additional metadata. * @constructor */ const DenormalizedProperty = < @@ -479,12 +479,10 @@ const DenormalizedProperty = < modelData: TModel, modelInstance: ModelInstance ) => { - console.log('I AM HERE') - console.log(value) if (value !== undefined) { return value } - return calculate(modelData) + return calculate(modelData, modelInstance) }, }), additionalMetadata @@ -494,6 +492,72 @@ const DenormalizedProperty = < }) } +/** + * A Denormalized Property that is for text. + * @param calculate - A function that can get a string + * @param config - Any configs + * @param additionalMetadata - Optional Metadata + * @constructor + */ +const DenormalizedTextProperty = ( + calculate: CalculateDenormalization, + config: PropertyConfig = {}, + additionalMetadata = {} +) => + DenormalizedProperty( + PROPERTY_TYPES.TextProperty, + calculate, + merge(config, { + isString: true, + validators: mergeValidators(config, getCommonTextValidators(config)), + }), + additionalMetadata + ) + +/** + * A Denormalized Property that is for numbers. + * @param calculate - A function that can get a string + * @param config - Any configs + * @param additionalMetadata - Optional Metadata + * @constructor + */ +const DenormalizedNumberProperty = ( + calculate: CalculateDenormalization, + config: PropertyConfig = {}, + additionalMetadata = {} +) => + DenormalizedProperty( + PROPERTY_TYPES.NumberProperty, + calculate, + merge(config, { + isNumber: true, + validators: mergeValidators(config, getCommonNumberValidators(config)), + }), + additionalMetadata + ) + +/** + * A Denormalized Property that is for integers. + * @param calculate - A function that can get a string + * @param config - Any configs + * @param additionalMetadata - Optional Metadata + * @constructor + */ +const DenormalizedIntegerProperty = ( + calculate: CalculateDenormalization, + config: PropertyConfig = {}, + additionalMetadata = {} +) => + DenormalizedProperty( + PROPERTY_TYPES.IntegerProperty, + calculate, + merge(config, { + isInteger: true, + validators: mergeValidators(config, getCommonNumberValidators(config)), + }), + additionalMetadata + ) + /** * An Id that is naturally formed by the other properties within a model. * Instead of having a "globally unique" id the model is unique because @@ -564,4 +628,7 @@ export { EmailProperty, BooleanProperty, DenormalizedProperty, + DenormalizedIntegerProperty, + DenormalizedNumberProperty, + DenormalizedTextProperty, } diff --git a/test/src/properties.test.ts b/test/src/properties.test.ts index 60ba8bc..e4a8a08 100644 --- a/test/src/properties.test.ts +++ b/test/src/properties.test.ts @@ -19,6 +19,9 @@ import { EmailProperty, NaturalIdProperty, DenormalizedProperty, + DenormalizedIntegerProperty, + DenormalizedNumberProperty, + DenormalizedTextProperty, } from '../../src/properties' import { TYPE_PRIMITIVES, arrayType } from '../../src/validation' import { BaseModel } from '../../src/models' @@ -49,6 +52,96 @@ const TestModel1 = BaseModel('TestModel1', { }) describe('/src/properties.ts', () => { + describe('#DenormalizedTextProperty()', () => { + it('should return "Hello Dolly"', async () => { + type Greeting = { + name: string + greeting: string + displayName?: string + } + + const displayNameProperty = DenormalizedTextProperty( + (modelData: TypedJsonObj) => { + return `${modelData.greeting} ${modelData.name}` + } + ) + + const getter = displayNameProperty.createGetter( + // @ts-ignore + undefined, + { + name: 'Dolly', + greeting: 'Hello', + displayName: undefined, + }, + {} + ) + + const actual = await getter() + const expected = 'Hello Dolly' + assert.deepEqual(actual, expected) + }) + }) + describe('#DenormalizedNumberProperty()', () => { + it('should return 123.456', async () => { + type MyType = { + x: number + y: number + calculated?: number + } + + const displayNameProperty = DenormalizedNumberProperty( + (modelData: MyType) => { + return modelData.x + modelData.y + } + ) + + const getter = displayNameProperty.createGetter( + // @ts-ignore + undefined, + { + x: 123.0, + y: 0.456, + calculated: undefined, + }, + {} + ) + + const actual = await getter() + const expected = 123.456 + assert.deepEqual(actual, expected) + }) + }) + describe('#DenormalizedIntegerProperty()', () => { + it('should return 555', async () => { + type MyType = { + x: number + y: number + calculated?: number + } + + const displayNameProperty = DenormalizedIntegerProperty( + (modelData: MyType) => { + return modelData.x + modelData.y + } + ) + + const getter = displayNameProperty.createGetter( + // @ts-ignore + undefined, + { + x: 222, + y: 333, + calculated: undefined, + }, + {} + ) + + const actual = await getter() + const expected = 555 + assert.deepEqual(actual, expected) + }) + }) describe('#DenormalizedProperty()', () => { it('should return "Hello Dolly"', async () => { type Greeting = { @@ -59,7 +152,7 @@ describe('/src/properties.ts', () => { const displayNameProperty = DenormalizedProperty( 'TextProperty', - (modelData: TypedJsonObj) => { + (modelData: Greeting) => { return `${modelData.greeting} ${modelData.name}` } ) @@ -88,7 +181,7 @@ describe('/src/properties.ts', () => { const displayNameProperty = DenormalizedProperty( 'TextProperty', - (modelData: TypedJsonObj) => { + (modelData: Greeting) => { return `${modelData.greeting} ${modelData.name}` } )