Skip to content

Commit 8c6d27d

Browse files
authored
Merge pull request #82 from LumaKernel/port/190
feat(validation): allow user to specify custom plainToInstance and validateOrReject
2 parents c2e8157 + 8df0f61 commit 8c6d27d

File tree

6 files changed

+52
-12
lines changed

6 files changed

+52
-12
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
44

5-
## [0.28.0](https://github.com/frouriojs/frourio-express/compare/v0.27.1...v0.28.0) (2022-03-11)
5+
## [0.28.0](https://github.com/frouriojs/frourio-express/compare/v0.27.1...v0.28.0) (2022-03-14)
66

77
### Features
88

99
* add "or undefined" explicitly to support exactOptionalPropertyTypes (https://github.com/frouriojs/frourio-express/pull/81)
10+
* feat(validation): allow user to specify custom plainToInstance and validateOrReject (https://github.com/frouriojs/frourio-express/pull/82)
1011

1112
## [0.27.1](https://github.com/frouriojs/frourio-express/compare/v0.27.0...v0.27.1) (2022-02-28)
1213

__test__/index.spec.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import rimraf from 'rimraf'
55
import express from 'express'
66
import FormData from 'form-data'
77
import axios from 'axios'
8+
import { plainToInstance } from 'class-transformer'
9+
import { validateOrReject } from 'class-validator'
810
import aspida from '@aspida/axios'
911
import aspidaFetch from '@aspida/node-fetch'
1012
import api from '../servers/all/api/$api'
@@ -20,11 +22,25 @@ const client = api(aspida(undefined, { baseURL }))
2022
const fetchClient = api(aspidaFetch(undefined, { baseURL: subBaseURL, throwHttpErrors: true }))
2123
let server: Server
2224
let subServer: Server
25+
let subServerPlainToInstanceCallCount = 0
26+
let subServerValidateOrRejectCallCount = 0
2327

2428
beforeEach(cb => {
2529
server = frourio(express()).listen(port, () => {
26-
subServer = frourio(express(), { basePath: subBasePath }).listen(subPort, cb)
30+
subServer = frourio(express(), {
31+
basePath: subBasePath,
32+
plainToInstance: (cls, object, options): object => {
33+
subServerPlainToInstanceCallCount++
34+
return plainToInstance(cls, object, options)
35+
},
36+
validateOrReject: (instance, options): Promise<void> => {
37+
subServerValidateOrRejectCallCount++
38+
return validateOrReject(instance, options)
39+
}
40+
}).listen(subPort, cb)
2741
})
42+
subServerPlainToInstanceCallCount = 0
43+
subServerValidateOrRejectCallCount = 0
2844
})
2945

3046
afterEach(cb => {
@@ -134,6 +150,9 @@ test('PUT: JSON', async () => {
134150
})
135151

136152
test('POST: formdata', async () => {
153+
expect(subServerPlainToInstanceCallCount).toBe(0)
154+
expect(subServerValidateOrRejectCallCount).toBe(0)
155+
137156
const port = '3000'
138157
const fileName = 'tsconfig.json'
139158
const res1 = await client.$post({
@@ -150,6 +169,9 @@ test('POST: formdata', async () => {
150169
expect(res1.port).toBe(port)
151170
expect(res1.fileName).toBe(fileName)
152171

172+
expect(subServerPlainToInstanceCallCount).toBe(0)
173+
expect(subServerValidateOrRejectCallCount).toBe(0)
174+
153175
const res2 = await fetchClient.$post({
154176
query: {
155177
requiredNum: 0,
@@ -163,6 +185,10 @@ test('POST: formdata', async () => {
163185
})
164186
expect(res2.port).toBe(port)
165187
expect(res2.fileName).toBe(fileName)
188+
189+
// 2 = query + body
190+
expect(subServerPlainToInstanceCallCount).toBe(2)
191+
expect(subServerValidateOrRejectCallCount).toBe(2)
166192
})
167193

168194
test('POST: multi file upload', async () => {

servers/all/$server.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import 'reflect-metadata'
22
import type { ClassTransformOptions } from 'class-transformer'
3-
import { plainToInstance } from 'class-transformer'
3+
import { plainToInstance as defaultPlainToInstance } from 'class-transformer'
44
import type { ValidatorOptions } from 'class-validator'
5-
import { validateOrReject } from 'class-validator'
5+
import { validateOrReject as defaultValidateOrReject } from 'class-validator'
66
import path from 'path'
77
import type { Express, RequestHandler, Request } from 'express'
88
import express from 'express'
@@ -33,6 +33,8 @@ export type FrourioOptions = {
3333
basePath?: string
3434
transformer?: ClassTransformOptions | undefined
3535
validator?: ValidatorOptions | undefined
36+
plainToInstance?: ((cls: new (...args: any[]) => object, object: unknown, options: ClassTransformOptions) => object) | undefined
37+
validateOrReject?: ((instance: object, options: ValidatorOptions) => Promise<void>) | undefined
3638
multer?: Options | undefined
3739
}
3840

@@ -273,6 +275,7 @@ export default (app: Express, options: FrourioOptions = {}) => {
273275
const basePath = options.basePath ?? ''
274276
const transformerOptions: ClassTransformOptions = { enableCircularCheck: true, ...options.transformer }
275277
const validatorOptions: ValidatorOptions = { validationError: { target: false }, ...options.validator }
278+
const { plainToInstance = defaultPlainToInstance as NonNullable<FrourioOptions["plainToInstance"]>, validateOrReject = defaultValidateOrReject as NonNullable<FrourioOptions["validateOrReject"]> } = options
276279
const hooks0 = hooksFn0(app)
277280
const hooks1 = hooksFn1(app)
278281
const hooks2 = hooksFn2(app)

servers/noMulter/$server.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import 'reflect-metadata'
22
import type { ClassTransformOptions } from 'class-transformer'
3-
import { plainToInstance } from 'class-transformer'
3+
import { plainToInstance as defaultPlainToInstance } from 'class-transformer'
44
import type { ValidatorOptions } from 'class-validator'
5-
import { validateOrReject } from 'class-validator'
5+
import { validateOrReject as defaultValidateOrReject } from 'class-validator'
66
import type { Express, RequestHandler, Request } from 'express'
77
import express from 'express'
88
import * as Validators from './validators'
@@ -21,6 +21,8 @@ export type FrourioOptions = {
2121
basePath?: string
2222
transformer?: ClassTransformOptions | undefined
2323
validator?: ValidatorOptions | undefined
24+
plainToInstance?: ((cls: new (...args: any[]) => object, object: unknown, options: ClassTransformOptions) => object) | undefined
25+
validateOrReject?: ((instance: object, options: ValidatorOptions) => Promise<void>) | undefined
2426
}
2527

2628
type HttpStatusNoOk = 301 | 302 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 409 | 500 | 501 | 502 | 503 | 504 | 505
@@ -127,6 +129,7 @@ export default (app: Express, options: FrourioOptions = {}) => {
127129
const basePath = options.basePath ?? ''
128130
const transformerOptions: ClassTransformOptions = { enableCircularCheck: true, ...options.transformer }
129131
const validatorOptions: ValidatorOptions = { validationError: { target: false }, ...options.validator }
132+
const { plainToInstance = defaultPlainToInstance as NonNullable<FrourioOptions["plainToInstance"]>, validateOrReject = defaultValidateOrReject as NonNullable<FrourioOptions["validateOrReject"]> } = options
130133
const hooks0 = hooksFn0(app)
131134
const hooks1 = hooksFn1(app)
132135
const ctrlHooks0 = ctrlHooksFn0(app)

servers/noTypedParams/$server.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import 'reflect-metadata'
22
import type { ClassTransformOptions } from 'class-transformer'
3-
import { plainToInstance } from 'class-transformer'
3+
import { plainToInstance as defaultPlainToInstance } from 'class-transformer'
44
import type { ValidatorOptions } from 'class-validator'
5-
import { validateOrReject } from 'class-validator'
5+
import { validateOrReject as defaultValidateOrReject } from 'class-validator'
66
import path from 'path'
77
import type { Express, RequestHandler, Request } from 'express'
88
import express from 'express'
@@ -25,6 +25,8 @@ export type FrourioOptions = {
2525
basePath?: string
2626
transformer?: ClassTransformOptions | undefined
2727
validator?: ValidatorOptions | undefined
28+
plainToInstance?: ((cls: new (...args: any[]) => object, object: unknown, options: ClassTransformOptions) => object) | undefined
29+
validateOrReject?: ((instance: object, options: ValidatorOptions) => Promise<void>) | undefined
2830
multer?: Options | undefined
2931
}
3032

@@ -153,6 +155,7 @@ export default (app: Express, options: FrourioOptions = {}) => {
153155
const basePath = options.basePath ?? ''
154156
const transformerOptions: ClassTransformOptions = { enableCircularCheck: true, ...options.transformer }
155157
const validatorOptions: ValidatorOptions = { validationError: { target: false }, ...options.validator }
158+
const { plainToInstance = defaultPlainToInstance as NonNullable<FrourioOptions["plainToInstance"]>, validateOrReject = defaultValidateOrReject as NonNullable<FrourioOptions["validateOrReject"]> } = options
156159
const hooks0 = hooksFn0(app)
157160
const hooks1 = hooksFn1(app)
158161
const ctrlHooks0 = ctrlHooksFn0(app)

src/buildServerFile.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ export default (input: string, project?: string) => {
8585
headIpmorts.push(
8686
"import 'reflect-metadata'",
8787
"import type { ClassTransformOptions } from 'class-transformer'",
88-
"import { plainToInstance } from 'class-transformer'",
88+
"import { plainToInstance as defaultPlainToInstance } from 'class-transformer'",
8989
"import type { ValidatorOptions } from 'class-validator'",
90-
"import { validateOrReject } from 'class-validator'"
90+
"import { validateOrReject as defaultValidateOrReject } from 'class-validator'"
9191
)
9292
}
9393

@@ -132,7 +132,10 @@ export type FrourioOptions = {
132132
basePath?: string
133133
${
134134
hasValidator
135-
? ' transformer?: ClassTransformOptions | undefined\n validator?: ValidatorOptions | undefined\n'
135+
? ' transformer?: ClassTransformOptions | undefined\n' +
136+
' validator?: ValidatorOptions | undefined\n' +
137+
' plainToInstance?: ((cls: new (...args: any[]) => object, object: unknown, options: ClassTransformOptions) => object) | undefined\n' +
138+
' validateOrReject?: ((instance: object, options: ValidatorOptions) => Promise<void>) | undefined\n'
136139
: ''
137140
}${
138141
hasMulter
@@ -340,7 +343,8 @@ export default (app: Express, options: FrourioOptions = {}) => {
340343
${
341344
hasValidator
342345
? ' const transformerOptions: ClassTransformOptions = { enableCircularCheck: true, ...options.transformer }\n' +
343-
' const validatorOptions: ValidatorOptions = { validationError: { target: false }, ...options.validator }\n'
346+
' const validatorOptions: ValidatorOptions = { validationError: { target: false }, ...options.validator }\n' +
347+
' const { plainToInstance = defaultPlainToInstance as NonNullable<FrourioOptions["plainToInstance"]>, validateOrReject = defaultValidateOrReject as NonNullable<FrourioOptions["validateOrReject"]> } = options\n'
344348
: ''
345349
}${consts}${
346350
hasMulter

0 commit comments

Comments
 (0)