1
1
import ono from 'ono' ;
2
+ import ajv = require( 'ajv' ) ;
2
3
import * as express from 'express' ;
3
4
import * as _uniq from 'lodash.uniq' ;
4
5
import * as cloneDeep from 'lodash.clonedeep' ;
@@ -15,6 +16,7 @@ import {
15
16
OpenApiRequestMetadata ,
16
17
ValidateSecurityOpts ,
17
18
OpenAPIV3 ,
19
+ RequestValidatorOptions ,
18
20
} from './framework/types' ;
19
21
import { defaultResolver } from './resolvers' ;
20
22
import { OperationHandlerOptions } from './framework/types' ;
@@ -35,6 +37,7 @@ export {
35
37
36
38
export class OpenApiValidator {
37
39
readonly options : OpenApiValidatorOpts ;
40
+ readonly ajvOpts : AjvOptions ;
38
41
39
42
constructor ( options : OpenApiValidatorOpts ) {
40
43
this . validateOptions ( options ) ;
@@ -82,6 +85,7 @@ export class OpenApiValidator {
82
85
}
83
86
84
87
this . options = options ;
88
+ this . ajvOpts = new AjvOptions ( options ) ;
85
89
}
86
90
87
91
installMiddleware ( spec : Promise < Spec > ) : OpenApiRequestHandler [ ] {
@@ -90,14 +94,10 @@ export class OpenApiValidator {
90
94
const responseApiDoc = this . options . validateResponses
91
95
? cloneDeep ( spec . apiDoc )
92
96
: null ;
93
- new RequestSchemaPreprocessor ( spec . apiDoc , {
94
- nullable : true ,
95
- coerceTypes : this . options . coerceTypes ,
96
- removeAdditional : false ,
97
- useDefaults : true ,
98
- unknownFormats : this . options . unknownFormats ,
99
- format : this . options . validateFormats ,
100
- } ) . preProcess ( ) ;
97
+ new RequestSchemaPreprocessor (
98
+ spec . apiDoc ,
99
+ this . ajvOpts . preprocessor ,
100
+ ) . preProcess ( ) ;
101
101
102
102
return {
103
103
context : new OpenApiContext ( spec , this . options . ignorePaths ) ,
@@ -249,7 +249,7 @@ export class OpenApiValidator {
249
249
private multipartMiddleware ( apiDoc : OpenAPIV3 . Document ) {
250
250
return middlewares . multipart ( apiDoc , {
251
251
multerOpts : this . options . fileUploader ,
252
- unknownFormats : this . options . unknownFormats ,
252
+ ajvOpts : this . ajvOpts . multipart ,
253
253
} ) ;
254
254
}
255
255
@@ -261,59 +261,18 @@ export class OpenApiValidator {
261
261
}
262
262
263
263
private requestValidationMiddleware ( apiDoc : OpenAPIV3 . Document ) {
264
- const {
265
- coerceTypes,
266
- unknownFormats,
267
- validateRequests,
268
- validateFormats,
269
- formats,
270
- } = this . options ;
271
- const { allowUnknownQueryParameters } = < ValidateRequestOpts > (
272
- validateRequests
264
+ const requestValidator = new middlewares . RequestValidator (
265
+ apiDoc ,
266
+ this . ajvOpts . request ,
273
267
) ;
274
- const requestValidator = new middlewares . RequestValidator ( apiDoc , {
275
- nullable : true ,
276
- coerceTypes,
277
- removeAdditional : false ,
278
- useDefaults : true ,
279
- unknownFormats,
280
- allowUnknownQueryParameters,
281
- format : validateFormats ,
282
- formats : formats . reduce ( ( acc , f ) => {
283
- acc [ f . name ] = {
284
- type : f . type ,
285
- validate : f . validate ,
286
- } ;
287
- return acc ;
288
- } , { } ) ,
289
- } ) ;
290
268
return ( req , res , next ) => requestValidator . validate ( req , res , next ) ;
291
269
}
292
270
293
271
private responseValidationMiddleware ( apiDoc : OpenAPIV3 . Document ) {
294
- const {
295
- coerceTypes,
296
- unknownFormats,
297
- validateResponses,
298
- validateFormats,
299
- formats,
300
- } = this . options ;
301
- const { removeAdditional } = < ValidateResponseOpts > validateResponses ;
302
-
303
- return new middlewares . ResponseValidator ( apiDoc , {
304
- nullable : true ,
305
- coerceTypes,
306
- removeAdditional,
307
- unknownFormats,
308
- format : validateFormats ,
309
- formats : formats . reduce ( ( acc , f ) => {
310
- acc [ f . name ] = {
311
- type : f . type ,
312
- valdiate : f . validate ,
313
- } ;
314
- return acc ;
315
- } , { } ) ,
316
- } ) . validate ( ) ;
272
+ return new middlewares . ResponseValidator (
273
+ apiDoc ,
274
+ this . ajvOpts . response ,
275
+ ) . validate ( ) ;
317
276
}
318
277
319
278
installOperationHandlers ( baseUrl : string , context : OpenApiContext ) : Router {
@@ -394,3 +353,57 @@ export class OpenApiValidator {
394
353
}
395
354
}
396
355
}
356
+
357
+ class AjvOptions {
358
+ private options : OpenApiValidatorOpts ;
359
+ constructor ( options : OpenApiValidatorOpts ) {
360
+ this . options = options ;
361
+ }
362
+ get preprocessor ( ) : ajv . Options {
363
+ return this . baseOptions ( ) ;
364
+ }
365
+
366
+ get response ( ) : ajv . Options {
367
+ const { removeAdditional } = < ValidateResponseOpts > (
368
+ this . options . validateResponses
369
+ ) ;
370
+ return {
371
+ ...this . baseOptions ( ) ,
372
+ useDefaults : false ,
373
+ removeAdditional,
374
+ } ;
375
+ }
376
+
377
+ get request ( ) : RequestValidatorOptions {
378
+ const { allowUnknownQueryParameters } = < ValidateRequestOpts > (
379
+ this . options . validateRequests
380
+ ) ;
381
+ return {
382
+ ...this . baseOptions ( ) ,
383
+ allowUnknownQueryParameters,
384
+ } ;
385
+ }
386
+
387
+ get multipart ( ) : ajv . Options {
388
+ return this . baseOptions ( ) ;
389
+ }
390
+
391
+ private baseOptions ( ) : ajv . Options {
392
+ const { coerceTypes, unknownFormats, validateFormats } = this . options ;
393
+ return {
394
+ nullable : true ,
395
+ coerceTypes,
396
+ useDefaults : true ,
397
+ removeAdditional : false ,
398
+ unknownFormats,
399
+ format : validateFormats ,
400
+ formats : this . options . formats . reduce ( ( acc , f ) => {
401
+ acc [ f . name ] = {
402
+ type : f . type ,
403
+ validate : f . validate ,
404
+ } ;
405
+ return acc ;
406
+ } , { } ) ,
407
+ } ;
408
+ }
409
+ }
0 commit comments