Skip to content

Commit

Permalink
Allow to get the generated request AJV object in order to use it out …
Browse files Browse the repository at this point in the history
…of an OpenAPI and express usage (websocket...)

#683
  • Loading branch information
pilerou authored and cdimascio committed Dec 24, 2021
1 parent 2069cf9 commit ad3e785
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
// export default openapiValidator;
export const resolvers = res;
export const middleware = openapiValidator;
export const ajv = ajvInstances;
export const error = {
InternalServerError,
UnsupportedMediaType,
Expand All @@ -43,3 +44,16 @@ function openapiValidator(options: OpenApiValidatorOpts) {
}).load(),
);
}

function ajvInstances(options: OpenApiValidatorOpts) {
const oav = new OpenApiValidator(options);
exports.middleware._oav = oav;

return oav.installAjv(
new OpenApiSpecLoader({
apiDoc: cloneDeep(options.apiSpec),
validateApiSpec: options.validateApiSpec,
$refParser: options.$refParser,
}).load(),
);
}
4 changes: 4 additions & 0 deletions src/middlewares/openapi.request.validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ export class RequestValidator {
}
}
}

public getAJV () : Ajv {
return this.ajv;
}
}

class Validator {
Expand Down
22 changes: 22 additions & 0 deletions src/openapi.validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { OperationHandlerOptions } from './framework/types';
import { defaultSerDes } from './framework/base.serdes';
import { SchemaPreprocessor } from './middlewares/parsers/schema.preprocessor';
import { AjvOptions } from './framework/ajv/options';
import { Ajv } from 'ajv';

export {
OpenApiValidatorOpts,
Expand Down Expand Up @@ -90,6 +91,27 @@ export class OpenApiValidator {
this.ajvOpts = new AjvOptions(options);
}

installAjv(spec: Promise<Spec>): Promise<Ajv> {
return spec
.then((spec) => {
const apiDoc = spec.apiDoc;
const ajvOpts = this.ajvOpts.preprocessor;
const resOpts = this.options.validateResponses as ValidateRequestOpts;
const sp = new SchemaPreprocessor(
apiDoc,
ajvOpts,
resOpts,
).preProcess();
/*return {
context: new OpenApiContext(spec, this.options.ignorePaths, this.options.ignoreUndocumented),
responseApiDoc: sp.apiDocRes,
error: null,
};*/
return new middlewares.RequestValidator(apiDoc, this.ajvOpts.request).getAJV();
});
}


installMiddleware(spec: Promise<Spec>): OpenApiRequestHandler[] {
const middlewares: OpenApiRequestHandler[] = [];
const pContext = spec
Expand Down
74 changes: 74 additions & 0 deletions test/ajv.return.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import * as path from 'path';
import { expect } from 'chai';

import { date, dateTime } from '../src/framework/base.serdes';
import * as OpenApiValidator from '../src';
import { Ajv } from 'ajv';

const apiSpecPath = path.join('test', 'resources', 'serdes.yaml');

class ObjectID {
id: string;

constructor(id: string = "5fdefd13a6640bb5fb5fa925") {
this.id = id;
}

toString() {
return this.id;
}
}

describe('ajv.return', () => {
let ajv : Ajv = null;

before(async () => {
ajv = await OpenApiValidator.ajv({
apiSpec: apiSpecPath,
validateRequests: {
coerceTypes: true
},
validateResponses: {
coerceTypes: true
},
serDes: [
date,
dateTime,
{
format: "mongo-objectid",
deserialize: (s) => new ObjectID(s),
serialize: (o) => o.toString(),
},
],
unknownFormats: ['string-list'],
});
});

it('should control BAD id format and throw an error', async () => {
class ReqClass {
id: string|ObjectID
}

const req : ReqClass = {
id : '507f191e810c19729de860ea',
}

ajv.validate(
{
type: 'object',
properties: {
id: {
$ref: '#/components/schemas/ObjectId',
},
},
required: ['token'],
additionalProperties: false,
},
req
);
expect(req.id instanceof ObjectID).to.be.true;
});
});



0 comments on commit ad3e785

Please sign in to comment.