Skip to content

Commit ad3e785

Browse files
pileroucdimascio
authored andcommitted
Allow to get the generated request AJV object in order to use it out of an OpenAPI and express usage (websocket...)
#683
1 parent 2069cf9 commit ad3e785

File tree

4 files changed

+114
-0
lines changed

4 files changed

+114
-0
lines changed

src/index.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
// export default openapiValidator;
1818
export const resolvers = res;
1919
export const middleware = openapiValidator;
20+
export const ajv = ajvInstances;
2021
export const error = {
2122
InternalServerError,
2223
UnsupportedMediaType,
@@ -43,3 +44,16 @@ function openapiValidator(options: OpenApiValidatorOpts) {
4344
}).load(),
4445
);
4546
}
47+
48+
function ajvInstances(options: OpenApiValidatorOpts) {
49+
const oav = new OpenApiValidator(options);
50+
exports.middleware._oav = oav;
51+
52+
return oav.installAjv(
53+
new OpenApiSpecLoader({
54+
apiDoc: cloneDeep(options.apiSpec),
55+
validateApiSpec: options.validateApiSpec,
56+
$refParser: options.$refParser,
57+
}).load(),
58+
);
59+
}

src/middlewares/openapi.request.validator.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ export class RequestValidator {
227227
}
228228
}
229229
}
230+
231+
public getAJV () : Ajv {
232+
return this.ajv;
233+
}
230234
}
231235

232236
class Validator {

src/openapi.validator.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { OperationHandlerOptions } from './framework/types';
2020
import { defaultSerDes } from './framework/base.serdes';
2121
import { SchemaPreprocessor } from './middlewares/parsers/schema.preprocessor';
2222
import { AjvOptions } from './framework/ajv/options';
23+
import { Ajv } from 'ajv';
2324

2425
export {
2526
OpenApiValidatorOpts,
@@ -90,6 +91,27 @@ export class OpenApiValidator {
9091
this.ajvOpts = new AjvOptions(options);
9192
}
9293

94+
installAjv(spec: Promise<Spec>): Promise<Ajv> {
95+
return spec
96+
.then((spec) => {
97+
const apiDoc = spec.apiDoc;
98+
const ajvOpts = this.ajvOpts.preprocessor;
99+
const resOpts = this.options.validateResponses as ValidateRequestOpts;
100+
const sp = new SchemaPreprocessor(
101+
apiDoc,
102+
ajvOpts,
103+
resOpts,
104+
).preProcess();
105+
/*return {
106+
context: new OpenApiContext(spec, this.options.ignorePaths, this.options.ignoreUndocumented),
107+
responseApiDoc: sp.apiDocRes,
108+
error: null,
109+
};*/
110+
return new middlewares.RequestValidator(apiDoc, this.ajvOpts.request).getAJV();
111+
});
112+
}
113+
114+
93115
installMiddleware(spec: Promise<Spec>): OpenApiRequestHandler[] {
94116
const middlewares: OpenApiRequestHandler[] = [];
95117
const pContext = spec

test/ajv.return.spec.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import * as path from 'path';
2+
import { expect } from 'chai';
3+
4+
import { date, dateTime } from '../src/framework/base.serdes';
5+
import * as OpenApiValidator from '../src';
6+
import { Ajv } from 'ajv';
7+
8+
const apiSpecPath = path.join('test', 'resources', 'serdes.yaml');
9+
10+
class ObjectID {
11+
id: string;
12+
13+
constructor(id: string = "5fdefd13a6640bb5fb5fa925") {
14+
this.id = id;
15+
}
16+
17+
toString() {
18+
return this.id;
19+
}
20+
}
21+
22+
describe('ajv.return', () => {
23+
let ajv : Ajv = null;
24+
25+
before(async () => {
26+
ajv = await OpenApiValidator.ajv({
27+
apiSpec: apiSpecPath,
28+
validateRequests: {
29+
coerceTypes: true
30+
},
31+
validateResponses: {
32+
coerceTypes: true
33+
},
34+
serDes: [
35+
date,
36+
dateTime,
37+
{
38+
format: "mongo-objectid",
39+
deserialize: (s) => new ObjectID(s),
40+
serialize: (o) => o.toString(),
41+
},
42+
],
43+
unknownFormats: ['string-list'],
44+
});
45+
});
46+
47+
it('should control BAD id format and throw an error', async () => {
48+
class ReqClass {
49+
id: string|ObjectID
50+
}
51+
52+
const req : ReqClass = {
53+
id : '507f191e810c19729de860ea',
54+
}
55+
56+
ajv.validate(
57+
{
58+
type: 'object',
59+
properties: {
60+
id: {
61+
$ref: '#/components/schemas/ObjectId',
62+
},
63+
},
64+
required: ['token'],
65+
additionalProperties: false,
66+
},
67+
req
68+
);
69+
expect(req.id instanceof ObjectID).to.be.true;
70+
});
71+
});
72+
73+
74+

0 commit comments

Comments
 (0)