Skip to content

Commit

Permalink
fix empty child classes issue (epiphone#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
martinpetlus authored May 18, 2024
1 parent 4821a25 commit d3c2ca3
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 3 deletions.
49 changes: 47 additions & 2 deletions __tests__/inheritedProperties.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import {
} from 'class-validator'
import _get from 'lodash.get'

import { JSONSchema, validationMetadatasToSchemas } from '../src'
import {
JSONSchema,
targetConstructorToSchema,
validationMetadatasToSchemas,
} from '../src'

@JSONSchema({
description: 'Contains email, password and phone',
Expand Down Expand Up @@ -43,7 +47,6 @@ class BaseContent {
@JSONSchema({
title: 'User object',
})
// @ts-ignore: not referenced
class User extends BaseContent {
@MinLength(10)
@MaxLength(20)
Expand All @@ -65,6 +68,9 @@ class User extends BaseContent {
@Contains('hello') welcome: string
}

// @ts-ignore: not referenced
class Admin extends User {}

const metadatas = _get(getFromContainer(MetadataStorage), 'validationMetadatas')

describe('Inheriting validation decorators', () => {
Expand Down Expand Up @@ -140,4 +146,43 @@ describe('Inheriting validation decorators', () => {
expect(schemas.BaseContent.required).toEqual(['email', 'phone'])
expect(schemas.User.required).toEqual(['password', 'email'])
})

it('inherits and merges validation decorators from multiple parent classes and empty child class', () => {
const schema = targetConstructorToSchema(Admin)

expect(schema).toEqual({
properties: {
email: {
default: '[email protected]',
format: 'email',
type: 'string',
not: { type: 'null' },
},
name: {
maxLength: 20,
minLength: 10,
type: 'string',
},
password: {
description: 'Password field - required!',
minLength: 20,
type: 'string',
not: { type: 'null' },
},
phone: {
format: 'mobile-phone',
title: 'Mobile phone number',
type: 'string',
not: { type: 'null' },
},
welcome: {
pattern: 'hello',
type: 'string',
},
},
required: ['name', 'welcome', 'email'],
title: 'User object',
type: 'object',
})
})
})
22 changes: 21 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,26 @@ export function validationMetadataArrayToSchemas(
return schemas
}

/**
* Search for the JSON Schema definition from child class up to the
* top parent class until empty function name is found.
*/
function getTargetConstructorSchema(
schemas: Record<string, SchemaObject>,
targetConstructor: Function
): SchemaObject {
if (!targetConstructor.name) {
return {}
} else if (schemas[targetConstructor.name]) {
return schemas[targetConstructor.name]
} else {
return getTargetConstructorSchema(
schemas,
Object.getPrototypeOf(targetConstructor)
)
}
}

/**
* Generate JSON Schema definitions from the target object constructor.
*/
Expand All @@ -122,7 +142,7 @@ export function targetConstructorToSchema(
metadatas = populateMetadatasWithConstraints(storage, metadatas)

const schemas = validationMetadataArrayToSchemas(metadatas, userOptions)
return Object.values(schemas).length ? Object.values(schemas)[0] : {}
return getTargetConstructorSchema(schemas, targetConstructor)
}

/**
Expand Down

0 comments on commit d3c2ca3

Please sign in to comment.