Skip to content

Commit 54325c8

Browse files
pedro2sepiphone
andauthored
Handle class-transformer @Expose decorator (#120)
* feat: enhance validation metadata processing to support class-transformer exposed metadata * feat: add tests for Expose decorator and improve metadata handling * Update src/index.ts Co-authored-by: Aleksi Pekkala <aleksipekkala@gmail.com> * Update src/index.ts Co-authored-by: Aleksi Pekkala <aleksipekkala@gmail.com> * fix: refactor for CI approved --------- Co-authored-by: Aleksi Pekkala <aleksipekkala@gmail.com>
1 parent 3cc1803 commit 54325c8

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

__tests__/expose.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// tslint:disable:no-submodule-imports
2+
import { Expose } from 'class-transformer'
3+
import { IsString } from 'class-validator'
4+
import { validationMetadatasToSchemas } from '../src'
5+
const { defaultMetadataStorage } = require('class-transformer/cjs/storage')
6+
7+
// @ts-ignore unused
8+
class User {
9+
@IsString()
10+
id: string
11+
12+
@Expose({ name: 'domain_id' })
13+
@IsString()
14+
domainId: string
15+
}
16+
17+
describe('Expose() decorator', () => {
18+
it('rename Expose()-decorated properties from output schema', () => {
19+
const schema = validationMetadatasToSchemas({
20+
classTransformerMetadataStorage: defaultMetadataStorage,
21+
})
22+
23+
expect(schema).toEqual({
24+
User: {
25+
properties: {
26+
id: { type: 'string' },
27+
domain_id: { type: 'string' },
28+
},
29+
type: 'object',
30+
required: ['id', 'domain_id'],
31+
},
32+
})
33+
})
34+
})

src/index.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type { ReferenceObject, SchemaObject } from 'openapi3-ts'
88
import { getMetadataSchema } from './decorators'
99
import { defaultConverters } from './defaultConverters'
1010
import { defaultOptions, IOptions } from './options'
11+
import { ExposeMetadata } from 'class-transformer'
1112

1213
export { JSONSchema } from './decorators'
1314

@@ -64,6 +65,26 @@ export function validationMetadataArrayToSchemas(
6465
isExcluded({ ...propMeta, target }, options)
6566
)
6667
)
68+
.map((propMeta) => {
69+
/**
70+
* Retrieves all properties that have the Expose decorator from class-transformer
71+
* and remaps the property names to the names exposed by the Expose decorator.
72+
*/
73+
const exposeMetadata =
74+
userOptions?.classTransformerMetadataStorage?.getExposedMetadatas(
75+
propMeta.target as any
76+
)
77+
78+
const ctMetaForField = exposeMetadata?.find(
79+
(meta: ExposeMetadata) => meta.propertyName === propMeta.propertyName
80+
)
81+
82+
if (ctMetaForField?.options.name) {
83+
propMeta.propertyName = ctMetaForField.options.name
84+
}
85+
86+
return propMeta
87+
})
6788

6889
const properties: { [name: string]: ReferenceObject | SchemaObject } = {}
6990

0 commit comments

Comments
 (0)